Merge from gnus--rel--5.10
[emacs.git] / src / macterm.c
blob1efa2667f15565ec1f0aaab6966aaa26e916f468
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 CGFloat 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 CGFloat 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, mac_rect_make (f, 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 CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
527 CGRect dest_rect = mac_rect_make (f, 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 mac_rect_make (f, 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 Window w;
639 unsigned int width, height;
640 unsigned int depth;
642 Pixmap pixmap;
643 Rect r;
644 QDErr err;
646 #ifdef MAC_OS8
647 SetPortWindowPort (w);
648 #endif
649 SetRect (&r, 0, 0, width, height);
650 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
651 if (depth == 1)
652 #endif
653 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
654 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
655 else
656 /* CreateCGImageFromPixMaps requires ARGB format. */
657 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
658 #endif
659 if (err != noErr)
660 return NULL;
661 return pixmap;
665 Pixmap
666 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
667 Display *display;
668 Window w;
669 char *data;
670 unsigned int width, height;
671 unsigned long fg, bg;
672 unsigned int depth;
674 Pixmap pixmap;
675 BitMap bitmap;
676 CGrafPtr old_port;
677 GDHandle old_gdh;
678 static GC gc = NULL;
680 if (gc == NULL)
681 gc = XCreateGC (display, w, 0, NULL);
683 pixmap = XCreatePixmap (display, w, width, height, depth);
684 if (pixmap == NULL)
685 return NULL;
687 GetGWorld (&old_port, &old_gdh);
688 SetGWorld (pixmap, NULL);
689 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
690 XSetForeground (display, gc, fg);
691 XSetBackground (display, gc, bg);
692 RGBForeColor (GC_FORE_COLOR (gc));
693 RGBBackColor (GC_BACK_COLOR (gc));
694 LockPixels (GetGWorldPixMap (pixmap));
695 #if TARGET_API_MAC_CARBON
696 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
697 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
698 #else /* not TARGET_API_MAC_CARBON */
699 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
700 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
701 #endif /* not TARGET_API_MAC_CARBON */
702 UnlockPixels (GetGWorldPixMap (pixmap));
703 SetGWorld (old_port, old_gdh);
704 mac_free_bitmap (&bitmap);
706 return pixmap;
710 void
711 XFreePixmap (display, pixmap)
712 Display *display;
713 Pixmap pixmap;
715 DisposeGWorld (pixmap);
719 /* Mac replacement for XFillRectangle. */
721 static void
722 mac_fill_rectangle (f, gc, x, y, width, height)
723 struct frame *f;
724 GC gc;
725 int x, y;
726 unsigned int width, height;
728 #if USE_CG_DRAWING
729 CGContextRef context;
731 context = mac_begin_cg_clip (f, gc);
732 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
733 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
734 mac_end_cg_clip (f);
735 #else
736 Rect r;
738 mac_begin_clip (f, gc);
739 RGBForeColor (GC_FORE_COLOR (gc));
740 SetRect (&r, x, y, x + width, y + height);
741 PaintRect (&r); /* using foreground color of gc */
742 mac_end_clip (f, gc);
743 #endif
747 /* Mac replacement for XDrawRectangle: dest is a window. */
749 static void
750 mac_draw_rectangle (f, gc, x, y, width, height)
751 struct frame *f;
752 GC gc;
753 int x, y;
754 unsigned int width, height;
756 #if USE_CG_DRAWING
757 CGContextRef context;
759 context = mac_begin_cg_clip (f, gc);
760 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
761 CGContextStrokeRect (context,
762 CGRectMake (x + 0.5f, y + 0.5f, width, height));
763 mac_end_cg_clip (f);
764 #else
765 Rect r;
767 mac_begin_clip (f, gc);
768 RGBForeColor (GC_FORE_COLOR (gc));
769 SetRect (&r, x, y, x + width + 1, y + height + 1);
770 FrameRect (&r); /* using foreground color of gc */
771 mac_end_clip (f, gc);
772 #endif
776 static void
777 mac_invert_rectangle (f, x, y, width, height)
778 struct frame *f;
779 int x, y;
780 unsigned int width, height;
782 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
783 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
784 if (CGContextSetBlendMode != NULL)
785 #endif
787 CGContextRef context;
789 context = mac_begin_cg_clip (f, NULL);
790 CGContextSetRGBFillColor (context, 1.0f, 1.0f, 1.0f, 1.0f);
791 CGContextSetBlendMode (context, kCGBlendModeDifference);
792 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
793 mac_end_cg_clip (f);
795 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
796 else /* CGContextSetBlendMode == NULL */
797 #endif
798 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
799 #if !USE_CG_DRAWING || MAC_OS_X_VERSION_MAX_ALLOWED < 1040 || (MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020)
801 Rect r;
803 mac_begin_clip (f, NULL);
804 SetRect (&r, x, y, x + width, y + height);
805 InvertRect (&r);
806 mac_end_clip (f, NULL);
808 #endif
812 #if USE_ATSUI
813 static OSStatus
814 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
815 ConstUniCharArrayPtr text;
816 UniCharCount text_length;
817 ATSUStyle style;
818 ATSUTextLayout *text_layout;
820 OSStatus err;
821 static ATSUTextLayout saved_text_layout = NULL;
823 if (saved_text_layout == NULL)
825 static const UniCharCount lengths[] = {kATSUToTextEnd};
826 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
827 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
828 static ATSLineLayoutOptions line_layout =
829 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
830 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
831 | kATSLineUseQDRendering
832 #else
833 kATSLineIsDisplayOnly | kATSLineFractDisable
834 #endif
836 static const ATSUAttributeValuePtr values[] = {&line_layout};
838 err = ATSUCreateTextLayoutWithTextPtr (text,
839 kATSUFromTextBeginning,
840 kATSUToTextEnd,
841 text_length,
842 1, lengths, &style,
843 &saved_text_layout);
844 if (err == noErr)
845 err = ATSUSetLayoutControls (saved_text_layout,
846 sizeof (tags) / sizeof (tags[0]),
847 tags, sizes, values);
848 if (err == noErr)
849 err = ATSUSetTransientFontMatching (saved_text_layout, true);
851 else
853 err = ATSUSetRunStyle (saved_text_layout, style,
854 kATSUFromTextBeginning, kATSUToTextEnd);
855 if (err == noErr)
856 err = ATSUSetTextPointerLocation (saved_text_layout, text,
857 kATSUFromTextBeginning,
858 kATSUToTextEnd,
859 text_length);
862 if (err == noErr)
863 *text_layout = saved_text_layout;
864 return err;
868 static void
869 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
870 overstrike_p, bytes_per_char)
871 struct frame *f;
872 GC gc;
873 int x, y;
874 char *buf;
875 int nchars, bg_width, overstrike_p, bytes_per_char;
877 OSStatus err;
878 ATSUTextLayout text_layout;
880 xassert (bytes_per_char == 2);
882 #ifndef WORDS_BIG_ENDIAN
884 int i;
885 UniChar *text = (UniChar *)buf;
887 for (i = 0; i < nchars; i++)
888 text[i] = EndianU16_BtoN (text[i]);
890 #endif
891 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
892 nchars,
893 GC_FONT (gc)->mac_style,
894 &text_layout);
895 if (err != noErr)
896 return;
897 #ifdef MAC_OSX
898 if (!mac_use_core_graphics)
900 #endif
901 mac_begin_clip (f, gc);
902 RGBForeColor (GC_FORE_COLOR (gc));
903 if (bg_width)
905 Rect r;
907 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
908 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
909 RGBBackColor (GC_BACK_COLOR (gc));
910 EraseRect (&r);
911 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
913 MoveTo (x, y);
914 ATSUDrawText (text_layout,
915 kATSUFromTextBeginning, kATSUToTextEnd,
916 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
917 if (overstrike_p)
919 MoveTo (x + 1, y);
920 ATSUDrawText (text_layout,
921 kATSUFromTextBeginning, kATSUToTextEnd,
922 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
924 mac_end_clip (f, gc);
925 #ifdef MAC_OSX
927 else
929 static CGContextRef context;
930 CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
931 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
932 static const ByteCount sizes[] = {sizeof (CGContextRef)};
933 static const ATSUAttributeValuePtr values[] = {&context};
935 #if USE_CG_DRAWING
936 context = mac_begin_cg_clip (f, gc);
937 #else
938 CGrafPtr port;
940 GetPort (&port);
941 QDBeginCGContext (port, &context);
942 if (gc->n_clip_rects || bg_width)
944 CGContextTranslateCTM (context, 0, port_height);
945 CGContextScaleCTM (context, 1, -1);
946 if (gc->n_clip_rects)
947 CGContextClipToRects (context, gc->clip_rects,
948 gc->n_clip_rects);
949 #endif
950 if (bg_width)
952 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
953 CGContextFillRect (context,
954 mac_rect_make (f,
955 x, y - FONT_BASE (GC_FONT (gc)),
956 bg_width,
957 FONT_HEIGHT (GC_FONT (gc))));
959 CGContextScaleCTM (context, 1, -1);
960 CGContextTranslateCTM (context, 0, -port_height);
961 #if !USE_CG_DRAWING
963 #endif
964 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
965 err = ATSUSetLayoutControls (text_layout,
966 sizeof (tags) / sizeof (tags[0]),
967 tags, sizes, values);
968 if (err == noErr)
970 ATSUDrawText (text_layout,
971 kATSUFromTextBeginning, kATSUToTextEnd,
972 Long2Fix (x), Long2Fix (port_height - y));
973 if (overstrike_p)
974 ATSUDrawText (text_layout,
975 kATSUFromTextBeginning, kATSUToTextEnd,
976 Long2Fix (x + 1), Long2Fix (port_height - y));
978 #if USE_CG_DRAWING
979 mac_end_cg_clip (f);
980 context = NULL;
981 #else
982 CGContextSynchronize (context);
983 QDEndCGContext (port, &context);
984 #endif
985 #if 0
986 /* This doesn't work on Mac OS X 10.1. */
987 ATSUClearLayoutControls (text_layout,
988 sizeof (tags) / sizeof (tags[0]), tags);
989 #else
990 ATSUSetLayoutControls (text_layout,
991 sizeof (tags) / sizeof (tags[0]),
992 tags, sizes, values);
993 #endif
995 #endif /* MAC_OSX */
997 #endif /* USE_ATSUI */
1000 static void
1001 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1002 overstrike_p, bytes_per_char)
1003 struct frame *f;
1004 GC gc;
1005 int x, y;
1006 char *buf;
1007 int nchars, bg_width, overstrike_p, bytes_per_char;
1009 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1010 UInt32 savedFlags;
1011 #endif
1013 mac_begin_clip (f, gc);
1014 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1015 if (mac_use_core_graphics)
1016 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1017 #endif
1018 RGBForeColor (GC_FORE_COLOR (gc));
1019 #ifdef MAC_OS8
1020 if (bg_width)
1022 RGBBackColor (GC_BACK_COLOR (gc));
1023 TextMode (srcCopy);
1025 else
1026 TextMode (srcOr);
1027 #else
1028 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1029 because:
1030 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1031 into an offscreen graphics world first. So performance gain
1032 cannot be expected.)
1033 - It lowers rendering quality.
1034 - Some fonts leave garbage on cursor movement. */
1035 if (bg_width)
1037 Rect r;
1039 RGBBackColor (GC_BACK_COLOR (gc));
1040 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1041 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1042 EraseRect (&r);
1044 TextMode (srcOr);
1045 #endif
1046 TextFont (GC_FONT (gc)->mac_fontnum);
1047 TextSize (GC_FONT (gc)->mac_fontsize);
1048 TextFace (GC_FONT (gc)->mac_fontface);
1049 MoveTo (x, y);
1050 DrawText (buf, 0, nchars * bytes_per_char);
1051 if (overstrike_p)
1053 TextMode (srcOr);
1054 MoveTo (x + 1, y);
1055 DrawText (buf, 0, nchars * bytes_per_char);
1057 if (bg_width)
1058 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1059 mac_end_clip (f, gc);
1061 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1062 if (mac_use_core_graphics)
1063 SwapQDTextFlags(savedFlags);
1064 #endif
1068 static INLINE void
1069 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1070 overstrike_p, bytes_per_char)
1071 struct frame *f;
1072 GC gc;
1073 int x, y;
1074 char *buf;
1075 int nchars, bg_width, overstrike_p, bytes_per_char;
1077 #if USE_ATSUI
1078 if (GC_FONT (gc)->mac_style)
1079 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1080 overstrike_p, bytes_per_char);
1081 else
1082 #endif /* USE_ATSUI */
1083 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1084 overstrike_p, bytes_per_char);
1088 /* Mac replacement for XDrawImageString. */
1090 static void
1091 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1092 struct frame *f;
1093 GC gc;
1094 int x, y;
1095 char *buf;
1096 int nchars, bg_width, overstrike_p;
1098 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1099 overstrike_p, 1);
1103 /* Mac replacement for XDrawImageString16. */
1105 static void
1106 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1107 struct frame *f;
1108 GC gc;
1109 int x, y;
1110 XChar2b *buf;
1111 int nchars, bg_width, overstrike_p;
1113 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1114 overstrike_p, 2);
1118 /* Mac replacement for XQueryTextExtents, but takes a character. If
1119 STYLE is NULL, measurement is done by QuickDraw Text routines for
1120 the font of the current graphics port. If CG_GLYPH is not NULL,
1121 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1123 static OSStatus
1124 mac_query_char_extents (style, c,
1125 font_ascent_return, font_descent_return,
1126 overall_return, cg_glyph)
1127 #if USE_ATSUI
1128 ATSUStyle style;
1129 #else
1130 void *style;
1131 #endif
1132 int c;
1133 int *font_ascent_return, *font_descent_return;
1134 XCharStruct *overall_return;
1135 #if USE_CG_TEXT_DRAWING
1136 CGGlyph *cg_glyph;
1137 #else
1138 void *cg_glyph;
1139 #endif
1141 OSStatus err = noErr;
1142 int width;
1143 Rect char_bounds;
1145 #if USE_ATSUI
1146 if (style)
1148 ATSUTextLayout text_layout;
1149 UniChar ch = c;
1151 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1152 if (err == noErr
1153 && (font_ascent_return || font_descent_return || overall_return))
1155 ATSTrapezoid glyph_bounds;
1157 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1158 kATSUFromTextBeginning, kATSUToTextEnd,
1159 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1160 kATSUseFractionalOrigins,
1161 #else
1162 kATSUseDeviceOrigins,
1163 #endif
1164 1, &glyph_bounds, NULL);
1165 if (err == noErr)
1167 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1168 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1170 width = Fix2Long (glyph_bounds.upperRight.x
1171 - glyph_bounds.upperLeft.x);
1172 if (font_ascent_return)
1173 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1174 if (font_descent_return)
1175 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1178 if (err == noErr && overall_return)
1180 err = ATSUMeasureTextImage (text_layout,
1181 kATSUFromTextBeginning, kATSUToTextEnd,
1182 0, 0, &char_bounds);
1183 if (err == noErr)
1184 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1185 #if USE_CG_TEXT_DRAWING
1186 if (err == noErr && cg_glyph)
1188 OSStatus err1;
1189 ATSUGlyphInfoArray glyph_info_array;
1190 ByteCount count = sizeof (ATSUGlyphInfoArray);
1192 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1193 kATSUToTextEnd, NULL, NULL, NULL);
1194 if (err1 == noErr)
1195 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1196 kATSUToTextEnd, &count,
1197 &glyph_info_array);
1198 if (err1 == noErr
1199 /* Make sure that we don't have to make layout
1200 adjustments. */
1201 && glyph_info_array.glyphs[0].deltaY == 0.0f
1202 && glyph_info_array.glyphs[0].idealX == 0.0f
1203 && glyph_info_array.glyphs[0].screenX == 0)
1205 xassert (glyph_info_array.glyphs[0].glyphID);
1206 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1208 else
1209 *cg_glyph = 0;
1211 #endif
1214 else
1215 #endif
1217 if (font_ascent_return || font_descent_return)
1219 FontInfo font_info;
1221 GetFontInfo (&font_info);
1222 if (font_ascent_return)
1223 *font_ascent_return = font_info.ascent;
1224 if (font_descent_return)
1225 *font_descent_return = font_info.descent;
1227 if (overall_return)
1229 char ch = c;
1231 width = CharWidth (ch);
1232 QDTextBounds (1, &ch, &char_bounds);
1233 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1237 return err;
1241 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1243 static int
1244 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1245 XFontStruct *font_struct;
1246 XChar2b *string;
1247 int nchars;
1248 XCharStruct *overall_return;
1250 int i;
1251 short width = 0, lbearing = 0, rbearing = 0;
1252 XCharStruct *pcm;
1254 for (i = 0; i < nchars; i++)
1256 pcm = mac_per_char_metric (font_struct, string, 0);
1257 if (pcm == NULL)
1258 width += FONT_WIDTH (font_struct);
1259 else
1261 lbearing = min (lbearing, width + pcm->lbearing);
1262 rbearing = max (rbearing, width + pcm->rbearing);
1263 width += pcm->width;
1265 string++;
1268 overall_return->lbearing = lbearing;
1269 overall_return->rbearing = rbearing;
1270 overall_return->width = width;
1272 /* What's the meaning of the return value of XTextExtents16? */
1276 #if USE_CG_TEXT_DRAWING
1277 static int cg_text_anti_aliasing_threshold = 8;
1279 static void
1280 init_cg_text_anti_aliasing_threshold ()
1282 int threshold;
1283 Boolean valid_p;
1285 threshold =
1286 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1287 kCFPreferencesCurrentApplication,
1288 &valid_p);
1289 if (valid_p)
1290 cg_text_anti_aliasing_threshold = threshold;
1293 static int
1294 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1295 struct frame *f;
1296 GC gc;
1297 int x, y;
1298 XChar2b *buf;
1299 int nchars, bg_width, overstrike_p;
1301 CGFloat port_height, gx, gy;
1302 int i;
1303 CGContextRef context;
1304 CGGlyph *glyphs;
1305 CGSize *advances;
1307 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1308 return 0;
1310 port_height = FRAME_PIXEL_HEIGHT (f);
1311 gx = x;
1312 gy = port_height - y;
1313 glyphs = (CGGlyph *)buf;
1314 advances = alloca (sizeof (CGSize) * nchars);
1315 if (advances == NULL)
1316 return 0;
1317 for (i = 0; i < nchars; i++)
1319 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1321 advances[i].width = pcm->width;
1322 advances[i].height = 0;
1323 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1324 buf++;
1327 #if USE_CG_DRAWING
1328 context = mac_begin_cg_clip (f, gc);
1329 #else
1330 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1331 if (gc->n_clip_rects || bg_width)
1333 CGContextTranslateCTM (context, 0, port_height);
1334 CGContextScaleCTM (context, 1, -1);
1335 if (gc->n_clip_rects)
1336 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1337 #endif
1338 if (bg_width)
1340 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1341 CGContextFillRect
1342 (context,
1343 mac_rect_make (f, gx, y - FONT_BASE (GC_FONT (gc)),
1344 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1346 CGContextScaleCTM (context, 1, -1);
1347 CGContextTranslateCTM (context, 0, -port_height);
1348 #if !USE_CG_DRAWING
1350 #endif
1351 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1352 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1353 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1354 CGContextSetTextMatrix (context, CGAffineTransformIdentity);
1355 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1356 CGContextSetShouldAntialias (context, false);
1357 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1358 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1359 if (CGContextShowGlyphsWithAdvances != NULL)
1360 #endif
1362 CGContextSetTextPosition (context, gx, gy);
1363 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1364 if (overstrike_p)
1366 CGContextSetTextPosition (context, gx + 1.0f, gy);
1367 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1370 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1371 else /* CGContextShowGlyphsWithAdvances == NULL */
1372 #endif
1373 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1374 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1376 for (i = 0; i < nchars; i++)
1378 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1379 if (overstrike_p)
1380 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1381 gx += advances[i].width;
1384 #endif
1385 #if USE_CG_DRAWING
1386 mac_end_cg_clip (f);
1387 #else
1388 CGContextSynchronize (context);
1389 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1390 #endif
1392 return 1;
1394 #endif
1397 #if !USE_CG_DRAWING
1398 /* Mac replacement for XCopyArea: dest must be window. */
1400 static void
1401 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1402 Pixmap src;
1403 struct frame *f;
1404 GC gc;
1405 int src_x, src_y;
1406 unsigned int width, height;
1407 int dest_x, dest_y;
1409 Rect src_r, dest_r;
1411 mac_begin_clip (f, gc);
1413 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1414 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1416 ForeColor (blackColor);
1417 BackColor (whiteColor);
1419 LockPixels (GetGWorldPixMap (src));
1420 #if TARGET_API_MAC_CARBON
1422 CGrafPtr port;
1424 GetPort (&port);
1425 LockPortBits (port);
1426 CopyBits (GetPortBitMapForCopyBits (src),
1427 GetPortBitMapForCopyBits (port),
1428 &src_r, &dest_r, srcCopy, 0);
1429 UnlockPortBits (port);
1431 #else /* not TARGET_API_MAC_CARBON */
1432 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1433 &src_r, &dest_r, srcCopy, 0);
1434 #endif /* not TARGET_API_MAC_CARBON */
1435 UnlockPixels (GetGWorldPixMap (src));
1437 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1439 mac_end_clip (f, gc);
1443 static void
1444 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1445 width, height, dest_x, dest_y)
1446 Pixmap src, mask;
1447 struct frame *f;
1448 GC gc;
1449 int src_x, src_y;
1450 unsigned int width, height;
1451 int dest_x, dest_y;
1453 Rect src_r, dest_r;
1455 mac_begin_clip (f, gc);
1457 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1458 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1460 ForeColor (blackColor);
1461 BackColor (whiteColor);
1463 LockPixels (GetGWorldPixMap (src));
1464 LockPixels (GetGWorldPixMap (mask));
1465 #if TARGET_API_MAC_CARBON
1467 CGrafPtr port;
1469 GetPort (&port);
1470 LockPortBits (port);
1471 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1472 GetPortBitMapForCopyBits (port),
1473 &src_r, &src_r, &dest_r);
1474 UnlockPortBits (port);
1476 #else /* not TARGET_API_MAC_CARBON */
1477 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1478 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1479 #endif /* not TARGET_API_MAC_CARBON */
1480 UnlockPixels (GetGWorldPixMap (mask));
1481 UnlockPixels (GetGWorldPixMap (src));
1483 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1485 mac_end_clip (f, gc);
1487 #endif /* !USE_CG_DRAWING */
1490 /* Mac replacement for XCopyArea: used only for scrolling. */
1492 #if TARGET_API_MAC_CARBON
1493 /* Defined in mactoolbox.c. */
1494 extern void mac_scroll_area P_ ((struct frame *, GC, int, int,
1495 unsigned int, unsigned int, int, int));
1496 #else /* not TARGET_API_MAC_CARBON */
1497 static void
1498 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1499 struct frame *f;
1500 GC gc;
1501 int src_x, src_y;
1502 unsigned int width, height;
1503 int dest_x, dest_y;
1505 Rect src_r, dest_r;
1506 WindowRef w = FRAME_MAC_WINDOW (f);
1508 mac_begin_clip (f, gc);
1510 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1511 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1513 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1514 color mapping in CopyBits. Otherwise, it will be slow. */
1515 ForeColor (blackColor);
1516 BackColor (whiteColor);
1517 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1519 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1521 mac_end_clip (f, gc);
1523 #endif /* not TARGET_API_MAC_CARBON */
1526 /* Mac replacement for XChangeGC. */
1528 static void
1529 XChangeGC (display, gc, mask, xgcv)
1530 Display *display;
1531 GC gc;
1532 unsigned long mask;
1533 XGCValues *xgcv;
1535 if (mask & GCForeground)
1536 XSetForeground (display, gc, xgcv->foreground);
1537 if (mask & GCBackground)
1538 XSetBackground (display, gc, xgcv->background);
1539 if (mask & GCFont)
1540 XSetFont (display, gc, xgcv->font);
1544 /* Mac replacement for XCreateGC. */
1547 XCreateGC (display, d, mask, xgcv)
1548 Display *display;
1549 void *d;
1550 unsigned long mask;
1551 XGCValues *xgcv;
1553 GC gc = xmalloc (sizeof (*gc));
1555 bzero (gc, sizeof (*gc));
1556 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1557 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1558 if (CGColorGetTypeID != NULL)
1559 #endif
1561 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1562 CGColorRetain (gc->cg_fore_color);
1563 CGColorRetain (gc->cg_back_color);
1565 #endif
1566 XChangeGC (display, gc, mask, xgcv);
1568 return gc;
1572 /* Used in xfaces.c. */
1574 void
1575 XFreeGC (display, gc)
1576 Display *display;
1577 GC gc;
1579 if (gc->clip_region)
1580 DisposeRgn (gc->clip_region);
1581 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1582 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1583 if (CGColorGetTypeID != NULL)
1584 #endif
1586 CGColorRelease (gc->cg_fore_color);
1587 CGColorRelease (gc->cg_back_color);
1589 #endif
1590 xfree (gc);
1594 /* Mac replacement for XGetGCValues. */
1596 static void
1597 XGetGCValues (display, gc, mask, xgcv)
1598 Display *display;
1599 GC gc;
1600 unsigned long mask;
1601 XGCValues *xgcv;
1603 if (mask & GCForeground)
1604 xgcv->foreground = gc->xgcv.foreground;
1605 if (mask & GCBackground)
1606 xgcv->background = gc->xgcv.background;
1607 if (mask & GCFont)
1608 xgcv->font = gc->xgcv.font;
1612 /* Mac replacement for XSetForeground. */
1614 void
1615 XSetForeground (display, gc, color)
1616 Display *display;
1617 GC gc;
1618 unsigned long color;
1620 if (gc->xgcv.foreground != color)
1622 gc->xgcv.foreground = color;
1623 gc->fore_color.red = RED16_FROM_ULONG (color);
1624 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1625 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1626 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1627 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1628 if (CGColorGetTypeID != NULL)
1629 #endif
1631 CGColorRelease (gc->cg_fore_color);
1632 if (color == 0)
1634 gc->cg_fore_color = mac_cg_color_black;
1635 CGColorRetain (gc->cg_fore_color);
1637 else
1639 CGFloat rgba[4];
1641 rgba[0] = gc->fore_color.red / 65535.0f;
1642 rgba[1] = gc->fore_color.green / 65535.0f;
1643 rgba[2] = gc->fore_color.blue / 65535.0f;
1644 rgba[3] = 1.0f;
1645 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1648 #endif
1653 /* Mac replacement for XSetBackground. */
1655 void
1656 XSetBackground (display, gc, color)
1657 Display *display;
1658 GC gc;
1659 unsigned long color;
1661 if (gc->xgcv.background != color)
1663 gc->xgcv.background = color;
1664 gc->back_color.red = RED16_FROM_ULONG (color);
1665 gc->back_color.green = GREEN16_FROM_ULONG (color);
1666 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1667 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1668 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1669 if (CGColorGetTypeID != NULL)
1670 #endif
1672 CGColorRelease (gc->cg_back_color);
1673 if (color == 0)
1675 gc->cg_back_color = mac_cg_color_black;
1676 CGColorRetain (gc->cg_back_color);
1678 else
1680 CGFloat rgba[4];
1682 rgba[0] = gc->back_color.red / 65535.0f;
1683 rgba[1] = gc->back_color.green / 65535.0f;
1684 rgba[2] = gc->back_color.blue / 65535.0f;
1685 rgba[3] = 1.0f;
1686 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1689 #endif
1694 /* Mac replacement for XSetFont. */
1696 static void
1697 XSetFont (display, gc, font)
1698 Display *display;
1699 GC gc;
1700 XFontStruct *font;
1702 gc->xgcv.font = font;
1706 /* Mac replacement for XSetClipRectangles. */
1708 static void
1709 mac_set_clip_rectangles (f, gc, rectangles, n)
1710 struct frame *f;
1711 GC gc;
1712 Rect *rectangles;
1713 int n;
1715 int i;
1717 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1719 gc->n_clip_rects = n;
1720 if (n > 0)
1722 if (gc->clip_region == NULL)
1723 gc->clip_region = NewRgn ();
1724 RectRgn (gc->clip_region, rectangles);
1725 if (n > 1)
1727 RgnHandle region = NewRgn ();
1729 for (i = 1; i < n; i++)
1731 RectRgn (region, rectangles + i);
1732 UnionRgn (gc->clip_region, region, gc->clip_region);
1734 DisposeRgn (region);
1737 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1738 for (i = 0; i < n; i++)
1740 Rect *rect = rectangles + i;
1742 gc->clip_rects[i] = mac_rect_make (f, rect->left, rect->top,
1743 rect->right - rect->left,
1744 rect->bottom - rect->top);
1746 #endif
1750 /* Mac replacement for XSetClipMask. */
1752 static INLINE void
1753 mac_reset_clip_rectangles (f, gc)
1754 struct frame *f;
1755 GC gc;
1757 gc->n_clip_rects = 0;
1760 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1761 Calls to XFlush should be unnecessary because the X output buffer
1762 is flushed automatically as needed by calls to XPending,
1763 XNextEvent, or XWindowEvent according to the XFlush man page.
1764 XTread_socket calls XPending. Removing XFlush improves
1765 performance. */
1767 #define XFlush(DISPLAY) (void) 0
1770 /***********************************************************************
1771 Starting and ending an update
1772 ***********************************************************************/
1774 /* Start an update of frame F. This function is installed as a hook
1775 for update_begin, i.e. it is called when update_begin is called.
1776 This function is called prior to calls to x_update_window_begin for
1777 each window being updated. */
1779 static void
1780 x_update_begin (f)
1781 struct frame *f;
1783 BLOCK_INPUT;
1784 mac_update_begin (f);
1785 UNBLOCK_INPUT;
1789 /* Start update of window W. Set the global variable updated_window
1790 to the window being updated and set output_cursor to the cursor
1791 position of W. */
1793 static void
1794 x_update_window_begin (w)
1795 struct window *w;
1797 struct frame *f = XFRAME (WINDOW_FRAME (w));
1798 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1800 updated_window = w;
1801 set_output_cursor (&w->cursor);
1803 BLOCK_INPUT;
1805 if (f == display_info->mouse_face_mouse_frame)
1807 /* Don't do highlighting for mouse motion during the update. */
1808 display_info->mouse_face_defer = 1;
1810 /* If F needs to be redrawn, simply forget about any prior mouse
1811 highlighting. */
1812 if (FRAME_GARBAGED_P (f))
1813 display_info->mouse_face_window = Qnil;
1815 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1816 their mouse_face_p flag set, which means that they are always
1817 unequal to rows in a desired matrix which never have that
1818 flag set. So, rows containing mouse-face glyphs are never
1819 scrolled, and we don't have to switch the mouse highlight off
1820 here to prevent it from being scrolled. */
1822 /* Can we tell that this update does not affect the window
1823 where the mouse highlight is? If so, no need to turn off.
1824 Likewise, don't do anything if the frame is garbaged;
1825 in that case, the frame's current matrix that we would use
1826 is all wrong, and we will redisplay that line anyway. */
1827 if (!NILP (display_info->mouse_face_window)
1828 && w == XWINDOW (display_info->mouse_face_window))
1830 int i;
1832 for (i = 0; i < w->desired_matrix->nrows; ++i)
1833 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1834 break;
1836 if (i < w->desired_matrix->nrows)
1837 clear_mouse_face (display_info);
1839 #endif /* 0 */
1842 UNBLOCK_INPUT;
1846 /* Draw a vertical window border from (x,y0) to (x,y1) */
1848 static void
1849 mac_draw_vertical_window_border (w, x, y0, y1)
1850 struct window *w;
1851 int x, y0, y1;
1853 struct frame *f = XFRAME (WINDOW_FRAME (w));
1854 struct face *face;
1856 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1857 if (face)
1858 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1859 face->foreground);
1861 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1864 /* End update of window W (which is equal to updated_window).
1866 Draw vertical borders between horizontally adjacent windows, and
1867 display W's cursor if CURSOR_ON_P is non-zero.
1869 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1870 glyphs in mouse-face were overwritten. In that case we have to
1871 make sure that the mouse-highlight is properly redrawn.
1873 W may be a menu bar pseudo-window in case we don't have X toolkit
1874 support. Such windows don't have a cursor, so don't display it
1875 here. */
1877 static void
1878 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1879 struct window *w;
1880 int cursor_on_p, mouse_face_overwritten_p;
1882 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1884 if (!w->pseudo_window_p)
1886 BLOCK_INPUT;
1888 if (cursor_on_p)
1889 display_and_set_cursor (w, 1, output_cursor.hpos,
1890 output_cursor.vpos,
1891 output_cursor.x, output_cursor.y);
1893 if (draw_window_fringes (w, 1))
1894 x_draw_vertical_border (w);
1896 UNBLOCK_INPUT;
1899 /* If a row with mouse-face was overwritten, arrange for
1900 XTframe_up_to_date to redisplay the mouse highlight. */
1901 if (mouse_face_overwritten_p)
1903 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1904 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1905 dpyinfo->mouse_face_window = Qnil;
1908 updated_window = NULL;
1912 /* End update of frame F. This function is installed as a hook in
1913 update_end. */
1915 static void
1916 x_update_end (f)
1917 struct frame *f;
1919 /* Mouse highlight may be displayed again. */
1920 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1922 BLOCK_INPUT;
1923 mac_update_end (f);
1924 XFlush (FRAME_MAC_DISPLAY (f));
1925 UNBLOCK_INPUT;
1929 /* This function is called from various places in xdisp.c whenever a
1930 complete update has been performed. The global variable
1931 updated_window is not available here. */
1933 static void
1934 XTframe_up_to_date (f)
1935 struct frame *f;
1937 if (FRAME_MAC_P (f))
1939 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1941 if (dpyinfo->mouse_face_deferred_gc
1942 || f == dpyinfo->mouse_face_mouse_frame)
1944 BLOCK_INPUT;
1945 if (dpyinfo->mouse_face_mouse_frame)
1946 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1947 dpyinfo->mouse_face_mouse_x,
1948 dpyinfo->mouse_face_mouse_y);
1949 dpyinfo->mouse_face_deferred_gc = 0;
1950 UNBLOCK_INPUT;
1953 mac_frame_up_to_date (f);
1958 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1959 arrow bitmaps, or clear the fringes if no bitmaps are required
1960 before DESIRED_ROW is made current. The window being updated is
1961 found in updated_window. This function is called from
1962 update_window_line only if it is known that there are differences
1963 between bitmaps to be drawn between current row and DESIRED_ROW. */
1965 static void
1966 x_after_update_window_line (desired_row)
1967 struct glyph_row *desired_row;
1969 struct window *w = updated_window;
1970 struct frame *f;
1971 int width, height;
1973 xassert (w);
1975 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1976 desired_row->redraw_fringe_bitmaps_p = 1;
1978 /* When a window has disappeared, make sure that no rest of
1979 full-width rows stays visible in the internal border. Could
1980 check here if updated_window is the leftmost/rightmost window,
1981 but I guess it's not worth doing since vertically split windows
1982 are almost never used, internal border is rarely set, and the
1983 overhead is very small. */
1984 if (windows_or_buffers_changed
1985 && desired_row->full_width_p
1986 && (f = XFRAME (w->frame),
1987 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1988 width != 0)
1989 && (height = desired_row->visible_height,
1990 height > 0))
1992 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1994 /* Internal border is drawn below the tool bar. */
1995 if (WINDOWP (f->tool_bar_window)
1996 && w == XWINDOW (f->tool_bar_window))
1997 y -= width;
1999 BLOCK_INPUT;
2000 mac_clear_area (f, 0, y, width, height);
2001 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2002 UNBLOCK_INPUT;
2007 /* Draw the bitmap WHICH in one of the left or right fringes of
2008 window W. ROW is the glyph row for which to display the bitmap; it
2009 determines the vertical position at which the bitmap has to be
2010 drawn. */
2012 static void
2013 x_draw_fringe_bitmap (w, row, p)
2014 struct window *w;
2015 struct glyph_row *row;
2016 struct draw_fringe_bitmap_params *p;
2018 struct frame *f = XFRAME (WINDOW_FRAME (w));
2019 Display *display = FRAME_MAC_DISPLAY (f);
2020 struct face *face = p->face;
2021 int rowY;
2022 int overlay_p = p->overlay_p;
2024 #ifdef MAC_OSX
2025 if (!overlay_p)
2027 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2029 #if 0 /* MAC_TODO: stipple */
2030 /* In case the same realized face is used for fringes and
2031 for something displayed in the text (e.g. face `region' on
2032 mono-displays, the fill style may have been changed to
2033 FillSolid in x_draw_glyph_string_background. */
2034 if (face->stipple)
2035 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2036 else
2037 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2038 #endif
2040 /* If the fringe is adjacent to the left (right) scroll bar of a
2041 leftmost (rightmost, respectively) window, then extend its
2042 background to the gap between the fringe and the bar. */
2043 if ((WINDOW_LEFTMOST_P (w)
2044 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2045 || (WINDOW_RIGHTMOST_P (w)
2046 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2048 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2050 if (sb_width > 0)
2052 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2053 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2054 * FRAME_COLUMN_WIDTH (f));
2056 if (bx < 0
2057 && (left + width == p->x
2058 || p->x + p->wd == left))
2060 /* Bitmap fills the fringe and we need background
2061 extension. */
2062 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2064 bx = p->x;
2065 nx = p->wd;
2066 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2067 row->y));
2068 ny = row->visible_height;
2071 if (bx >= 0)
2073 if (left + width == bx)
2075 bx = left + sb_width;
2076 nx += width - sb_width;
2078 else if (bx + nx == left)
2079 nx += width - sb_width;
2084 if (bx >= 0)
2086 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2087 /* The fringe background has already been filled. */
2088 overlay_p = 1;
2091 #if 0 /* MAC_TODO: stipple */
2092 if (!face->stipple)
2093 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2094 #endif
2096 #endif /* MAC_OSX */
2098 /* Must clip because of partially visible lines. */
2099 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2100 if (p->y < rowY)
2102 /* Adjust position of "bottom aligned" bitmap on partially
2103 visible last row. */
2104 int oldY = row->y;
2105 int oldVH = row->visible_height;
2106 row->visible_height = p->h;
2107 row->y -= rowY - p->y;
2108 x_clip_to_row (w, row, -1, face->gc);
2109 row->y = oldY;
2110 row->visible_height = oldVH;
2112 else
2113 x_clip_to_row (w, row, -1, face->gc);
2115 #ifndef MAC_OSX
2116 if (p->bx >= 0 && !p->overlay_p)
2118 #if 0 /* MAC_TODO: stipple */
2119 /* In case the same realized face is used for fringes and
2120 for something displayed in the text (e.g. face `region' on
2121 mono-displays, the fill style may have been changed to
2122 FillSolid in x_draw_glyph_string_background. */
2123 if (face->stipple)
2124 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2125 else
2126 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2127 #endif
2129 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2131 #if 0 /* MAC_TODO: stipple */
2132 if (!face->stipple)
2133 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2134 #endif
2136 #endif /* !MAC_OSX */
2138 if (p->which
2139 #if USE_CG_DRAWING
2140 && p->which < max_fringe_bmp
2141 #endif
2144 XGCValues gcv;
2146 XGetGCValues (display, face->gc, GCForeground, &gcv);
2147 XSetForeground (display, face->gc,
2148 (p->cursor_p
2149 ? (p->overlay_p ? face->background
2150 : f->output_data.mac->cursor_pixel)
2151 : face->foreground));
2152 #if USE_CG_DRAWING
2153 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2154 p->wd, p->h, p->x, p->y, overlay_p);
2155 #else
2156 mac_draw_bitmap (f, face->gc, p->x, p->y,
2157 p->wd, p->h, p->bits + p->dh, overlay_p);
2158 #endif
2159 XSetForeground (display, face->gc, gcv.foreground);
2162 mac_reset_clip_rectangles (f, face->gc);
2165 #if USE_CG_DRAWING
2166 static void
2167 mac_define_fringe_bitmap (which, bits, h, wd)
2168 int which;
2169 unsigned short *bits;
2170 int h, wd;
2172 int i;
2173 CGDataProviderRef provider;
2175 if (which >= max_fringe_bmp)
2177 i = max_fringe_bmp;
2178 max_fringe_bmp = which + 20;
2179 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2180 while (i < max_fringe_bmp)
2181 fringe_bmp[i++] = 0;
2184 for (i = 0; i < h; i++)
2185 bits[i] = ~bits[i];
2187 BLOCK_INPUT;
2189 provider = CGDataProviderCreateWithData (NULL, bits,
2190 sizeof (unsigned short) * h, NULL);
2191 if (provider)
2193 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2194 sizeof (unsigned short),
2195 provider, NULL, 0);
2196 CGDataProviderRelease (provider);
2199 UNBLOCK_INPUT;
2202 static void
2203 mac_destroy_fringe_bitmap (which)
2204 int which;
2206 if (which >= max_fringe_bmp)
2207 return;
2209 if (fringe_bmp[which])
2211 BLOCK_INPUT;
2212 CGImageRelease (fringe_bmp[which]);
2213 UNBLOCK_INPUT;
2215 fringe_bmp[which] = 0;
2217 #endif
2220 /* This is called when starting Emacs and when restarting after
2221 suspend. When starting Emacs, no window is mapped. And nothing
2222 must be done to Emacs's own window if it is suspended (though that
2223 rarely happens). */
2225 static void
2226 XTset_terminal_modes ()
2230 /* This is called when exiting or suspending Emacs. Exiting will make
2231 the windows go away, and suspending requires no action. */
2233 static void
2234 XTreset_terminal_modes ()
2240 /***********************************************************************
2241 Display Iterator
2242 ***********************************************************************/
2244 /* Function prototypes of this page. */
2246 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2247 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2250 static void
2251 pcm_init (pcm, count)
2252 XCharStruct *pcm;
2253 int count;
2255 bzero (pcm, sizeof (XCharStruct) * count);
2256 while (--count >= 0)
2258 pcm->descent = PCM_INVALID;
2259 pcm++;
2263 static enum pcm_status
2264 pcm_get_status (pcm)
2265 const XCharStruct *pcm;
2267 int height = pcm->ascent + pcm->descent;
2269 /* Negative height means some special status. */
2270 return height >= 0 ? PCM_VALID : height;
2273 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2274 is not contained in the font. */
2276 static INLINE XCharStruct *
2277 x_per_char_metric (font, char2b)
2278 XFontStruct *font;
2279 XChar2b *char2b;
2281 /* The result metric information. */
2282 XCharStruct *pcm = NULL;
2284 xassert (font && char2b);
2286 #if USE_ATSUI
2287 if (font->mac_style)
2289 XCharStruct **row = font->bounds.rows + char2b->byte1;
2291 if (*row == NULL)
2293 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2294 pcm_init (*row, 0x100);
2296 pcm = *row + char2b->byte2;
2297 if (pcm_get_status (pcm) != PCM_VALID)
2299 BLOCK_INPUT;
2300 mac_query_char_extents (font->mac_style,
2301 (char2b->byte1 << 8) + char2b->byte2,
2302 NULL, NULL, pcm, NULL);
2303 UNBLOCK_INPUT;
2306 else
2308 #endif
2309 if (font->bounds.per_char != NULL)
2311 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2313 /* min_char_or_byte2 specifies the linear character index
2314 corresponding to the first element of the per_char array,
2315 max_char_or_byte2 is the index of the last character. A
2316 character with non-zero CHAR2B->byte1 is not in the font.
2317 A character with byte2 less than min_char_or_byte2 or
2318 greater max_char_or_byte2 is not in the font. */
2319 if (char2b->byte1 == 0
2320 && char2b->byte2 >= font->min_char_or_byte2
2321 && char2b->byte2 <= font->max_char_or_byte2)
2322 pcm = font->bounds.per_char
2323 + (char2b->byte2 - font->min_char_or_byte2);
2325 else
2327 /* If either min_byte1 or max_byte1 are nonzero, both
2328 min_char_or_byte2 and max_char_or_byte2 are less than
2329 256, and the 2-byte character index values corresponding
2330 to the per_char array element N (counting from 0) are:
2332 byte1 = N/D + min_byte1
2333 byte2 = N\D + min_char_or_byte2
2335 where:
2337 D = max_char_or_byte2 - min_char_or_byte2 + 1
2338 / = integer division
2339 \ = integer modulus */
2340 if (char2b->byte1 >= font->min_byte1
2341 && char2b->byte1 <= font->max_byte1
2342 && char2b->byte2 >= font->min_char_or_byte2
2343 && char2b->byte2 <= font->max_char_or_byte2)
2345 pcm = (font->bounds.per_char
2346 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2347 * (char2b->byte1 - font->min_byte1))
2348 + (char2b->byte2 - font->min_char_or_byte2));
2352 else
2354 /* If the per_char pointer is null, all glyphs between the first
2355 and last character indexes inclusive have the same
2356 information, as given by both min_bounds and max_bounds. */
2357 if (char2b->byte2 >= font->min_char_or_byte2
2358 && char2b->byte2 <= font->max_char_or_byte2)
2359 pcm = &font->max_bounds;
2361 #if USE_ATSUI
2363 #endif
2365 return ((pcm == NULL
2366 || (pcm->width == 0
2367 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2368 && (pcm->rbearing - pcm->lbearing) == 0
2369 #endif
2371 ? NULL : pcm);
2374 /* RIF:
2377 static XCharStruct *
2378 mac_per_char_metric (font, char2b, font_type)
2379 XFontStruct *font;
2380 XChar2b *char2b;
2381 int font_type;
2383 return x_per_char_metric (font, char2b);
2386 /* RIF:
2387 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2388 the two-byte form of C. Encoding is returned in *CHAR2B. */
2390 static int
2391 mac_encode_char (c, char2b, font_info, two_byte_p)
2392 int c;
2393 XChar2b *char2b;
2394 struct font_info *font_info;
2395 int *two_byte_p;
2397 int charset = CHAR_CHARSET (c);
2398 XFontStruct *font = font_info->font;
2400 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2401 This may be either a program in a special encoder language or a
2402 fixed encoding. */
2403 if (font_info->font_encoder)
2405 /* It's a program. */
2406 struct ccl_program *ccl = font_info->font_encoder;
2408 check_ccl_update (ccl);
2409 if (CHARSET_DIMENSION (charset) == 1)
2411 ccl->reg[0] = charset;
2412 ccl->reg[1] = char2b->byte2;
2413 ccl->reg[2] = -1;
2415 else
2417 ccl->reg[0] = charset;
2418 ccl->reg[1] = char2b->byte1;
2419 ccl->reg[2] = char2b->byte2;
2422 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2424 /* We assume that MSBs are appropriately set/reset by CCL
2425 program. */
2426 if (font->max_byte1 == 0) /* 1-byte font */
2427 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2428 else
2429 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2431 else if (font_info->encoding[charset])
2433 /* Fixed encoding scheme. See fontset.h for the meaning of the
2434 encoding numbers. */
2435 int enc = font_info->encoding[charset];
2437 if ((enc == 1 || enc == 2)
2438 && CHARSET_DIMENSION (charset) == 2)
2439 char2b->byte1 |= 0x80;
2441 if (enc == 1 || enc == 3)
2442 char2b->byte2 |= 0x80;
2444 if (enc == 4)
2446 int sjis1, sjis2;
2448 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2449 char2b->byte1 = sjis1;
2450 char2b->byte2 = sjis2;
2454 if (two_byte_p)
2455 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2457 return FONT_TYPE_UNKNOWN;
2462 /***********************************************************************
2463 Glyph display
2464 ***********************************************************************/
2468 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2469 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2470 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2471 int));
2472 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2473 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2474 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2475 static void x_draw_glyph_string P_ ((struct glyph_string *));
2476 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2477 static void x_set_cursor_gc P_ ((struct glyph_string *));
2478 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2479 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2480 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2481 unsigned long *, double, int));*/
2482 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2483 double, int, unsigned long));
2484 static void x_setup_relief_colors P_ ((struct glyph_string *));
2485 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2486 static void x_draw_image_relief P_ ((struct glyph_string *));
2487 static void x_draw_image_foreground P_ ((struct glyph_string *));
2488 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2489 int, int, int));
2490 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2491 int, int, int, int, int, int,
2492 Rect *));
2493 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2494 int, int, int, Rect *));
2496 #if GLYPH_DEBUG
2497 static void x_check_font P_ ((struct frame *, XFontStruct *));
2498 #endif
2501 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2502 face. */
2504 static void
2505 x_set_cursor_gc (s)
2506 struct glyph_string *s;
2508 if (s->font == FRAME_FONT (s->f)
2509 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2510 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2511 && !s->cmp)
2512 s->gc = s->f->output_data.mac->cursor_gc;
2513 else
2515 /* Cursor on non-default face: must merge. */
2516 XGCValues xgcv;
2517 unsigned long mask;
2519 xgcv.background = s->f->output_data.mac->cursor_pixel;
2520 xgcv.foreground = s->face->background;
2522 /* If the glyph would be invisible, try a different foreground. */
2523 if (xgcv.foreground == xgcv.background)
2524 xgcv.foreground = s->face->foreground;
2525 if (xgcv.foreground == xgcv.background)
2526 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2527 if (xgcv.foreground == xgcv.background)
2528 xgcv.foreground = s->face->foreground;
2530 /* Make sure the cursor is distinct from text in this face. */
2531 if (xgcv.background == s->face->background
2532 && xgcv.foreground == s->face->foreground)
2534 xgcv.background = s->face->foreground;
2535 xgcv.foreground = s->face->background;
2538 IF_DEBUG (x_check_font (s->f, s->font));
2539 xgcv.font = s->font;
2540 mask = GCForeground | GCBackground | GCFont;
2542 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2543 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2544 mask, &xgcv);
2545 else
2546 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2547 = XCreateGC (s->display, s->window, mask, &xgcv);
2549 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2554 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2556 static void
2557 x_set_mouse_face_gc (s)
2558 struct glyph_string *s;
2560 int face_id;
2561 struct face *face;
2563 /* What face has to be used last for the mouse face? */
2564 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2565 face = FACE_FROM_ID (s->f, face_id);
2566 if (face == NULL)
2567 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2569 if (s->first_glyph->type == CHAR_GLYPH)
2570 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2571 else
2572 face_id = FACE_FOR_CHAR (s->f, face, 0);
2573 s->face = FACE_FROM_ID (s->f, face_id);
2574 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2576 /* If font in this face is same as S->font, use it. */
2577 if (s->font == s->face->font)
2578 s->gc = s->face->gc;
2579 else
2581 /* Otherwise construct scratch_cursor_gc with values from FACE
2582 but font FONT. */
2583 XGCValues xgcv;
2584 unsigned long mask;
2586 xgcv.background = s->face->background;
2587 xgcv.foreground = s->face->foreground;
2588 IF_DEBUG (x_check_font (s->f, s->font));
2589 xgcv.font = s->font;
2590 mask = GCForeground | GCBackground | GCFont;
2592 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2593 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2594 mask, &xgcv);
2595 else
2596 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2597 = XCreateGC (s->display, s->window, mask, &xgcv);
2599 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2602 xassert (s->gc != 0);
2606 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2607 Faces to use in the mode line have already been computed when the
2608 matrix was built, so there isn't much to do, here. */
2610 static INLINE void
2611 x_set_mode_line_face_gc (s)
2612 struct glyph_string *s;
2614 s->gc = s->face->gc;
2618 /* Set S->gc of glyph string S for drawing that glyph string. Set
2619 S->stippled_p to a non-zero value if the face of S has a stipple
2620 pattern. */
2622 static INLINE void
2623 x_set_glyph_string_gc (s)
2624 struct glyph_string *s;
2626 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2628 if (s->hl == DRAW_NORMAL_TEXT)
2630 s->gc = s->face->gc;
2631 s->stippled_p = s->face->stipple != 0;
2633 else if (s->hl == DRAW_INVERSE_VIDEO)
2635 x_set_mode_line_face_gc (s);
2636 s->stippled_p = s->face->stipple != 0;
2638 else if (s->hl == DRAW_CURSOR)
2640 x_set_cursor_gc (s);
2641 s->stippled_p = 0;
2643 else if (s->hl == DRAW_MOUSE_FACE)
2645 x_set_mouse_face_gc (s);
2646 s->stippled_p = s->face->stipple != 0;
2648 else if (s->hl == DRAW_IMAGE_RAISED
2649 || s->hl == DRAW_IMAGE_SUNKEN)
2651 s->gc = s->face->gc;
2652 s->stippled_p = s->face->stipple != 0;
2654 else
2656 s->gc = s->face->gc;
2657 s->stippled_p = s->face->stipple != 0;
2660 /* GC must have been set. */
2661 xassert (s->gc != 0);
2665 /* Set clipping for output of glyph string S. S may be part of a mode
2666 line or menu if we don't have X toolkit support. */
2668 static INLINE void
2669 x_set_glyph_string_clipping (s)
2670 struct glyph_string *s;
2672 Rect rects[MAX_CLIP_RECTS];
2673 int n;
2675 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2676 mac_set_clip_rectangles (s->f, s->gc, rects, n);
2680 /* RIF:
2681 Compute left and right overhang of glyph string S. If S is a glyph
2682 string for a composition, assume overhangs don't exist. */
2684 static void
2685 mac_compute_glyph_string_overhangs (s)
2686 struct glyph_string *s;
2688 if (!(s->cmp == NULL
2689 && s->first_glyph->type == CHAR_GLYPH))
2690 return;
2692 if (!s->two_byte_p
2693 #if USE_ATSUI
2694 || s->font->mac_style
2695 #endif
2698 XCharStruct cs;
2700 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2701 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2702 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2704 else
2706 Rect r;
2707 MacFontStruct *font = s->font;
2709 mac_begin_clip (s->f, NULL);
2711 TextFont (font->mac_fontnum);
2712 TextSize (font->mac_fontsize);
2713 TextFace (font->mac_fontface);
2715 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2717 mac_end_clip (s->f, NULL);
2719 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2720 s->left_overhang = r.left < 0 ? -r.left : 0;
2725 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2727 static INLINE void
2728 x_clear_glyph_string_rect (s, x, y, w, h)
2729 struct glyph_string *s;
2730 int x, y, w, h;
2732 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2736 /* Draw the background of glyph_string S. If S->background_filled_p
2737 is non-zero don't draw it. FORCE_P non-zero means draw the
2738 background even if it wouldn't be drawn normally. This is used
2739 when a string preceding S draws into the background of S, or S
2740 contains the first component of a composition. */
2742 static void
2743 x_draw_glyph_string_background (s, force_p)
2744 struct glyph_string *s;
2745 int force_p;
2747 /* Nothing to do if background has already been drawn or if it
2748 shouldn't be drawn in the first place. */
2749 if (!s->background_filled_p)
2751 int box_line_width = max (s->face->box_line_width, 0);
2753 #if 0 /* MAC_TODO: stipple */
2754 if (s->stippled_p)
2756 /* Fill background with a stipple pattern. */
2757 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2758 XFillRectangle (s->display, s->window, s->gc, s->x,
2759 s->y + box_line_width,
2760 s->background_width,
2761 s->height - 2 * box_line_width);
2762 XSetFillStyle (s->display, s->gc, FillSolid);
2763 s->background_filled_p = 1;
2765 else
2766 #endif
2767 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2768 || s->font_not_found_p
2769 || s->extends_to_end_of_line_p
2770 || force_p)
2772 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2773 s->background_width,
2774 s->height - 2 * box_line_width);
2775 s->background_filled_p = 1;
2781 /* Draw the foreground of glyph string S. */
2783 static void
2784 x_draw_glyph_string_foreground (s)
2785 struct glyph_string *s;
2787 int i, x, bg_width;
2789 /* If first glyph of S has a left box line, start drawing the text
2790 of S to the right of that box line. */
2791 if (s->face->box != FACE_NO_BOX
2792 && s->first_glyph->left_box_line_p)
2793 x = s->x + abs (s->face->box_line_width);
2794 else
2795 x = s->x;
2797 /* Draw characters of S as rectangles if S's font could not be
2798 loaded. */
2799 if (s->font_not_found_p)
2801 for (i = 0; i < s->nchars; ++i)
2803 struct glyph *g = s->first_glyph + i;
2804 mac_draw_rectangle (s->f, s->gc, x, s->y,
2805 g->pixel_width - 1, s->height - 1);
2806 x += g->pixel_width;
2809 else
2811 char *char1b = (char *) s->char2b;
2812 int boff = s->font_info->baseline_offset;
2814 if (s->font_info->vertical_centering)
2815 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2817 /* If we can use 8-bit functions, condense S->char2b. */
2818 if (!s->two_byte_p
2819 #if USE_ATSUI
2820 && GC_FONT (s->gc)->mac_style == NULL
2821 #endif
2823 for (i = 0; i < s->nchars; ++i)
2824 char1b[i] = s->char2b[i].byte2;
2826 /* Draw text with XDrawString if background has already been
2827 filled. Otherwise, use XDrawImageString. (Note that
2828 XDrawImageString is usually faster than XDrawString.) Always
2829 use XDrawImageString when drawing the cursor so that there is
2830 no chance that characters under a box cursor are invisible. */
2831 if (s->for_overlaps
2832 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2833 bg_width = 0; /* Corresponds to XDrawString. */
2834 else
2835 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2837 if (s->two_byte_p
2838 #if USE_ATSUI
2839 || GC_FONT (s->gc)->mac_style
2840 #endif
2842 #if USE_CG_TEXT_DRAWING
2843 if (!s->two_byte_p
2844 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
2845 s->char2b, s->nchars, bg_width,
2846 s->face->overstrike))
2848 else
2849 #endif
2850 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2851 s->char2b, s->nchars, bg_width,
2852 s->face->overstrike);
2853 else
2854 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2855 char1b, s->nchars, bg_width,
2856 s->face->overstrike);
2860 /* Draw the foreground of composite glyph string S. */
2862 static void
2863 x_draw_composite_glyph_string_foreground (s)
2864 struct glyph_string *s;
2866 int i, x;
2868 /* If first glyph of S has a left box line, start drawing the text
2869 of S to the right of that box line. */
2870 if (s->face->box != FACE_NO_BOX
2871 && s->first_glyph->left_box_line_p)
2872 x = s->x + abs (s->face->box_line_width);
2873 else
2874 x = s->x;
2876 /* S is a glyph string for a composition. S->gidx is the index of
2877 the first character drawn for glyphs of this composition.
2878 S->gidx == 0 means we are drawing the very first character of
2879 this composition. */
2881 /* Draw a rectangle for the composition if the font for the very
2882 first character of the composition could not be loaded. */
2883 if (s->font_not_found_p)
2885 if (s->gidx == 0)
2886 mac_draw_rectangle (s->f, s->gc, x, s->y,
2887 s->width - 1, s->height - 1);
2889 else
2891 for (i = 0; i < s->nchars; i++, ++s->gidx)
2892 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
2893 /* This is a nonexistent or zero-width glyph such as a
2894 combining diacritic. Draw a rectangle. */
2895 mac_draw_rectangle (s->f, s->gc,
2896 x + s->cmp->offsets[s->gidx * 2], s->y,
2897 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
2898 else
2899 mac_draw_image_string_16 (s->f, s->gc,
2900 x + s->cmp->offsets[s->gidx * 2],
2901 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2902 s->char2b + i, 1, 0, s->face->overstrike);
2907 #ifdef USE_X_TOOLKIT
2909 static struct frame *x_frame_of_widget P_ ((Widget));
2912 /* Return the frame on which widget WIDGET is used.. Abort if frame
2913 cannot be determined. */
2915 static struct frame *
2916 x_frame_of_widget (widget)
2917 Widget widget;
2919 struct x_display_info *dpyinfo;
2920 Lisp_Object tail;
2921 struct frame *f;
2923 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2925 /* Find the top-level shell of the widget. Note that this function
2926 can be called when the widget is not yet realized, so XtWindow
2927 (widget) == 0. That's the reason we can't simply use
2928 x_any_window_to_frame. */
2929 while (!XtIsTopLevelShell (widget))
2930 widget = XtParent (widget);
2932 /* Look for a frame with that top-level widget. Allocate the color
2933 on that frame to get the right gamma correction value. */
2934 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2935 if (GC_FRAMEP (XCAR (tail))
2936 && (f = XFRAME (XCAR (tail)),
2937 (f->output_data.nothing != 1
2938 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2939 && f->output_data.x->widget == widget)
2940 return f;
2942 abort ();
2946 /* Allocate the color COLOR->pixel on the screen and display of
2947 widget WIDGET in colormap CMAP. If an exact match cannot be
2948 allocated, try the nearest color available. Value is non-zero
2949 if successful. This is called from lwlib. */
2952 x_alloc_nearest_color_for_widget (widget, cmap, color)
2953 Widget widget;
2954 Colormap cmap;
2955 XColor *color;
2957 struct frame *f = x_frame_of_widget (widget);
2958 return x_alloc_nearest_color (f, cmap, color);
2962 #endif /* USE_X_TOOLKIT */
2964 #if 0 /* MAC_TODO */
2966 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2967 CMAP. If an exact match can't be allocated, try the nearest color
2968 available. Value is non-zero if successful. Set *COLOR to the
2969 color allocated. */
2972 x_alloc_nearest_color (f, cmap, color)
2973 struct frame *f;
2974 Colormap cmap;
2975 XColor *color;
2977 Display *display = FRAME_X_DISPLAY (f);
2978 Screen *screen = FRAME_X_SCREEN (f);
2979 int rc;
2981 gamma_correct (f, color);
2982 rc = XAllocColor (display, cmap, color);
2983 if (rc == 0)
2985 /* If we got to this point, the colormap is full, so we're going
2986 to try to get the next closest color. The algorithm used is
2987 a least-squares matching, which is what X uses for closest
2988 color matching with StaticColor visuals. */
2989 int nearest, i;
2990 unsigned long nearest_delta = ~0;
2991 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2992 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2994 for (i = 0; i < ncells; ++i)
2995 cells[i].pixel = i;
2996 XQueryColors (display, cmap, cells, ncells);
2998 for (nearest = i = 0; i < ncells; ++i)
3000 long dred = (color->red >> 8) - (cells[i].red >> 8);
3001 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3002 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3003 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3005 if (delta < nearest_delta)
3007 nearest = i;
3008 nearest_delta = delta;
3012 color->red = cells[nearest].red;
3013 color->green = cells[nearest].green;
3014 color->blue = cells[nearest].blue;
3015 rc = XAllocColor (display, cmap, color);
3018 #ifdef DEBUG_X_COLORS
3019 if (rc)
3020 register_color (color->pixel);
3021 #endif /* DEBUG_X_COLORS */
3023 return rc;
3027 /* Allocate color PIXEL on frame F. 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_color (f, pixel)
3033 struct frame *f;
3034 unsigned long pixel;
3036 XColor color;
3038 color.pixel = pixel;
3039 BLOCK_INPUT;
3040 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3041 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3042 UNBLOCK_INPUT;
3043 #ifdef DEBUG_X_COLORS
3044 register_color (pixel);
3045 #endif
3046 return color.pixel;
3050 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3051 It's necessary to do this instead of just using PIXEL directly to
3052 get color reference counts right. */
3054 unsigned long
3055 x_copy_dpy_color (dpy, cmap, pixel)
3056 Display *dpy;
3057 Colormap cmap;
3058 unsigned long pixel;
3060 XColor color;
3062 color.pixel = pixel;
3063 BLOCK_INPUT;
3064 XQueryColor (dpy, cmap, &color);
3065 XAllocColor (dpy, cmap, &color);
3066 UNBLOCK_INPUT;
3067 #ifdef DEBUG_X_COLORS
3068 register_color (pixel);
3069 #endif
3070 return color.pixel;
3073 #endif /* MAC_TODO */
3076 /* Brightness beyond which a color won't have its highlight brightness
3077 boosted.
3079 Nominally, highlight colors for `3d' faces are calculated by
3080 brightening an object's color by a constant scale factor, but this
3081 doesn't yield good results for dark colors, so for colors who's
3082 brightness is less than this value (on a scale of 0-255) have to
3083 use an additional additive factor.
3085 The value here is set so that the default menu-bar/mode-line color
3086 (grey75) will not have its highlights changed at all. */
3087 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3090 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3091 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3092 If this produces the same color as COLOR, try a color where all RGB
3093 values have DELTA added. Return the allocated color in *COLOR.
3094 DISPLAY is the X display, CMAP is the colormap to operate on.
3095 Value is non-zero if successful. */
3097 static int
3098 mac_alloc_lighter_color (f, color, factor, delta)
3099 struct frame *f;
3100 unsigned long *color;
3101 double factor;
3102 int delta;
3104 unsigned long new;
3105 long bright;
3107 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3108 delta /= 256;
3110 /* Change RGB values by specified FACTOR. Avoid overflow! */
3111 xassert (factor >= 0);
3112 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3113 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3114 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3116 /* Calculate brightness of COLOR. */
3117 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3118 + BLUE_FROM_ULONG (*color)) / 6;
3120 /* We only boost colors that are darker than
3121 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3122 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3123 /* Make an additive adjustment to NEW, because it's dark enough so
3124 that scaling by FACTOR alone isn't enough. */
3126 /* How far below the limit this color is (0 - 1, 1 being darker). */
3127 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3128 /* The additive adjustment. */
3129 int min_delta = delta * dimness * factor / 2;
3131 if (factor < 1)
3132 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3133 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3134 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3135 else
3136 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3137 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3138 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3141 if (new == *color)
3142 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3143 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3144 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3146 /* MAC_TODO: Map to palette and retry with delta if same? */
3147 /* MAC_TODO: Free colors (if using palette)? */
3149 if (new == *color)
3150 return 0;
3152 *color = new;
3154 return 1;
3158 /* Set up the foreground color for drawing relief lines of glyph
3159 string S. RELIEF is a pointer to a struct relief containing the GC
3160 with which lines will be drawn. Use a color that is FACTOR or
3161 DELTA lighter or darker than the relief's background which is found
3162 in S->f->output_data.x->relief_background. If such a color cannot
3163 be allocated, use DEFAULT_PIXEL, instead. */
3165 static void
3166 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3167 struct frame *f;
3168 struct relief *relief;
3169 double factor;
3170 int delta;
3171 unsigned long default_pixel;
3173 XGCValues xgcv;
3174 struct mac_output *di = f->output_data.mac;
3175 unsigned long mask = GCForeground;
3176 unsigned long pixel;
3177 unsigned long background = di->relief_background;
3178 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3180 /* MAC_TODO: Free colors (if using palette)? */
3182 /* Allocate new color. */
3183 xgcv.foreground = default_pixel;
3184 pixel = background;
3185 if (dpyinfo->n_planes != 1
3186 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3188 relief->allocated_p = 1;
3189 xgcv.foreground = relief->pixel = pixel;
3192 if (relief->gc == 0)
3194 #if 0 /* MAC_TODO: stipple */
3195 xgcv.stipple = dpyinfo->gray;
3196 mask |= GCStipple;
3197 #endif
3198 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3200 else
3201 XChangeGC (NULL, relief->gc, mask, &xgcv);
3205 /* Set up colors for the relief lines around glyph string S. */
3207 static void
3208 x_setup_relief_colors (s)
3209 struct glyph_string *s;
3211 struct mac_output *di = s->f->output_data.mac;
3212 unsigned long color;
3214 if (s->face->use_box_color_for_shadows_p)
3215 color = s->face->box_color;
3216 else if (s->first_glyph->type == IMAGE_GLYPH
3217 && s->img->pixmap
3218 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3219 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3220 else
3222 XGCValues xgcv;
3224 /* Get the background color of the face. */
3225 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3226 color = xgcv.background;
3229 if (di->white_relief.gc == 0
3230 || color != di->relief_background)
3232 di->relief_background = color;
3233 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3234 WHITE_PIX_DEFAULT (s->f));
3235 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3236 BLACK_PIX_DEFAULT (s->f));
3241 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3242 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3243 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3244 relief. LEFT_P non-zero means draw a relief on the left side of
3245 the rectangle. RIGHT_P non-zero means draw a relief on the right
3246 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3247 when drawing. */
3249 static void
3250 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3251 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3252 struct frame *f;
3253 int left_x, top_y, right_x, bottom_y, width;
3254 int top_p, bot_p, left_p, right_p, raised_p;
3255 Rect *clip_rect;
3257 Display *dpy = FRAME_MAC_DISPLAY (f);
3258 int i;
3259 GC gc;
3261 if (raised_p)
3262 gc = f->output_data.mac->white_relief.gc;
3263 else
3264 gc = f->output_data.mac->black_relief.gc;
3265 mac_set_clip_rectangles (f, gc, clip_rect, 1);
3267 /* Top. */
3268 if (top_p)
3269 for (i = 0; i < width; ++i)
3270 mac_draw_line (f, gc,
3271 left_x + i * left_p, top_y + i,
3272 right_x + 1 - i * right_p, top_y + i);
3274 /* Left. */
3275 if (left_p)
3276 for (i = 0; i < width; ++i)
3277 mac_draw_line (f, gc,
3278 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3280 mac_reset_clip_rectangles (f, gc);
3281 if (raised_p)
3282 gc = f->output_data.mac->black_relief.gc;
3283 else
3284 gc = f->output_data.mac->white_relief.gc;
3285 mac_set_clip_rectangles (f, gc, clip_rect, 1);
3287 /* Bottom. */
3288 if (bot_p)
3289 for (i = 0; i < width; ++i)
3290 mac_draw_line (f, gc,
3291 left_x + i * left_p, bottom_y - i,
3292 right_x + 1 - i * right_p, bottom_y - i);
3294 /* Right. */
3295 if (right_p)
3296 for (i = 0; i < width; ++i)
3297 mac_draw_line (f, gc,
3298 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3300 mac_reset_clip_rectangles (f, gc);
3304 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3305 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3306 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3307 left side of the rectangle. RIGHT_P non-zero means draw a line
3308 on the right side of the rectangle. CLIP_RECT is the clipping
3309 rectangle to use when drawing. */
3311 static void
3312 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3313 left_p, right_p, clip_rect)
3314 struct glyph_string *s;
3315 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3316 Rect *clip_rect;
3318 XGCValues xgcv;
3320 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3321 XSetForeground (s->display, s->gc, s->face->box_color);
3322 mac_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
3324 /* Top. */
3325 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3326 right_x - left_x + 1, width);
3328 /* Left. */
3329 if (left_p)
3330 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3331 width, bottom_y - top_y + 1);
3333 /* Bottom. */
3334 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3335 right_x - left_x + 1, width);
3337 /* Right. */
3338 if (right_p)
3339 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3340 top_y, width, bottom_y - top_y + 1);
3342 XSetForeground (s->display, s->gc, xgcv.foreground);
3343 mac_reset_clip_rectangles (s->f, s->gc);
3347 /* Draw a box around glyph string S. */
3349 static void
3350 x_draw_glyph_string_box (s)
3351 struct glyph_string *s;
3353 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3354 int left_p, right_p;
3355 struct glyph *last_glyph;
3356 Rect clip_rect;
3358 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3359 ? WINDOW_RIGHT_EDGE_X (s->w)
3360 : window_box_right (s->w, s->area));
3362 /* The glyph that may have a right box line. */
3363 last_glyph = (s->cmp || s->img
3364 ? s->first_glyph
3365 : s->first_glyph + s->nchars - 1);
3367 width = abs (s->face->box_line_width);
3368 raised_p = s->face->box == FACE_RAISED_BOX;
3369 left_x = s->x;
3370 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3371 ? last_x - 1
3372 : min (last_x, s->x + s->background_width) - 1);
3373 top_y = s->y;
3374 bottom_y = top_y + s->height - 1;
3376 left_p = (s->first_glyph->left_box_line_p
3377 || (s->hl == DRAW_MOUSE_FACE
3378 && (s->prev == NULL
3379 || s->prev->hl != s->hl)));
3380 right_p = (last_glyph->right_box_line_p
3381 || (s->hl == DRAW_MOUSE_FACE
3382 && (s->next == NULL
3383 || s->next->hl != s->hl)));
3385 get_glyph_string_clip_rect (s, &clip_rect);
3387 if (s->face->box == FACE_SIMPLE_BOX)
3388 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3389 left_p, right_p, &clip_rect);
3390 else
3392 x_setup_relief_colors (s);
3393 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3394 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3399 /* Draw foreground of image glyph string S. */
3401 static void
3402 x_draw_image_foreground (s)
3403 struct glyph_string *s;
3405 int x = s->x;
3406 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3408 /* If first glyph of S has a left box line, start drawing it to the
3409 right of that line. */
3410 if (s->face->box != FACE_NO_BOX
3411 && s->first_glyph->left_box_line_p
3412 && s->slice.x == 0)
3413 x += abs (s->face->box_line_width);
3415 /* If there is a margin around the image, adjust x- and y-position
3416 by that margin. */
3417 if (s->slice.x == 0)
3418 x += s->img->hmargin;
3419 if (s->slice.y == 0)
3420 y += s->img->vmargin;
3422 if (s->img->pixmap)
3424 x_set_glyph_string_clipping (s);
3426 #if USE_CG_DRAWING
3427 mac_draw_cg_image (s->img->data.ptr_val,
3428 s->f, s->gc, s->slice.x, s->slice.y,
3429 s->slice.width, s->slice.height, x, y, 1);
3430 #endif
3431 if (s->img->mask)
3432 #if !USE_CG_DRAWING
3433 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3434 s->f, s->gc, s->slice.x, s->slice.y,
3435 s->slice.width, s->slice.height, x, y);
3436 #else
3438 #endif
3439 else
3441 #if !USE_CG_DRAWING
3442 mac_copy_area (s->img->pixmap,
3443 s->f, s->gc, s->slice.x, s->slice.y,
3444 s->slice.width, s->slice.height, x, y);
3445 #endif
3447 /* When the image has a mask, we can expect that at
3448 least part of a mouse highlight or a block cursor will
3449 be visible. If the image doesn't have a mask, make
3450 a block cursor visible by drawing a rectangle around
3451 the image. I believe it's looking better if we do
3452 nothing here for mouse-face. */
3453 if (s->hl == DRAW_CURSOR)
3455 int r = s->img->relief;
3456 if (r < 0) r = -r;
3457 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3458 s->slice.width + r*2 - 1,
3459 s->slice.height + r*2 - 1);
3463 else
3464 /* Draw a rectangle if image could not be loaded. */
3465 mac_draw_rectangle (s->f, s->gc, x, y,
3466 s->slice.width - 1, s->slice.height - 1);
3470 /* Draw a relief around the image glyph string S. */
3472 static void
3473 x_draw_image_relief (s)
3474 struct glyph_string *s;
3476 int x0, y0, x1, y1, thick, raised_p;
3477 Rect r;
3478 int x = s->x;
3479 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3481 /* If first glyph of S has a left box line, start drawing it to the
3482 right of that line. */
3483 if (s->face->box != FACE_NO_BOX
3484 && s->first_glyph->left_box_line_p
3485 && s->slice.x == 0)
3486 x += abs (s->face->box_line_width);
3488 /* If there is a margin around the image, adjust x- and y-position
3489 by that margin. */
3490 if (s->slice.x == 0)
3491 x += s->img->hmargin;
3492 if (s->slice.y == 0)
3493 y += s->img->vmargin;
3495 if (s->hl == DRAW_IMAGE_SUNKEN
3496 || s->hl == DRAW_IMAGE_RAISED)
3498 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3499 raised_p = s->hl == DRAW_IMAGE_RAISED;
3501 else
3503 thick = abs (s->img->relief);
3504 raised_p = s->img->relief > 0;
3507 x0 = x - thick;
3508 y0 = y - thick;
3509 x1 = x + s->slice.width + thick - 1;
3510 y1 = y + s->slice.height + thick - 1;
3512 x_setup_relief_colors (s);
3513 get_glyph_string_clip_rect (s, &r);
3514 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3515 s->slice.y == 0,
3516 s->slice.y + s->slice.height == s->img->height,
3517 s->slice.x == 0,
3518 s->slice.x + s->slice.width == s->img->width,
3519 &r);
3523 /* Draw part of the background of glyph string S. X, Y, W, and H
3524 give the rectangle to draw. */
3526 static void
3527 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3528 struct glyph_string *s;
3529 int x, y, w, h;
3531 #if 0 /* MAC_TODO: stipple */
3532 if (s->stippled_p)
3534 /* Fill background with a stipple pattern. */
3535 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3536 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3537 XSetFillStyle (s->display, s->gc, FillSolid);
3539 else
3540 #endif /* MAC_TODO */
3541 x_clear_glyph_string_rect (s, x, y, w, h);
3545 /* Draw image glyph string S.
3547 s->y
3548 s->x +-------------------------
3549 | s->face->box
3551 | +-------------------------
3552 | | s->img->margin
3554 | | +-------------------
3555 | | | the image
3559 static void
3560 x_draw_image_glyph_string (s)
3561 struct glyph_string *s;
3563 int x, y;
3564 int box_line_hwidth = abs (s->face->box_line_width);
3565 int box_line_vwidth = max (s->face->box_line_width, 0);
3566 int height;
3568 height = s->height - 2 * box_line_vwidth;
3571 /* Fill background with face under the image. Do it only if row is
3572 taller than image or if image has a clip mask to reduce
3573 flickering. */
3574 s->stippled_p = s->face->stipple != 0;
3575 if (height > s->slice.height
3576 || s->img->hmargin
3577 || s->img->vmargin
3578 || s->img->mask
3579 || s->img->pixmap == 0
3580 || s->width != s->background_width)
3582 x = s->x;
3583 if (s->first_glyph->left_box_line_p
3584 && s->slice.x == 0)
3585 x += box_line_hwidth;
3587 y = s->y;
3588 if (s->slice.y == 0)
3589 y += box_line_vwidth;
3591 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3593 s->background_filled_p = 1;
3596 /* Draw the foreground. */
3597 x_draw_image_foreground (s);
3599 /* If we must draw a relief around the image, do it. */
3600 if (s->img->relief
3601 || s->hl == DRAW_IMAGE_RAISED
3602 || s->hl == DRAW_IMAGE_SUNKEN)
3603 x_draw_image_relief (s);
3607 /* Draw stretch glyph string S. */
3609 static void
3610 x_draw_stretch_glyph_string (s)
3611 struct glyph_string *s;
3613 xassert (s->first_glyph->type == STRETCH_GLYPH);
3615 if (s->hl == DRAW_CURSOR
3616 && !x_stretch_cursor_p)
3618 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3619 as wide as the stretch glyph. */
3620 int width, background_width = s->background_width;
3621 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3623 if (x < left_x)
3625 background_width -= left_x - x;
3626 x = left_x;
3628 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3630 /* Draw cursor. */
3631 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3633 /* Clear rest using the GC of the original non-cursor face. */
3634 if (width < background_width)
3636 int y = s->y;
3637 int w = background_width - width, h = s->height;
3638 Rect r;
3639 GC gc;
3641 x += width;
3642 if (s->row->mouse_face_p
3643 && cursor_in_mouse_face_p (s->w))
3645 x_set_mouse_face_gc (s);
3646 gc = s->gc;
3648 else
3649 gc = s->face->gc;
3651 get_glyph_string_clip_rect (s, &r);
3652 mac_set_clip_rectangles (s->f, gc, &r, 1);
3654 #if 0 /* MAC_TODO: stipple */
3655 if (s->face->stipple)
3657 /* Fill background with a stipple pattern. */
3658 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3659 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3660 XSetFillStyle (s->display, gc, FillSolid);
3662 else
3663 #endif /* MAC_TODO */
3664 mac_erase_rectangle (s->f, gc, x, y, w, h);
3667 else if (!s->background_filled_p)
3669 int background_width = s->background_width;
3670 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3672 /* Don't draw into left margin, fringe or scrollbar area
3673 except for header line and mode line. */
3674 if (x < left_x && !s->row->mode_line_p)
3676 background_width -= left_x - x;
3677 x = left_x;
3679 if (background_width > 0)
3680 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3683 s->background_filled_p = 1;
3687 /* Draw glyph string S. */
3689 static void
3690 x_draw_glyph_string (s)
3691 struct glyph_string *s;
3693 int relief_drawn_p = 0;
3695 /* If S draws into the background of its successor that does not
3696 draw a cursor, draw the background of the successor first so that
3697 S can draw into it. This makes S->next use XDrawString instead
3698 of XDrawImageString. */
3699 if (s->next && s->right_overhang && !s->for_overlaps
3700 && s->next->hl != DRAW_CURSOR)
3702 xassert (s->next->img == NULL);
3703 x_set_glyph_string_gc (s->next);
3704 x_set_glyph_string_clipping (s->next);
3705 x_draw_glyph_string_background (s->next, 1);
3708 /* Set up S->gc, set clipping and draw S. */
3709 x_set_glyph_string_gc (s);
3711 /* Draw relief (if any) in advance for char/composition so that the
3712 glyph string can be drawn over it. */
3713 if (!s->for_overlaps
3714 && s->face->box != FACE_NO_BOX
3715 && (s->first_glyph->type == CHAR_GLYPH
3716 || s->first_glyph->type == COMPOSITE_GLYPH))
3719 x_set_glyph_string_clipping (s);
3720 x_draw_glyph_string_background (s, 1);
3721 x_draw_glyph_string_box (s);
3722 x_set_glyph_string_clipping (s);
3723 relief_drawn_p = 1;
3725 else
3726 x_set_glyph_string_clipping (s);
3728 switch (s->first_glyph->type)
3730 case IMAGE_GLYPH:
3731 x_draw_image_glyph_string (s);
3732 break;
3734 case STRETCH_GLYPH:
3735 x_draw_stretch_glyph_string (s);
3736 break;
3738 case CHAR_GLYPH:
3739 if (s->for_overlaps)
3740 s->background_filled_p = 1;
3741 else
3742 x_draw_glyph_string_background (s, 0);
3743 x_draw_glyph_string_foreground (s);
3744 break;
3746 case COMPOSITE_GLYPH:
3747 if (s->for_overlaps || s->gidx > 0)
3748 s->background_filled_p = 1;
3749 else
3750 x_draw_glyph_string_background (s, 1);
3751 x_draw_composite_glyph_string_foreground (s);
3752 break;
3754 default:
3755 abort ();
3758 if (!s->for_overlaps)
3760 /* Draw underline. */
3761 if (s->face->underline_p)
3763 unsigned long tem, h;
3764 int y;
3766 #if 0
3767 /* Get the underline thickness. Default is 1 pixel. */
3768 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3769 #endif
3770 h = 1;
3772 y = s->y + s->height - h;
3773 if (!x_underline_at_descent_line)
3775 /* Get the underline position. This is the recommended
3776 vertical offset in pixels from the baseline to the top of
3777 the underline. This is a signed value according to the
3778 specs, and its default is
3780 ROUND ((maximum descent) / 2), with
3781 ROUND(x) = floor (x + 0.5) */
3783 #if 0
3784 if (x_use_underline_position_properties
3785 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3786 y = s->ybase + (long) tem;
3787 else
3788 #endif
3789 if (s->face->font)
3790 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3793 if (s->face->underline_defaulted_p)
3794 mac_fill_rectangle (s->f, s->gc, s->x, y,
3795 s->background_width, h);
3796 else
3798 XGCValues xgcv;
3799 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3800 XSetForeground (s->display, s->gc, s->face->underline_color);
3801 mac_fill_rectangle (s->f, s->gc, s->x, y,
3802 s->background_width, h);
3803 XSetForeground (s->display, s->gc, xgcv.foreground);
3807 /* Draw overline. */
3808 if (s->face->overline_p)
3810 unsigned long dy = 0, h = 1;
3812 if (s->face->overline_color_defaulted_p)
3813 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3814 s->background_width, h);
3815 else
3817 XGCValues xgcv;
3818 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3819 XSetForeground (s->display, s->gc, s->face->overline_color);
3820 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3821 s->background_width, h);
3822 XSetForeground (s->display, s->gc, xgcv.foreground);
3826 /* Draw strike-through. */
3827 if (s->face->strike_through_p)
3829 unsigned long h = 1;
3830 unsigned long dy = (s->height - h) / 2;
3832 if (s->face->strike_through_color_defaulted_p)
3833 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3834 s->width, h);
3835 else
3837 XGCValues xgcv;
3838 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3839 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3840 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3841 s->width, h);
3842 XSetForeground (s->display, s->gc, xgcv.foreground);
3846 /* Draw relief if not yet drawn. */
3847 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3848 x_draw_glyph_string_box (s);
3851 /* Reset clipping. */
3852 mac_reset_clip_rectangles (s->f, s->gc);
3855 /* Shift display to make room for inserted glyphs. */
3857 void
3858 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3859 struct frame *f;
3860 int x, y, width, height, shift_by;
3862 mac_scroll_area (f, f->output_data.mac->normal_gc,
3863 x, y, width, height,
3864 x + shift_by, y);
3867 /* Delete N glyphs at the nominal cursor position. Not implemented
3868 for X frames. */
3870 static void
3871 x_delete_glyphs (n)
3872 register int n;
3874 abort ();
3878 /* Clear entire frame. If updating_frame is non-null, clear that
3879 frame. Otherwise clear the selected frame. */
3881 static void
3882 x_clear_frame ()
3884 struct frame *f;
3886 if (updating_frame)
3887 f = updating_frame;
3888 else
3889 f = SELECTED_FRAME ();
3891 /* Clearing the frame will erase any cursor, so mark them all as no
3892 longer visible. */
3893 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3894 output_cursor.hpos = output_cursor.vpos = 0;
3895 output_cursor.x = -1;
3897 /* We don't set the output cursor here because there will always
3898 follow an explicit cursor_to. */
3899 BLOCK_INPUT;
3900 mac_clear_window (f);
3902 /* We have to clear the scroll bars, too. If we have changed
3903 colors or something like that, then they should be notified. */
3904 x_scroll_bar_clear (f);
3906 XFlush (FRAME_MAC_DISPLAY (f));
3907 UNBLOCK_INPUT;
3912 /* Invert the middle quarter of the frame for .15 sec. */
3914 /* We use the select system call to do the waiting, so we have to make
3915 sure it's available. If it isn't, we just won't do visual bells. */
3917 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3920 /* Subtract the `struct timeval' values X and Y, storing the result in
3921 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3923 static int
3924 timeval_subtract (result, x, y)
3925 struct timeval *result, x, y;
3927 /* Perform the carry for the later subtraction by updating y. This
3928 is safer because on some systems the tv_sec member is unsigned. */
3929 if (x.tv_usec < y.tv_usec)
3931 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3932 y.tv_usec -= 1000000 * nsec;
3933 y.tv_sec += nsec;
3936 if (x.tv_usec - y.tv_usec > 1000000)
3938 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3939 y.tv_usec += 1000000 * nsec;
3940 y.tv_sec -= nsec;
3943 /* Compute the time remaining to wait. tv_usec is certainly
3944 positive. */
3945 result->tv_sec = x.tv_sec - y.tv_sec;
3946 result->tv_usec = x.tv_usec - y.tv_usec;
3948 /* Return indication of whether the result should be considered
3949 negative. */
3950 return x.tv_sec < y.tv_sec;
3953 void
3954 XTflash (f)
3955 struct frame *f;
3957 /* Get the height not including a menu bar widget. */
3958 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3959 /* Height of each line to flash. */
3960 int flash_height = FRAME_LINE_HEIGHT (f);
3961 /* These will be the left and right margins of the rectangles. */
3962 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3963 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3965 int width;
3967 /* Don't flash the area between a scroll bar and the frame
3968 edge it is next to. */
3969 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3971 case vertical_scroll_bar_left:
3972 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3973 break;
3975 case vertical_scroll_bar_right:
3976 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3977 break;
3979 default:
3980 break;
3983 width = flash_right - flash_left;
3985 BLOCK_INPUT;
3987 /* If window is tall, flash top and bottom line. */
3988 if (height > 3 * FRAME_LINE_HEIGHT (f))
3990 mac_invert_rectangle (f, flash_left,
3991 (FRAME_INTERNAL_BORDER_WIDTH (f)
3992 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3993 width, flash_height);
3994 mac_invert_rectangle (f, flash_left,
3995 (height - flash_height
3996 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3997 width, flash_height);
3999 else
4000 /* If it is short, flash it all. */
4001 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4002 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4004 x_flush (f);
4007 struct timeval wakeup;
4009 EMACS_GET_TIME (wakeup);
4011 /* Compute time to wait until, propagating carry from usecs. */
4012 wakeup.tv_usec += 150000;
4013 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4014 wakeup.tv_usec %= 1000000;
4016 /* Keep waiting until past the time wakeup or any input gets
4017 available. */
4018 while (! detect_input_pending ())
4020 struct timeval current;
4021 struct timeval timeout;
4023 EMACS_GET_TIME (current);
4025 /* Break if result would be negative. */
4026 if (timeval_subtract (&current, wakeup, current))
4027 break;
4029 /* How long `select' should wait. */
4030 timeout.tv_sec = 0;
4031 timeout.tv_usec = 10000;
4033 /* Try to wait that long--but we might wake up sooner. */
4034 select (0, NULL, NULL, NULL, &timeout);
4038 /* If window is tall, flash top and bottom line. */
4039 if (height > 3 * FRAME_LINE_HEIGHT (f))
4041 mac_invert_rectangle (f, flash_left,
4042 (FRAME_INTERNAL_BORDER_WIDTH (f)
4043 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4044 width, flash_height);
4045 mac_invert_rectangle (f, flash_left,
4046 (height - flash_height
4047 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4048 width, flash_height);
4050 else
4051 /* If it is short, flash it all. */
4052 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4053 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4055 x_flush (f);
4057 UNBLOCK_INPUT;
4060 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4063 /* Make audible bell. */
4065 void
4066 XTring_bell ()
4068 struct frame *f = SELECTED_FRAME ();
4070 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4071 if (visible_bell)
4072 XTflash (f);
4073 else
4074 #endif
4076 BLOCK_INPUT;
4077 mac_alert_sound_play ();
4078 XFlush (FRAME_MAC_DISPLAY (f));
4079 UNBLOCK_INPUT;
4084 /* Specify how many text lines, from the top of the window,
4085 should be affected by insert-lines and delete-lines operations.
4086 This, and those operations, are used only within an update
4087 that is bounded by calls to x_update_begin and x_update_end. */
4089 static void
4090 XTset_terminal_window (n)
4091 register int n;
4093 /* This function intentionally left blank. */
4098 /***********************************************************************
4099 Line Dance
4100 ***********************************************************************/
4102 /* Perform an insert-lines or delete-lines operation, inserting N
4103 lines or deleting -N lines at vertical position VPOS. */
4105 static void
4106 x_ins_del_lines (vpos, n)
4107 int vpos, n;
4109 abort ();
4113 /* Scroll part of the display as described by RUN. */
4115 static void
4116 x_scroll_run (w, run)
4117 struct window *w;
4118 struct run *run;
4120 struct frame *f = XFRAME (w->frame);
4121 int x, y, width, height, from_y, to_y, bottom_y;
4123 /* Get frame-relative bounding box of the text display area of W,
4124 without mode lines. Include in this box the left and right
4125 fringe of W. */
4126 window_box (w, -1, &x, &y, &width, &height);
4128 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4129 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4130 bottom_y = y + height;
4132 if (to_y < from_y)
4134 /* Scrolling up. Make sure we don't copy part of the mode
4135 line at the bottom. */
4136 if (from_y + run->height > bottom_y)
4137 height = bottom_y - from_y;
4138 else
4139 height = run->height;
4141 else
4143 /* Scolling down. Make sure we don't copy over the mode line.
4144 at the bottom. */
4145 if (to_y + run->height > bottom_y)
4146 height = bottom_y - to_y;
4147 else
4148 height = run->height;
4151 BLOCK_INPUT;
4153 /* Cursor off. Will be switched on again in x_update_window_end. */
4154 updated_window = w;
4155 x_clear_cursor (w);
4157 mac_scroll_area (f, f->output_data.mac->normal_gc,
4158 x, from_y,
4159 width, height,
4160 x, to_y);
4162 UNBLOCK_INPUT;
4167 /***********************************************************************
4168 Exposure Events
4169 ***********************************************************************/
4172 static void
4173 frame_highlight (f)
4174 struct frame *f;
4176 x_update_cursor (f, 1);
4179 static void
4180 frame_unhighlight (f)
4181 struct frame *f;
4183 x_update_cursor (f, 1);
4186 /* The focus has changed. Update the frames as necessary to reflect
4187 the new situation. Note that we can't change the selected frame
4188 here, because the Lisp code we are interrupting might become confused.
4189 Each event gets marked with the frame in which it occurred, so the
4190 Lisp code can tell when the switch took place by examining the events. */
4192 static void
4193 x_new_focus_frame (dpyinfo, frame)
4194 struct x_display_info *dpyinfo;
4195 struct frame *frame;
4197 struct frame *old_focus = dpyinfo->x_focus_frame;
4199 if (frame != dpyinfo->x_focus_frame)
4201 /* Set this before calling other routines, so that they see
4202 the correct value of x_focus_frame. */
4203 dpyinfo->x_focus_frame = frame;
4205 if (old_focus && old_focus->auto_lower)
4206 x_lower_frame (old_focus);
4208 #if 0
4209 selected_frame = frame;
4210 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4211 selected_frame);
4212 Fselect_window (selected_frame->selected_window, Qnil);
4213 choose_minibuf_frame ();
4214 #endif /* ! 0 */
4216 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4217 pending_autoraise_frame = dpyinfo->x_focus_frame;
4218 else
4219 pending_autoraise_frame = 0;
4221 #if USE_MAC_FONT_PANEL
4222 if (frame)
4223 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4224 #endif
4227 x_frame_rehighlight (dpyinfo);
4230 /* Handle FocusIn and FocusOut state changes for FRAME.
4231 If FRAME has focus and there exists more than one frame, puts
4232 a FOCUS_IN_EVENT into *BUFP. */
4234 void
4235 mac_focus_changed (type, dpyinfo, frame, bufp)
4236 int type;
4237 struct mac_display_info *dpyinfo;
4238 struct frame *frame;
4239 struct input_event *bufp;
4241 if (type == activeFlag)
4243 if (dpyinfo->x_focus_event_frame != frame)
4245 x_new_focus_frame (dpyinfo, frame);
4246 dpyinfo->x_focus_event_frame = frame;
4248 /* Don't stop displaying the initial startup message
4249 for a switch-frame event we don't need. */
4250 if (GC_NILP (Vterminal_frame)
4251 && GC_CONSP (Vframe_list)
4252 && !GC_NILP (XCDR (Vframe_list)))
4254 bufp->kind = FOCUS_IN_EVENT;
4255 XSETFRAME (bufp->frame_or_window, frame);
4259 else
4261 if (dpyinfo->x_focus_event_frame == frame)
4263 dpyinfo->x_focus_event_frame = 0;
4264 x_new_focus_frame (dpyinfo, 0);
4269 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4271 void
4272 x_mouse_leave (dpyinfo)
4273 struct x_display_info *dpyinfo;
4275 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4278 /* The focus has changed, or we have redirected a frame's focus to
4279 another frame (this happens when a frame uses a surrogate
4280 mini-buffer frame). Shift the highlight as appropriate.
4282 The FRAME argument doesn't necessarily have anything to do with which
4283 frame is being highlighted or un-highlighted; we only use it to find
4284 the appropriate X display info. */
4286 static void
4287 XTframe_rehighlight (frame)
4288 struct frame *frame;
4290 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4293 static void
4294 x_frame_rehighlight (dpyinfo)
4295 struct x_display_info *dpyinfo;
4297 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4299 if (dpyinfo->x_focus_frame)
4301 dpyinfo->x_highlight_frame
4302 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4303 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4304 : dpyinfo->x_focus_frame);
4305 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4307 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4308 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4311 else
4312 dpyinfo->x_highlight_frame = 0;
4314 if (dpyinfo->x_highlight_frame != old_highlight)
4316 if (old_highlight)
4317 frame_unhighlight (old_highlight);
4318 if (dpyinfo->x_highlight_frame)
4319 frame_highlight (dpyinfo->x_highlight_frame);
4325 /* Convert a keysym to its name. */
4327 char *
4328 x_get_keysym_name (keysym)
4329 int keysym;
4331 char *value;
4333 BLOCK_INPUT;
4334 #if 0
4335 value = XKeysymToString (keysym);
4336 #else
4337 value = 0;
4338 #endif
4339 UNBLOCK_INPUT;
4341 return value;
4346 /* Function to report a mouse movement to the mainstream Emacs code.
4347 The input handler calls this.
4349 We have received a mouse movement event, which is given in *event.
4350 If the mouse is over a different glyph than it was last time, tell
4351 the mainstream emacs code by setting mouse_moved. If not, ask for
4352 another motion event, so we can check again the next time it moves. */
4354 static Point last_mouse_motion_position;
4355 static Lisp_Object last_mouse_motion_frame;
4358 note_mouse_movement (frame, pos)
4359 FRAME_PTR frame;
4360 Point *pos;
4362 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4363 Rect r;
4365 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4366 last_mouse_motion_position = *pos;
4367 XSETFRAME (last_mouse_motion_frame, frame);
4369 if (frame == dpyinfo->mouse_face_mouse_frame
4370 && !PtInRect (*pos, mac_get_frame_bounds (frame, &r)))
4372 /* This case corresponds to LeaveNotify in X11. If we move
4373 outside the frame, then we're certainly no longer on any text
4374 in the frame. */
4375 clear_mouse_face (dpyinfo);
4376 dpyinfo->mouse_face_mouse_frame = 0;
4377 if (!dpyinfo->grabbed)
4378 rif->define_frame_cursor (frame,
4379 frame->output_data.mac->nontext_cursor);
4382 /* Has the mouse moved off the glyph it was on at the last sighting? */
4383 if (frame != last_mouse_glyph_frame
4384 || !PtInRect (*pos, &last_mouse_glyph))
4386 frame->mouse_moved = 1;
4387 last_mouse_scroll_bar = Qnil;
4388 note_mouse_highlight (frame, pos->h, pos->v);
4389 /* Remember which glyph we're now on. */
4390 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4391 last_mouse_glyph_frame = frame;
4392 return 1;
4395 return 0;
4399 /************************************************************************
4400 Mouse Face
4401 ************************************************************************/
4403 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4405 static void
4406 redo_mouse_highlight ()
4408 if (!NILP (last_mouse_motion_frame)
4409 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4410 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4411 last_mouse_motion_position.h,
4412 last_mouse_motion_position.v);
4416 struct frame *
4417 mac_focus_frame (dpyinfo)
4418 struct mac_display_info *dpyinfo;
4420 if (dpyinfo->x_focus_frame)
4421 return dpyinfo->x_focus_frame;
4422 else
4423 /* Mac version may get events, such as a menu bar click, even when
4424 all the frames are invisible. In this case, we regard the
4425 event came to the selected frame. */
4426 return SELECTED_FRAME ();
4430 /* Return the current position of the mouse.
4431 *FP should be a frame which indicates which display to ask about.
4433 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4434 and *PART to the frame, window, and scroll bar part that the mouse
4435 is over. Set *X and *Y to the portion and whole of the mouse's
4436 position on the scroll bar.
4438 If the mouse movement started elsewhere, set *FP to the frame the
4439 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4440 the mouse is over.
4442 Set *TIME to the server time-stamp for the time at which the mouse
4443 was at this position.
4445 Don't store anything if we don't have a valid set of values to report.
4447 This clears the mouse_moved flag, so we can wait for the next mouse
4448 movement. */
4450 static void
4451 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4452 FRAME_PTR *fp;
4453 int insist;
4454 Lisp_Object *bar_window;
4455 enum scroll_bar_part *part;
4456 Lisp_Object *x, *y;
4457 unsigned long *time;
4459 FRAME_PTR f1;
4461 BLOCK_INPUT;
4463 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4464 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4465 else
4467 Lisp_Object frame, tail;
4469 /* Clear the mouse-moved flag for every frame on this display. */
4470 FOR_EACH_FRAME (tail, frame)
4471 XFRAME (frame)->mouse_moved = 0;
4473 last_mouse_scroll_bar = Qnil;
4475 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4476 && FRAME_LIVE_P (last_mouse_frame))
4477 f1 = last_mouse_frame;
4478 else
4479 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4481 if (f1)
4483 /* Ok, we found a frame. Store all the values.
4484 last_mouse_glyph is a rectangle used to reduce the
4485 generation of mouse events. To not miss any motion
4486 events, we must divide the frame into rectangles of the
4487 size of the smallest character that could be displayed
4488 on it, i.e. into the same rectangles that matrices on
4489 the frame are divided into. */
4490 Point mouse_pos;
4492 mac_get_frame_mouse (f1, &mouse_pos);
4493 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4494 &last_mouse_glyph);
4495 last_mouse_glyph_frame = f1;
4497 *bar_window = Qnil;
4498 *part = 0;
4499 *fp = f1;
4500 XSETINT (*x, mouse_pos.h);
4501 XSETINT (*y, mouse_pos.v);
4502 *time = last_mouse_movement_time;
4506 UNBLOCK_INPUT;
4510 /************************************************************************
4511 Scroll bars, general
4512 ************************************************************************/
4514 /* Create a scroll bar and return the scroll bar vector for it. W is
4515 the Emacs window on which to create the scroll bar. TOP, LEFT,
4516 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4517 scroll bar. */
4519 static struct scroll_bar *
4520 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4521 struct window *w;
4522 int top, left, width, height, disp_top, disp_height;
4524 struct frame *f = XFRAME (w->frame);
4525 struct scroll_bar *bar
4526 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4527 Rect r;
4529 BLOCK_INPUT;
4531 XSETWINDOW (bar->window, w);
4532 XSETINT (bar->top, top);
4533 XSETINT (bar->left, left);
4534 XSETINT (bar->width, width);
4535 XSETINT (bar->height, height);
4536 #ifdef MAC_OSX
4537 bar->fringe_extended_p = Qnil;
4538 #endif
4539 bar->redraw_needed_p = Qnil;
4541 SetRect (&r, left, disp_top, left + width, disp_top + disp_height);
4542 mac_create_scroll_bar (bar, &r,
4543 #ifdef USE_TOOLKIT_SCROLL_BARS
4544 false
4545 #else
4546 width < disp_height
4547 #endif
4550 /* Add bar to its frame's list of scroll bars. */
4551 bar->next = FRAME_SCROLL_BARS (f);
4552 bar->prev = Qnil;
4553 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4554 if (!NILP (bar->next))
4555 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4557 UNBLOCK_INPUT;
4558 return bar;
4562 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4563 nil. */
4565 static void
4566 x_scroll_bar_remove (bar)
4567 struct scroll_bar *bar;
4569 BLOCK_INPUT;
4571 /* Destroy the Mac scroll bar control */
4572 mac_dispose_scroll_bar (bar);
4574 /* Disassociate this scroll bar from its window. */
4575 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4577 UNBLOCK_INPUT;
4581 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4582 that we are displaying PORTION characters out of a total of WHOLE
4583 characters, starting at POSITION. If WINDOW has no scroll bar,
4584 create one. */
4586 static void
4587 XTset_vertical_scroll_bar (w, portion, whole, position)
4588 struct window *w;
4589 int portion, whole, position;
4591 struct frame *f = XFRAME (w->frame);
4592 struct scroll_bar *bar;
4593 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4594 int window_y, window_height;
4595 #ifdef MAC_OSX
4596 int fringe_extended_p;
4597 #endif
4599 /* Get window dimensions. */
4600 window_box (w, -1, 0, &window_y, 0, &window_height);
4601 top = window_y;
4602 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4603 height = window_height;
4605 /* Compute the left edge of the scroll bar area. */
4606 left = WINDOW_SCROLL_BAR_AREA_X (w);
4608 /* Compute the width of the scroll bar which might be less than
4609 the width of the area reserved for the scroll bar. */
4610 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4611 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4612 else
4613 sb_width = width;
4615 /* Compute the left edge of the scroll bar. */
4616 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4617 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
4618 else
4619 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
4621 /* Adjustments according to Inside Macintosh to make it look nice */
4622 disp_top = top;
4623 disp_height = height;
4624 #ifdef MAC_OS8
4625 if (disp_top == 0)
4627 disp_top = -1;
4628 disp_height++;
4630 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4632 disp_top++;
4633 disp_height--;
4636 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4637 sb_left++;
4638 #endif
4640 #ifdef MAC_OSX
4641 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
4642 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
4643 && WINDOW_LEFT_FRINGE_WIDTH (w)
4644 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4645 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
4646 else
4647 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
4648 && WINDOW_RIGHT_FRINGE_WIDTH (w)
4649 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4650 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
4651 #endif
4653 /* Does the scroll bar exist yet? */
4654 if (NILP (w->vertical_scroll_bar))
4656 BLOCK_INPUT;
4657 #ifdef MAC_OSX
4658 if (fringe_extended_p)
4659 mac_clear_area (f, sb_left, top, sb_width, height);
4660 else
4661 #endif
4662 mac_clear_area (f, left, top, width, height);
4663 UNBLOCK_INPUT;
4664 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4665 disp_height);
4666 XSETVECTOR (w->vertical_scroll_bar, bar);
4668 else
4670 /* It may just need to be moved and resized. */
4671 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4673 BLOCK_INPUT;
4675 /* If already correctly positioned, do nothing. */
4676 if (XINT (bar->left) == sb_left
4677 && XINT (bar->top) == top
4678 && XINT (bar->width) == sb_width
4679 && XINT (bar->height) == height
4680 #ifdef MAC_OSX
4681 && !NILP (bar->fringe_extended_p) == fringe_extended_p
4682 #endif
4685 if (!NILP (bar->redraw_needed_p))
4686 mac_redraw_scroll_bar (bar);
4688 else
4690 Rect r;
4692 /* Since toolkit scroll bars are smaller than the space reserved
4693 for them on the frame, we have to clear "under" them. */
4694 #ifdef MAC_OSX
4695 if (fringe_extended_p)
4696 mac_clear_area (f, sb_left, top, sb_width, height);
4697 else
4698 #endif
4699 mac_clear_area (f, left, top, width, height);
4701 SetRect (&r, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top,
4702 sb_left + sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4703 disp_top + disp_height);
4704 mac_set_scroll_bar_bounds (bar, &r);
4706 /* Remember new settings. */
4707 XSETINT (bar->left, sb_left);
4708 XSETINT (bar->top, top);
4709 XSETINT (bar->width, sb_width);
4710 XSETINT (bar->height, height);
4713 UNBLOCK_INPUT;
4716 #ifdef MAC_OSX
4717 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
4718 #endif
4719 bar->redraw_needed_p = Qnil;
4721 #ifdef USE_TOOLKIT_SCROLL_BARS
4722 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4723 #else /* not USE_TOOLKIT_SCROLL_BARS */
4724 /* Set the scroll bar's current state, unless we're currently being
4725 dragged. */
4726 if (NILP (bar->dragging))
4728 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4730 if (whole == 0)
4731 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4732 else
4734 int start = ((double) position * top_range) / whole;
4735 int end = ((double) (position + portion) * top_range) / whole;
4736 x_scroll_bar_set_handle (bar, start, end, 0);
4739 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4743 /* The following three hooks are used when we're doing a thorough
4744 redisplay of the frame. We don't explicitly know which scroll bars
4745 are going to be deleted, because keeping track of when windows go
4746 away is a real pain - "Can you say set-window-configuration, boys
4747 and girls?" Instead, we just assert at the beginning of redisplay
4748 that *all* scroll bars are to be removed, and then save a scroll bar
4749 from the fiery pit when we actually redisplay its window. */
4751 /* Arrange for all scroll bars on FRAME to be removed at the next call
4752 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4753 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4755 static void
4756 XTcondemn_scroll_bars (frame)
4757 FRAME_PTR frame;
4759 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4760 while (! NILP (FRAME_SCROLL_BARS (frame)))
4762 Lisp_Object bar;
4763 bar = FRAME_SCROLL_BARS (frame);
4764 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4765 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4766 XSCROLL_BAR (bar)->prev = Qnil;
4767 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4768 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4769 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4774 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4775 Note that WINDOW isn't necessarily condemned at all. */
4777 static void
4778 XTredeem_scroll_bar (window)
4779 struct window *window;
4781 struct scroll_bar *bar;
4782 struct frame *f;
4784 /* We can't redeem this window's scroll bar if it doesn't have one. */
4785 if (NILP (window->vertical_scroll_bar))
4786 abort ();
4788 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4790 /* Unlink it from the condemned list. */
4791 f = XFRAME (WINDOW_FRAME (window));
4792 if (NILP (bar->prev))
4794 /* If the prev pointer is nil, it must be the first in one of
4795 the lists. */
4796 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4797 /* It's not condemned. Everything's fine. */
4798 return;
4799 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4800 window->vertical_scroll_bar))
4801 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4802 else
4803 /* If its prev pointer is nil, it must be at the front of
4804 one or the other! */
4805 abort ();
4807 else
4808 XSCROLL_BAR (bar->prev)->next = bar->next;
4810 if (! NILP (bar->next))
4811 XSCROLL_BAR (bar->next)->prev = bar->prev;
4813 bar->next = FRAME_SCROLL_BARS (f);
4814 bar->prev = Qnil;
4815 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4816 if (! NILP (bar->next))
4817 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4820 /* Remove all scroll bars on FRAME that haven't been saved since the
4821 last call to `*condemn_scroll_bars_hook'. */
4823 static void
4824 XTjudge_scroll_bars (f)
4825 FRAME_PTR f;
4827 Lisp_Object bar, next;
4829 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4831 /* Clear out the condemned list now so we won't try to process any
4832 more events on the hapless scroll bars. */
4833 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4835 for (; ! NILP (bar); bar = next)
4837 struct scroll_bar *b = XSCROLL_BAR (bar);
4839 x_scroll_bar_remove (b);
4841 next = b->next;
4842 b->next = b->prev = Qnil;
4845 /* Now there should be no references to the condemned scroll bars,
4846 and they should get garbage-collected. */
4849 /* The screen has been cleared so we may have changed foreground or
4850 background colors, and the scroll bars may need to be redrawn.
4851 Clear out the scroll bars, and ask for expose events, so we can
4852 redraw them. */
4854 void
4855 x_scroll_bar_clear (f)
4856 FRAME_PTR f;
4858 Lisp_Object bar;
4860 /* We can have scroll bars even if this is 0,
4861 if we just turned off scroll bar mode.
4862 But in that case we should not clear them. */
4863 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4864 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4865 bar = XSCROLL_BAR (bar)->next)
4866 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
4870 /***********************************************************************
4871 Tool-bars
4872 ***********************************************************************/
4873 #if USE_MAC_TOOLBAR
4874 void
4875 mac_move_window_with_gravity (f, win_gravity, left, top)
4876 struct frame *f;
4877 int win_gravity;
4878 short left, top;
4880 Rect inner, outer;
4882 mac_get_window_bounds (f, &inner, &outer);
4884 switch (win_gravity)
4886 case NorthWestGravity:
4887 case WestGravity:
4888 case SouthWestGravity:
4889 left += inner.left - outer.left;
4890 break;
4892 case NorthGravity:
4893 case CenterGravity:
4894 case SouthGravity:
4895 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
4896 break;
4898 case NorthEastGravity:
4899 case EastGravity:
4900 case SouthEastGravity:
4901 left += inner.right - outer.right;
4902 break;
4905 switch (win_gravity)
4907 case NorthWestGravity:
4908 case NorthGravity:
4909 case NorthEastGravity:
4910 top += inner.top - outer.top;
4911 break;
4913 case WestGravity:
4914 case CenterGravity:
4915 case EastGravity:
4916 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
4917 break;
4919 case SouthWestGravity:
4920 case SouthGravity:
4921 case SouthEastGravity:
4922 top += inner.bottom - outer.bottom;
4923 break;
4926 mac_move_window (FRAME_MAC_WINDOW (f), left, top, false);
4929 void
4930 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
4931 struct frame *f;
4932 int win_gravity;
4933 short *left, *top;
4935 Rect inner, outer;
4937 mac_get_window_bounds (f, &inner, &outer);
4939 switch (win_gravity)
4941 case NorthWestGravity:
4942 case WestGravity:
4943 case SouthWestGravity:
4944 *left = outer.left;
4945 break;
4947 case NorthGravity:
4948 case CenterGravity:
4949 case SouthGravity:
4950 *left = outer.left + ((outer.right - outer.left)
4951 - (inner.right - inner.left)) / 2;
4952 break;
4954 case NorthEastGravity:
4955 case EastGravity:
4956 case SouthEastGravity:
4957 *left = outer.right - (inner.right - inner.left);
4958 break;
4961 switch (win_gravity)
4963 case NorthWestGravity:
4964 case NorthGravity:
4965 case NorthEastGravity:
4966 *top = outer.top;
4967 break;
4969 case WestGravity:
4970 case CenterGravity:
4971 case EastGravity:
4972 *top = outer.top + ((outer.bottom - outer.top)
4973 - (inner.bottom - inner.top)) / 2;
4974 break;
4976 case SouthWestGravity:
4977 case SouthGravity:
4978 case SouthEastGravity:
4979 *top = outer.bottom - (inner.bottom - inner.top);
4980 break;
4984 CGImageRef
4985 mac_image_spec_to_cg_image (f, image)
4986 struct frame *f;
4987 Lisp_Object image;
4989 if (!valid_image_p (image))
4990 return NULL;
4991 else
4993 int img_id = lookup_image (f, image);
4994 struct image *img = IMAGE_FROM_ID (f, img_id);
4996 prepare_image_for_display (f, img);
4998 return img->data.ptr_val;
5001 #endif /* USE_MAC_TOOLBAR */
5004 /***********************************************************************
5005 Text Cursor
5006 ***********************************************************************/
5008 /* Set clipping for output in glyph row ROW. W is the window in which
5009 we operate. GC is the graphics context to set clipping in.
5011 ROW may be a text row or, e.g., a mode line. Text rows must be
5012 clipped to the interior of the window dedicated to text display,
5013 mode lines must be clipped to the whole window. */
5015 static void
5016 x_clip_to_row (w, row, area, gc)
5017 struct window *w;
5018 struct glyph_row *row;
5019 int area;
5020 GC gc;
5022 struct frame *f = XFRAME (WINDOW_FRAME (w));
5023 Rect clip_rect;
5024 int window_x, window_y, window_width;
5026 window_box (w, area, &window_x, &window_y, &window_width, 0);
5028 clip_rect.left = window_x;
5029 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5030 clip_rect.top = max (clip_rect.top, window_y);
5031 clip_rect.right = clip_rect.left + window_width;
5032 clip_rect.bottom = clip_rect.top + row->visible_height;
5034 mac_set_clip_rectangles (f, gc, &clip_rect, 1);
5038 /* Draw a hollow box cursor on window W in glyph row ROW. */
5040 static void
5041 x_draw_hollow_cursor (w, row)
5042 struct window *w;
5043 struct glyph_row *row;
5045 struct frame *f = XFRAME (WINDOW_FRAME (w));
5046 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5047 Display *dpy = FRAME_MAC_DISPLAY (f);
5048 int x, y, wd, h;
5049 XGCValues xgcv;
5050 struct glyph *cursor_glyph;
5051 GC gc;
5053 /* Get the glyph the cursor is on. If we can't tell because
5054 the current matrix is invalid or such, give up. */
5055 cursor_glyph = get_phys_cursor_glyph (w);
5056 if (cursor_glyph == NULL)
5057 return;
5059 /* Compute frame-relative coordinates for phys cursor. */
5060 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5061 wd = w->phys_cursor_width;
5063 /* The foreground of cursor_gc is typically the same as the normal
5064 background color, which can cause the cursor box to be invisible. */
5065 xgcv.foreground = f->output_data.mac->cursor_pixel;
5066 if (dpyinfo->scratch_cursor_gc)
5067 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5068 else
5069 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5070 GCForeground, &xgcv);
5071 gc = dpyinfo->scratch_cursor_gc;
5073 /* Set clipping, draw the rectangle, and reset clipping again. */
5074 x_clip_to_row (w, row, TEXT_AREA, gc);
5075 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5076 mac_reset_clip_rectangles (f, gc);
5080 /* Draw a bar cursor on window W in glyph row ROW.
5082 Implementation note: One would like to draw a bar cursor with an
5083 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5084 Unfortunately, I didn't find a font yet that has this property set.
5085 --gerd. */
5087 static void
5088 x_draw_bar_cursor (w, row, width, kind)
5089 struct window *w;
5090 struct glyph_row *row;
5091 int width;
5092 enum text_cursor_kinds kind;
5094 struct frame *f = XFRAME (w->frame);
5095 struct glyph *cursor_glyph;
5097 /* If cursor is out of bounds, don't draw garbage. This can happen
5098 in mini-buffer windows when switching between echo area glyphs
5099 and mini-buffer. */
5100 cursor_glyph = get_phys_cursor_glyph (w);
5101 if (cursor_glyph == NULL)
5102 return;
5104 /* If on an image, draw like a normal cursor. That's usually better
5105 visible than drawing a bar, esp. if the image is large so that
5106 the bar might not be in the window. */
5107 if (cursor_glyph->type == IMAGE_GLYPH)
5109 struct glyph_row *row;
5110 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5111 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5113 else
5115 Display *dpy = FRAME_MAC_DISPLAY (f);
5116 Window window = FRAME_MAC_WINDOW (f);
5117 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5118 unsigned long mask = GCForeground | GCBackground;
5119 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5120 XGCValues xgcv;
5122 /* If the glyph's background equals the color we normally draw
5123 the bar cursor in, the bar cursor in its normal color is
5124 invisible. Use the glyph's foreground color instead in this
5125 case, on the assumption that the glyph's colors are chosen so
5126 that the glyph is legible. */
5127 if (face->background == f->output_data.mac->cursor_pixel)
5128 xgcv.background = xgcv.foreground = face->foreground;
5129 else
5130 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5132 if (gc)
5133 XChangeGC (dpy, gc, mask, &xgcv);
5134 else
5136 gc = XCreateGC (dpy, window, mask, &xgcv);
5137 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5140 if (width < 0)
5141 width = FRAME_CURSOR_WIDTH (f);
5142 width = min (cursor_glyph->pixel_width, width);
5144 w->phys_cursor_width = width;
5145 x_clip_to_row (w, row, TEXT_AREA, gc);
5147 if (kind == BAR_CURSOR)
5148 mac_fill_rectangle (f, gc,
5149 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5150 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5151 width, row->height);
5152 else
5153 mac_fill_rectangle (f, gc,
5154 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5155 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5156 row->height - width),
5157 cursor_glyph->pixel_width,
5158 width);
5160 mac_reset_clip_rectangles (f, gc);
5165 /* RIF: Define cursor CURSOR on frame F. */
5167 static void
5168 mac_define_frame_cursor (f, cursor)
5169 struct frame *f;
5170 Cursor cursor;
5172 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5174 if (dpyinfo->x_focus_frame == f)
5175 SetThemeCursor (cursor);
5179 /* RIF: Clear area on frame F. */
5181 static void
5182 mac_clear_frame_area (f, x, y, width, height)
5183 struct frame *f;
5184 int x, y, width, height;
5186 mac_clear_area (f, x, y, width, height);
5190 /* RIF: Draw cursor on window W. */
5192 static void
5193 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5194 struct window *w;
5195 struct glyph_row *glyph_row;
5196 int x, y;
5197 int cursor_type, cursor_width;
5198 int on_p, active_p;
5200 if (on_p)
5202 w->phys_cursor_type = cursor_type;
5203 w->phys_cursor_on_p = 1;
5205 if (glyph_row->exact_window_width_line_p
5206 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5208 glyph_row->cursor_in_fringe_p = 1;
5209 draw_fringe_bitmap (w, glyph_row, 0);
5211 else
5212 switch (cursor_type)
5214 case HOLLOW_BOX_CURSOR:
5215 x_draw_hollow_cursor (w, glyph_row);
5216 break;
5218 case FILLED_BOX_CURSOR:
5219 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5220 break;
5222 case BAR_CURSOR:
5223 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5224 break;
5226 case HBAR_CURSOR:
5227 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5228 break;
5230 case NO_CURSOR:
5231 w->phys_cursor_width = 0;
5232 break;
5234 default:
5235 abort ();
5241 /* Icons. */
5243 #if 0 /* MAC_TODO: no icon support yet. */
5245 x_bitmap_icon (f, icon)
5246 struct frame *f;
5247 Lisp_Object icon;
5249 HANDLE hicon;
5251 if (FRAME_W32_WINDOW (f) == 0)
5252 return 1;
5254 if (NILP (icon))
5255 hicon = LoadIcon (hinst, EMACS_CLASS);
5256 else if (STRINGP (icon))
5257 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5258 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5259 else if (SYMBOLP (icon))
5261 LPCTSTR name;
5263 if (EQ (icon, intern ("application")))
5264 name = (LPCTSTR) IDI_APPLICATION;
5265 else if (EQ (icon, intern ("hand")))
5266 name = (LPCTSTR) IDI_HAND;
5267 else if (EQ (icon, intern ("question")))
5268 name = (LPCTSTR) IDI_QUESTION;
5269 else if (EQ (icon, intern ("exclamation")))
5270 name = (LPCTSTR) IDI_EXCLAMATION;
5271 else if (EQ (icon, intern ("asterisk")))
5272 name = (LPCTSTR) IDI_ASTERISK;
5273 else if (EQ (icon, intern ("winlogo")))
5274 name = (LPCTSTR) IDI_WINLOGO;
5275 else
5276 return 1;
5278 hicon = LoadIcon (NULL, name);
5280 else
5281 return 1;
5283 if (hicon == NULL)
5284 return 1;
5286 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5287 (LPARAM) hicon);
5289 return 0;
5291 #endif /* MAC_TODO */
5293 /************************************************************************
5294 Handling X errors
5295 ************************************************************************/
5297 /* Display Error Handling functions not used on W32. Listing them here
5298 helps diff stay in step when comparing w32term.c with xterm.c.
5300 x_error_catcher (display, error)
5301 x_catch_errors (dpy)
5302 x_catch_errors_unwind (old_val)
5303 x_check_errors (dpy, format)
5304 x_had_errors_p (dpy)
5305 x_clear_errors (dpy)
5306 x_uncatch_errors (dpy, count)
5307 x_trace_wire ()
5308 x_connection_signal (signalnum)
5309 x_connection_closed (dpy, error_message)
5310 x_error_quitter (display, error)
5311 x_error_handler (display, error)
5312 x_io_error_quitter (display)
5317 /* Changing the font of the frame. */
5319 /* Give frame F the font named FONTNAME as its default font, and
5320 return the full name of that font. FONTNAME may be a wildcard
5321 pattern; in that case, we choose some font that fits the pattern.
5322 The return value shows which font we chose. */
5324 Lisp_Object
5325 x_new_font (f, fontname)
5326 struct frame *f;
5327 register char *fontname;
5329 struct font_info *fontp
5330 = FS_LOAD_FONT (f, 0, fontname, -1);
5332 if (!fontp)
5333 return Qnil;
5335 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5336 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5337 FRAME_FONTSET (f) = -1;
5339 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5340 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5341 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5343 compute_fringe_widths (f, 1);
5345 /* Compute the scroll bar width in character columns. */
5346 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5348 int wid = FRAME_COLUMN_WIDTH (f);
5349 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5350 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5352 else
5354 int wid = FRAME_COLUMN_WIDTH (f);
5355 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5358 /* Now make the frame display the given font. */
5359 if (FRAME_MAC_WINDOW (f) != 0)
5361 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5362 FRAME_FONT (f));
5363 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5364 FRAME_FONT (f));
5365 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5366 FRAME_FONT (f));
5368 /* Don't change the size of a tip frame; there's no point in
5369 doing it because it's done in Fx_show_tip, and it leads to
5370 problems because the tip frame has no widget. */
5371 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5372 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5375 return build_string (fontp->full_name);
5378 /* Give frame F the fontset named FONTSETNAME as its default font, and
5379 return the full name of that fontset. FONTSETNAME may be a wildcard
5380 pattern; in that case, we choose some fontset that fits the pattern.
5381 The return value shows which fontset we chose. */
5383 Lisp_Object
5384 x_new_fontset (f, fontsetname)
5385 struct frame *f;
5386 char *fontsetname;
5388 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5389 Lisp_Object result;
5391 if (fontset < 0)
5392 return Qnil;
5394 if (FRAME_FONTSET (f) == fontset)
5395 /* This fontset is already set in frame F. There's nothing more
5396 to do. */
5397 return fontset_name (fontset);
5399 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5401 if (!STRINGP (result))
5402 /* Can't load ASCII font. */
5403 return Qnil;
5405 /* Since x_new_font doesn't update any fontset information, do it now. */
5406 FRAME_FONTSET (f) = fontset;
5408 return build_string (fontsetname);
5412 /***********************************************************************
5413 TODO: W32 Input Methods
5414 ***********************************************************************/
5415 /* Listing missing functions from xterm.c helps diff stay in step.
5417 xim_destroy_callback (xim, client_data, call_data)
5418 xim_open_dpy (dpyinfo, resource_name)
5419 struct xim_inst_t
5420 xim_instantiate_callback (display, client_data, call_data)
5421 xim_initialize (dpyinfo, resource_name)
5422 xim_close_dpy (dpyinfo)
5427 void
5428 mac_handle_origin_change (f)
5429 struct frame *f;
5431 x_real_positions (f, &f->left_pos, &f->top_pos);
5434 void
5435 mac_handle_size_change (f, pixelwidth, pixelheight)
5436 struct frame *f;
5437 int pixelwidth, pixelheight;
5439 int cols, rows;
5441 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
5442 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
5444 if (cols != FRAME_COLS (f)
5445 || rows != FRAME_LINES (f)
5446 || pixelwidth != FRAME_PIXEL_WIDTH (f)
5447 || pixelheight != FRAME_PIXEL_HEIGHT (f))
5449 /* We pass 1 for DELAY since we can't run Lisp code inside of
5450 a BLOCK_INPUT. */
5451 change_frame_size (f, rows, cols, 0, 1, 0);
5452 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5453 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5455 /* If cursor was outside the new size, mark it as off. */
5456 mark_window_cursors_off (XWINDOW (f->root_window));
5458 /* Clear out any recollection of where the mouse highlighting
5459 was, since it might be in a place that's outside the new
5460 frame size. Actually checking whether it is outside is a
5461 pain in the neck, so don't try--just let the highlighting be
5462 done afresh with new size. */
5463 cancel_mouse_face (f);
5465 #if TARGET_API_MAC_CARBON
5466 mac_reposition_hourglass (f);
5467 #endif
5472 /* Calculate the absolute position in frame F
5473 from its current recorded position values and gravity. */
5475 void
5476 x_calc_absolute_position (f)
5477 struct frame *f;
5479 int flags = f->size_hint_flags;
5480 Rect inner, outer;
5482 /* We have nothing to do if the current position
5483 is already for the top-left corner. */
5484 if (! ((flags & XNegative) || (flags & YNegative)))
5485 return;
5487 /* Find the offsets of the outside upper-left corner of
5488 the inner window, with respect to the outer window. */
5489 BLOCK_INPUT;
5490 mac_get_window_bounds (f, &inner, &outer);
5491 UNBLOCK_INPUT;
5493 /* Treat negative positions as relative to the leftmost bottommost
5494 position that fits on the screen. */
5495 if (flags & XNegative)
5496 f->left_pos += (FRAME_MAC_DISPLAY_INFO (f)->width
5497 - (outer.right - outer.left));
5499 if (flags & YNegative)
5500 f->top_pos += (FRAME_MAC_DISPLAY_INFO (f)->height
5501 - (outer.bottom - outer.top));
5503 /* The left_pos and top_pos
5504 are now relative to the top and left screen edges,
5505 so the flags should correspond. */
5506 f->size_hint_flags &= ~ (XNegative | YNegative);
5509 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5510 to really change the position, and 0 when calling from
5511 x_make_frame_visible (in that case, XOFF and YOFF are the current
5512 position values). It is -1 when calling from x_set_frame_parameters,
5513 which means, do adjust for borders but don't change the gravity. */
5515 void
5516 x_set_offset (f, xoff, yoff, change_gravity)
5517 struct frame *f;
5518 register int xoff, yoff;
5519 int change_gravity;
5521 if (change_gravity > 0)
5523 f->top_pos = yoff;
5524 f->left_pos = xoff;
5525 f->size_hint_flags &= ~ (XNegative | YNegative);
5526 if (xoff < 0)
5527 f->size_hint_flags |= XNegative;
5528 if (yoff < 0)
5529 f->size_hint_flags |= YNegative;
5530 f->win_gravity = NorthWestGravity;
5532 x_calc_absolute_position (f);
5534 BLOCK_INPUT;
5535 x_wm_set_size_hint (f, (long) 0, 0);
5537 #if TARGET_API_MAC_CARBON
5538 mac_move_window_structure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5539 /* If the title bar is completely outside the screen, adjust the
5540 position. */
5541 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5542 kWindowConstrainMoveRegardlessOfFit
5543 | kWindowConstrainAllowPartial, NULL, NULL);
5544 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
5545 mac_handle_origin_change (f);
5546 #else
5548 Rect inner, outer, screen_rect, dummy;
5549 RgnHandle region = NewRgn ();
5551 mac_get_window_bounds (f, &inner, &outer);
5552 f->x_pixels_diff = inner.left - outer.left;
5553 f->y_pixels_diff = inner.top - outer.top;
5554 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5555 f->top_pos + f->y_pixels_diff, false);
5557 /* If the title bar is completely outside the screen, adjust the
5558 position. The variable `outer' holds the title bar rectangle.
5559 The variable `inner' holds slightly smaller one than `outer',
5560 so that the calculation of overlapping may not become too
5561 strict. */
5562 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5563 outer = (*region)->rgnBBox;
5564 DisposeRgn (region);
5565 inner = outer;
5566 InsetRect (&inner, 8, 8);
5567 screen_rect = qd.screenBits.bounds;
5568 screen_rect.top += GetMBarHeight ();
5570 if (!SectRect (&inner, &screen_rect, &dummy))
5572 if (inner.right <= screen_rect.left)
5573 f->left_pos = screen_rect.left;
5574 else if (inner.left >= screen_rect.right)
5575 f->left_pos = screen_rect.right - (outer.right - outer.left);
5577 if (inner.bottom <= screen_rect.top)
5578 f->top_pos = screen_rect.top;
5579 else if (inner.top >= screen_rect.bottom)
5580 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5582 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5583 f->top_pos + f->y_pixels_diff, false);
5586 #endif
5588 UNBLOCK_INPUT;
5591 /* Call this to change the size of frame F's x-window.
5592 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5593 for this size change and subsequent size changes.
5594 Otherwise we leave the window gravity unchanged. */
5596 void
5597 x_set_window_size (f, change_gravity, cols, rows)
5598 struct frame *f;
5599 int change_gravity;
5600 int cols, rows;
5602 int pixelwidth, pixelheight;
5604 BLOCK_INPUT;
5606 check_frame_size (f, &rows, &cols);
5607 f->scroll_bar_actual_width
5608 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5610 compute_fringe_widths (f, 0);
5612 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5613 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5615 f->win_gravity = NorthWestGravity;
5616 x_wm_set_size_hint (f, (long) 0, 0);
5618 mac_size_window (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5620 #if TARGET_API_MAC_CARBON
5621 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
5622 #endif
5623 mac_handle_size_change (f, pixelwidth, pixelheight);
5625 if (f->output_data.mac->internal_border_width
5626 != FRAME_INTERNAL_BORDER_WIDTH (f))
5628 mac_clear_window (f);
5629 f->output_data.mac->internal_border_width
5630 = FRAME_INTERNAL_BORDER_WIDTH (f);
5633 SET_FRAME_GARBAGED (f);
5635 UNBLOCK_INPUT;
5638 /* Mouse warping. */
5640 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5642 void
5643 x_set_mouse_position (f, x, y)
5644 struct frame *f;
5645 int x, y;
5647 int pix_x, pix_y;
5649 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5650 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5652 if (pix_x < 0) pix_x = 0;
5653 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5655 if (pix_y < 0) pix_y = 0;
5656 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5658 x_set_mouse_pixel_position (f, pix_x, pix_y);
5661 void
5662 x_set_mouse_pixel_position (f, pix_x, pix_y)
5663 struct frame *f;
5664 int pix_x, pix_y;
5666 #ifdef MAC_OSX
5667 BLOCK_INPUT;
5668 mac_convert_frame_point_to_global (f, &pix_x, &pix_y);
5669 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
5670 UNBLOCK_INPUT;
5671 #else
5672 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
5673 BLOCK_INPUT;
5675 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5676 0, 0, 0, 0, pix_x, pix_y);
5677 UNBLOCK_INPUT;
5678 #endif
5679 #endif
5682 /* focus shifting, raising and lowering. */
5684 void
5685 x_focus_on_frame (f)
5686 struct frame *f;
5688 #if 0 /* This proves to be unpleasant. */
5689 x_raise_frame (f);
5690 #endif
5691 #if 0
5692 /* I don't think that the ICCCM allows programs to do things like this
5693 without the interaction of the window manager. Whatever you end up
5694 doing with this code, do it to x_unfocus_frame too. */
5695 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5696 RevertToPointerRoot, CurrentTime);
5697 #endif /* ! 0 */
5700 void
5701 x_unfocus_frame (f)
5702 struct frame *f;
5706 /* Raise frame F. */
5708 void
5709 x_raise_frame (f)
5710 struct frame *f;
5712 if (f->async_visible)
5714 BLOCK_INPUT;
5715 mac_bring_window_to_front (FRAME_MAC_WINDOW (f));
5716 UNBLOCK_INPUT;
5720 /* Lower frame F. */
5722 void
5723 x_lower_frame (f)
5724 struct frame *f;
5726 if (f->async_visible)
5728 BLOCK_INPUT;
5729 mac_send_window_behind (FRAME_MAC_WINDOW (f), NULL);
5730 UNBLOCK_INPUT;
5734 static void
5735 XTframe_raise_lower (f, raise_flag)
5736 FRAME_PTR f;
5737 int raise_flag;
5739 if (raise_flag)
5740 x_raise_frame (f);
5741 else
5742 x_lower_frame (f);
5745 /* Change of visibility. */
5747 void
5748 mac_handle_visibility_change (f)
5749 struct frame *f;
5751 Window wp = FRAME_MAC_WINDOW (f);
5752 int visible = 0, iconified = 0;
5753 struct input_event buf;
5755 if (mac_is_window_visible (wp))
5757 if (mac_is_window_collapsed (wp))
5758 iconified = 1;
5759 else
5760 visible = 1;
5763 if (!f->async_visible && visible)
5765 if (f->iconified)
5767 /* wait_reading_process_output will notice this and update
5768 the frame's display structures. If we were made
5769 invisible, we should not set garbaged, because that stops
5770 redrawing on Update events. */
5771 SET_FRAME_GARBAGED (f);
5773 EVENT_INIT (buf);
5774 buf.kind = DEICONIFY_EVENT;
5775 XSETFRAME (buf.frame_or_window, f);
5776 buf.arg = Qnil;
5777 kbd_buffer_store_event (&buf);
5779 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
5780 /* Force a redisplay sooner or later to update the
5781 frame titles in case this is the second frame. */
5782 record_asynch_buffer_change ();
5784 else if (f->async_visible && !visible)
5785 if (iconified)
5787 EVENT_INIT (buf);
5788 buf.kind = ICONIFY_EVENT;
5789 XSETFRAME (buf.frame_or_window, f);
5790 buf.arg = Qnil;
5791 kbd_buffer_store_event (&buf);
5794 f->async_visible = visible;
5795 f->async_iconified = iconified;
5798 /* This tries to wait until the frame is really visible.
5799 However, if the window manager asks the user where to position
5800 the frame, this will return before the user finishes doing that.
5801 The frame will not actually be visible at that time,
5802 but it will become visible later when the window manager
5803 finishes with it. */
5805 void
5806 x_make_frame_visible (f)
5807 struct frame *f;
5809 BLOCK_INPUT;
5811 if (! FRAME_VISIBLE_P (f))
5813 /* We test FRAME_GARBAGED_P here to make sure we don't
5814 call x_set_offset a second time
5815 if we get to x_make_frame_visible a second time
5816 before the window gets really visible. */
5817 if (! FRAME_ICONIFIED_P (f)
5818 && ! f->output_data.mac->asked_for_visible)
5819 x_set_offset (f, f->left_pos, f->top_pos, 0);
5821 f->output_data.mac->asked_for_visible = 1;
5823 mac_collapse_window (FRAME_MAC_WINDOW (f), false);
5824 mac_show_window (FRAME_MAC_WINDOW (f));
5827 XFlush (FRAME_MAC_DISPLAY (f));
5829 /* Synchronize to ensure Emacs knows the frame is visible
5830 before we do anything else. We do this loop with input not blocked
5831 so that incoming events are handled. */
5833 Lisp_Object frame;
5834 int count;
5836 /* This must come after we set COUNT. */
5837 UNBLOCK_INPUT;
5839 XSETFRAME (frame, f);
5841 /* Wait until the frame is visible. Process X events until a
5842 MapNotify event has been seen, or until we think we won't get a
5843 MapNotify at all.. */
5844 for (count = input_signal_count + 10;
5845 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5847 /* Force processing of queued events. */
5848 x_sync (f);
5850 /* Machines that do polling rather than SIGIO have been
5851 observed to go into a busy-wait here. So we'll fake an
5852 alarm signal to let the handler know that there's something
5853 to be read. We used to raise a real alarm, but it seems
5854 that the handler isn't always enabled here. This is
5855 probably a bug. */
5856 if (input_polling_used ())
5858 /* It could be confusing if a real alarm arrives while
5859 processing the fake one. Turn it off and let the
5860 handler reset it. */
5861 extern void poll_for_input_1 P_ ((void));
5862 int old_poll_suppress_count = poll_suppress_count;
5863 poll_suppress_count = 1;
5864 poll_for_input_1 ();
5865 poll_suppress_count = old_poll_suppress_count;
5868 /* See if a MapNotify event has been processed. */
5869 FRAME_SAMPLE_VISIBILITY (f);
5874 /* Change from mapped state to withdrawn state. */
5876 /* Make the frame visible (mapped and not iconified). */
5878 void
5879 x_make_frame_invisible (f)
5880 struct frame *f;
5882 /* A deactivate event does not occur when the last visible frame is
5883 made invisible. So if we clear the highlight here, it will not
5884 be rehighlighted when it is made visible. */
5885 #if 0
5886 /* Don't keep the highlight on an invisible frame. */
5887 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5888 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5889 #endif
5891 BLOCK_INPUT;
5893 #if !TARGET_API_MAC_CARBON
5894 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5895 that the current position of the window is user-specified, rather than
5896 program-specified, so that when the window is mapped again, it will be
5897 placed at the same location, without forcing the user to position it
5898 by hand again (they have already done that once for this window.) */
5899 x_wm_set_size_hint (f, (long) 0, 1);
5900 #endif
5902 mac_hide_window (FRAME_MAC_WINDOW (f));
5904 UNBLOCK_INPUT;
5906 #if !TARGET_API_MAC_CARBON
5907 mac_handle_visibility_change (f);
5908 #endif
5911 /* Change window state from mapped to iconified. */
5913 void
5914 x_iconify_frame (f)
5915 struct frame *f;
5917 OSStatus err;
5919 /* A deactivate event does not occur when the last visible frame is
5920 iconified. So if we clear the highlight here, it will not be
5921 rehighlighted when it is deiconified. */
5922 #if 0
5923 /* Don't keep the highlight on an invisible frame. */
5924 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5925 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5926 #endif
5928 if (f->async_iconified)
5929 return;
5931 BLOCK_INPUT;
5933 FRAME_SAMPLE_VISIBILITY (f);
5935 if (! FRAME_VISIBLE_P (f))
5936 mac_show_window (FRAME_MAC_WINDOW (f));
5938 err = mac_collapse_window (FRAME_MAC_WINDOW (f), true);
5940 UNBLOCK_INPUT;
5942 if (err != noErr)
5943 error ("Can't notify window manager of iconification");
5945 #if !TARGET_API_MAC_CARBON
5946 mac_handle_visibility_change (f);
5947 #endif
5951 /* Free X resources of frame F. */
5953 void
5954 x_free_frame_resources (f)
5955 struct frame *f;
5957 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5958 Window wp = FRAME_MAC_WINDOW (f);
5960 BLOCK_INPUT;
5962 /* AppKit version of mac_dispose_frame_window, which is implemented
5963 as -[NSWindow close], will change the focus to the next window
5964 during its call. So, unlike other platforms, we clean up the
5965 focus-related variables before calling mac_dispose_frame_window. */
5966 if (f == dpyinfo->x_focus_frame)
5968 dpyinfo->x_focus_frame = 0;
5969 #if USE_MAC_FONT_PANEL
5970 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
5971 #endif
5973 if (f == dpyinfo->x_focus_event_frame)
5974 dpyinfo->x_focus_event_frame = 0;
5975 if (f == dpyinfo->x_highlight_frame)
5976 dpyinfo->x_highlight_frame = 0;
5978 if (f == dpyinfo->mouse_face_mouse_frame)
5980 dpyinfo->mouse_face_beg_row
5981 = dpyinfo->mouse_face_beg_col = -1;
5982 dpyinfo->mouse_face_end_row
5983 = dpyinfo->mouse_face_end_col = -1;
5984 dpyinfo->mouse_face_window = Qnil;
5985 dpyinfo->mouse_face_deferred_gc = 0;
5986 dpyinfo->mouse_face_mouse_frame = 0;
5989 mac_dispose_frame_window (f);
5990 if (wp == tip_window)
5991 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5992 closed' event. So we reset tip_window here. */
5993 tip_window = NULL;
5995 free_frame_menubar (f);
5997 if (FRAME_FACE_CACHE (f))
5998 free_frame_faces (f);
6000 x_free_gcs (f);
6002 if (FRAME_SIZE_HINTS (f))
6003 xfree (FRAME_SIZE_HINTS (f));
6005 xfree (f->output_data.mac);
6006 f->output_data.mac = NULL;
6008 UNBLOCK_INPUT;
6012 /* Destroy the X window of frame F. */
6014 void
6015 x_destroy_window (f)
6016 struct frame *f;
6018 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6020 x_free_frame_resources (f);
6022 dpyinfo->reference_count--;
6026 /* Setting window manager hints. */
6028 /* Set the normal size hints for the window manager, for frame F.
6029 FLAGS is the flags word to use--or 0 meaning preserve the flags
6030 that the window now has.
6031 If USER_POSITION is nonzero, we set the USPosition
6032 flag (this is useful when FLAGS is 0). */
6033 void
6034 x_wm_set_size_hint (f, flags, user_position)
6035 struct frame *f;
6036 long flags;
6037 int user_position;
6039 int base_width, base_height, width_inc, height_inc;
6040 int min_rows = 0, min_cols = 0;
6041 XSizeHints *size_hints;
6043 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6044 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6045 width_inc = FRAME_COLUMN_WIDTH (f);
6046 height_inc = FRAME_LINE_HEIGHT (f);
6048 check_frame_size (f, &min_rows, &min_cols);
6050 size_hints = FRAME_SIZE_HINTS (f);
6051 if (size_hints == NULL)
6053 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6054 bzero (size_hints, sizeof (XSizeHints));
6057 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6058 size_hints->width_inc = width_inc;
6059 size_hints->height_inc = height_inc;
6060 size_hints->min_width = base_width + min_cols * width_inc;
6061 size_hints->min_height = base_height + min_rows * height_inc;
6062 size_hints->base_width = base_width;
6063 size_hints->base_height = base_height;
6065 if (flags)
6066 size_hints->flags = flags;
6067 else if (user_position)
6069 size_hints->flags &= ~ PPosition;
6070 size_hints->flags |= USPosition;
6074 #if 0 /* MAC_TODO: hide application instead of iconify? */
6075 /* Used for IconicState or NormalState */
6077 void
6078 x_wm_set_window_state (f, state)
6079 struct frame *f;
6080 int state;
6082 #ifdef USE_X_TOOLKIT
6083 Arg al[1];
6085 XtSetArg (al[0], XtNinitialState, state);
6086 XtSetValues (f->output_data.x->widget, al, 1);
6087 #else /* not USE_X_TOOLKIT */
6088 Window window = FRAME_X_WINDOW (f);
6090 f->output_data.x->wm_hints.flags |= StateHint;
6091 f->output_data.x->wm_hints.initial_state = state;
6093 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6094 #endif /* not USE_X_TOOLKIT */
6097 void
6098 x_wm_set_icon_pixmap (f, pixmap_id)
6099 struct frame *f;
6100 int pixmap_id;
6102 Pixmap icon_pixmap;
6104 #ifndef USE_X_TOOLKIT
6105 Window window = FRAME_X_WINDOW (f);
6106 #endif
6108 if (pixmap_id > 0)
6110 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6111 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6113 else
6115 /* It seems there is no way to turn off use of an icon pixmap.
6116 The following line does it, only if no icon has yet been created,
6117 for some window managers. But with mwm it crashes.
6118 Some people say it should clear the IconPixmapHint bit in this case,
6119 but that doesn't work, and the X consortium said it isn't the
6120 right thing at all. Since there is no way to win,
6121 best to explicitly give up. */
6122 #if 0
6123 f->output_data.x->wm_hints.icon_pixmap = None;
6124 #else
6125 return;
6126 #endif
6129 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6132 Arg al[1];
6133 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6134 XtSetValues (f->output_data.x->widget, al, 1);
6137 #else /* not USE_X_TOOLKIT */
6139 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6140 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6142 #endif /* not USE_X_TOOLKIT */
6145 #endif /* MAC_TODO */
6147 void
6148 x_wm_set_icon_position (f, icon_x, icon_y)
6149 struct frame *f;
6150 int icon_x, icon_y;
6152 #if 0 /* MAC_TODO: no icons on Mac */
6153 #ifdef USE_X_TOOLKIT
6154 Window window = XtWindow (f->output_data.x->widget);
6155 #else
6156 Window window = FRAME_X_WINDOW (f);
6157 #endif
6159 f->output_data.x->wm_hints.flags |= IconPositionHint;
6160 f->output_data.x->wm_hints.icon_x = icon_x;
6161 f->output_data.x->wm_hints.icon_y = icon_y;
6163 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6164 #endif /* MAC_TODO */
6168 /***********************************************************************
6169 XLFD Pattern Match
6170 ***********************************************************************/
6172 /* An XLFD pattern is divided into blocks delimited by '*'. This
6173 structure holds information for each block. */
6174 struct xlfdpat_block
6176 /* Length of the pattern string in this block. Non-zero except for
6177 the first and the last blocks. */
6178 int len;
6180 /* Pattern string except the last character in this block. The last
6181 character is replaced with NUL in order to use it as a
6182 sentinel. */
6183 unsigned char *pattern;
6185 /* Last character of the pattern string. Must not be '?'. */
6186 unsigned char last_char;
6188 /* One of the tables for the Boyer-Moore string search. It
6189 specifies the number of positions to proceed for each character
6190 with which the match fails. */
6191 int skip[256];
6193 /* The skip value for the last character in the above `skip' is
6194 assigned to `infinity' in order to simplify a loop condition.
6195 The original value is saved here. */
6196 int last_char_skip;
6199 struct xlfdpat
6201 /* Normalized pattern string. "Normalized" means that capital
6202 letters are lowered, blocks are not empty except the first and
6203 the last ones, and trailing '?'s in a block that is not the last
6204 one are moved to the next one. The last character in each block
6205 is replaced with NUL. */
6206 unsigned char *buf;
6208 /* Number of characters except '*'s and trailing '?'s in the
6209 normalized pattern string. */
6210 int nchars;
6212 /* Number of trailing '?'s in the normalized pattern string. */
6213 int trailing_anychars;
6215 /* Number of blocks and information for each block. The latter is
6216 NULL if the pattern is exact (no '*' or '?' in it). */
6217 int nblocks;
6218 struct xlfdpat_block *blocks;
6221 static void
6222 xlfdpat_destroy (pat)
6223 struct xlfdpat *pat;
6225 if (pat)
6227 if (pat->buf)
6229 if (pat->blocks)
6230 xfree (pat->blocks);
6231 xfree (pat->buf);
6233 xfree (pat);
6237 static struct xlfdpat *
6238 xlfdpat_create (pattern)
6239 const char *pattern;
6241 struct xlfdpat *pat;
6242 int nblocks, i, skip;
6243 unsigned char last_char, *p, *q, *anychar_head;
6244 const unsigned char *ptr;
6245 struct xlfdpat_block *blk;
6247 pat = xmalloc (sizeof (struct xlfdpat));
6248 pat->buf = xmalloc (strlen (pattern) + 1);
6250 /* Normalize the pattern string and store it to `pat->buf'. */
6251 nblocks = 0;
6252 anychar_head = NULL;
6253 q = pat->buf;
6254 last_char = '\0';
6255 for (ptr = pattern; *ptr; ptr++)
6257 unsigned char c = *ptr;
6259 if (c == '*')
6260 if (last_char == '*')
6261 /* ...a** -> ...a* */
6262 continue;
6263 else
6265 if (last_char == '?')
6267 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6268 /* ...*??* -> ...*?? */
6269 continue;
6270 else
6271 /* ...a??* -> ...a*?? */
6273 *anychar_head++ = '*';
6274 c = '?';
6277 nblocks++;
6279 else if (c == '?')
6281 if (last_char != '?')
6282 anychar_head = q;
6284 else
6285 /* On Mac OS X 10.3, tolower also converts non-ASCII
6286 characters for some locales. */
6287 if (isascii (c))
6288 c = tolower (c);
6290 *q++ = last_char = c;
6292 *q = '\0';
6293 nblocks++;
6294 pat->nblocks = nblocks;
6295 if (last_char != '?')
6296 pat->trailing_anychars = 0;
6297 else
6299 pat->trailing_anychars = q - anychar_head;
6300 q = anychar_head;
6302 pat->nchars = q - pat->buf - (nblocks - 1);
6304 if (anychar_head == NULL && nblocks == 1)
6306 /* The pattern is exact. */
6307 pat->blocks = NULL;
6308 return pat;
6311 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6313 /* Divide the normalized pattern into blocks. */
6314 p = pat->buf;
6315 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6317 blk->pattern = p;
6318 while (*p != '*')
6319 p++;
6320 blk->len = p - blk->pattern;
6321 p++;
6323 blk->pattern = p;
6324 blk->len = q - blk->pattern;
6326 /* Setup a table for the Boyer-Moore string search. */
6327 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6328 if (blk->len != 0)
6330 blk->last_char = blk->pattern[blk->len - 1];
6331 blk->pattern[blk->len - 1] = '\0';
6333 for (skip = 1; skip < blk->len; skip++)
6334 if (blk->pattern[blk->len - skip - 1] == '?')
6335 break;
6337 for (i = 0; i < 256; i++)
6338 blk->skip[i] = skip;
6340 p = blk->pattern + (blk->len - skip);
6341 while (--skip > 0)
6342 blk->skip[*p++] = skip;
6344 blk->last_char_skip = blk->skip[blk->last_char];
6347 return pat;
6350 static INLINE int
6351 xlfdpat_exact_p (pat)
6352 struct xlfdpat *pat;
6354 return pat->blocks == NULL;
6357 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6358 that the pattern in *BLK matches with its prefix. Return NULL
6359 there is no such strings. STRING must be lowered in advance. */
6361 static const char *
6362 xlfdpat_block_match_1 (blk, string, start_max)
6363 struct xlfdpat_block *blk;
6364 const unsigned char *string;
6365 int start_max;
6367 int start, infinity;
6368 unsigned char *p;
6369 const unsigned char *s;
6371 xassert (blk->len > 0);
6372 xassert (start_max + blk->len <= strlen (string));
6373 xassert (blk->last_char != '?');
6375 /* See the comments in the function `boyer_moore' (search.c) for the
6376 use of `infinity'. */
6377 infinity = start_max + blk->len + 1;
6378 blk->skip[blk->last_char] = infinity;
6380 start = 0;
6383 /* Check the last character of the pattern. */
6384 s = string + blk->len - 1;
6387 start += blk->skip[*(s + start)];
6389 while (start <= start_max);
6391 if (start < infinity)
6392 /* Couldn't find the last character. */
6393 return NULL;
6395 /* No less than `infinity' means we could find the last
6396 character at `s[start - infinity]'. */
6397 start -= infinity;
6399 /* Check the remaining characters. We prefer making no-'?'
6400 cases faster because the use of '?' is really rare. */
6401 p = blk->pattern;
6402 s = string + start;
6405 while (*p++ == *s++)
6408 while (*(p - 1) == '?');
6410 if (*(p - 1) == '\0')
6411 /* Matched. */
6412 return string + start;
6414 /* Didn't match. */
6415 start += blk->last_char_skip;
6417 while (start <= start_max);
6419 return NULL;
6422 #define xlfdpat_block_match(b, s, m) \
6423 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6424 : xlfdpat_block_match_1 (b, s, m))
6426 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
6427 matches with STRING. STRING must be lowered in advance. */
6429 static int
6430 xlfdpat_match (pat, string)
6431 struct xlfdpat *pat;
6432 const unsigned char *string;
6434 int str_len, nblocks, i, start_max;
6435 struct xlfdpat_block *blk;
6436 const unsigned char *s;
6438 xassert (pat->nblocks > 0);
6440 if (xlfdpat_exact_p (pat))
6441 return strcmp (pat->buf, string) == 0;
6443 /* The number of the characters in the string must not be smaller
6444 than that in the pattern. */
6445 str_len = strlen (string);
6446 if (str_len < pat->nchars + pat->trailing_anychars)
6447 return 0;
6449 /* Chop off the trailing '?'s. */
6450 str_len -= pat->trailing_anychars;
6452 /* The last block. When it is non-empty, it must match at the end
6453 of the string. */
6454 nblocks = pat->nblocks;
6455 blk = pat->blocks + (nblocks - 1);
6456 if (nblocks == 1)
6457 /* The last block is also the first one. */
6458 return (str_len == blk->len
6459 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6460 else if (blk->len != 0)
6461 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6462 return 0;
6464 /* The first block. When it is non-empty, it must match at the
6465 beginning of the string. */
6466 blk = pat->blocks;
6467 if (blk->len != 0)
6469 s = xlfdpat_block_match (blk, string, 0);
6470 if (s == NULL)
6471 return 0;
6472 string = s + blk->len;
6475 /* The rest of the blocks. */
6476 start_max = str_len - pat->nchars;
6477 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6479 s = xlfdpat_block_match (blk, string, start_max);
6480 if (s == NULL)
6481 return 0;
6482 start_max -= s - string;
6483 string = s + blk->len;
6486 return 1;
6490 /***********************************************************************
6491 Fonts
6492 ***********************************************************************/
6494 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6496 struct font_info *
6497 x_get_font_info (f, font_idx)
6498 FRAME_PTR f;
6499 int font_idx;
6501 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6504 /* the global font name table */
6505 static char **font_name_table = NULL;
6506 static int font_name_table_size = 0;
6507 static int font_name_count = 0;
6509 /* Alist linking font family names to Font Manager font family
6510 references (which can also be used as QuickDraw font IDs). We use
6511 an alist because hash tables are not ready when the terminal frame
6512 for Mac OS Classic is created. */
6513 static Lisp_Object fm_font_family_alist;
6514 #if USE_ATSUI
6515 /* Hash table linking font family names to ATSU font IDs. */
6516 static Lisp_Object atsu_font_id_hash;
6517 /* Alist linking Font Manager style to face attributes. */
6518 static Lisp_Object fm_style_face_attributes_alist;
6519 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
6520 #endif
6521 #if USE_MAC_FONT_PANEL
6522 Lisp_Object Qpanel_closed, Qselection;
6523 #endif
6525 /* Alist linking character set strings to Mac text encoding and Emacs
6526 coding system. */
6527 static Lisp_Object Vmac_charset_info_alist;
6529 static Lisp_Object
6530 create_text_encoding_info_alist ()
6532 Lisp_Object result = Qnil, rest;
6534 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6536 Lisp_Object charset_info = XCAR (rest);
6537 Lisp_Object charset, coding_system, text_encoding;
6538 Lisp_Object existing_info;
6540 if (!(CONSP (charset_info)
6541 && (charset = XCAR (charset_info),
6542 STRINGP (charset))
6543 && CONSP (XCDR (charset_info))
6544 && (text_encoding = XCAR (XCDR (charset_info)),
6545 INTEGERP (text_encoding))
6546 && CONSP (XCDR (XCDR (charset_info)))
6547 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
6548 SYMBOLP (coding_system))))
6549 continue;
6551 existing_info = assq_no_quit (text_encoding, result);
6552 if (NILP (existing_info))
6553 result = Fcons (list3 (text_encoding, coding_system, charset),
6554 result);
6555 else
6556 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6557 XSETCDR (XCDR (existing_info),
6558 Fcons (charset, XCDR (XCDR (existing_info))));
6561 return result;
6565 static void
6566 decode_mac_font_name (name, size, coding_system)
6567 char *name;
6568 int size;
6569 Lisp_Object coding_system;
6571 struct coding_system coding;
6572 char *buf, *p;
6574 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6576 for (p = name; *p; p++)
6577 if (!isascii (*p) || iscntrl (*p))
6578 break;
6580 if (*p)
6582 setup_coding_system (coding_system, &coding);
6583 coding.src_multibyte = 0;
6584 coding.dst_multibyte = 1;
6585 coding.mode |= CODING_MODE_LAST_BLOCK;
6586 coding.composing = COMPOSITION_DISABLED;
6587 buf = (char *) alloca (size);
6589 decode_coding (&coding, name, buf, strlen (name), size - 1);
6590 bcopy (buf, name, coding.produced);
6591 name[coding.produced] = '\0';
6595 /* If there's just one occurrence of '-' in the family name, it is
6596 replaced with '_'. (More than one occurrence of '-' means a
6597 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6598 p = strchr (name, '-');
6599 if (p && strchr (p + 1, '-') == NULL)
6600 *p = '_';
6602 for (p = name; *p; p++)
6603 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6604 for some locales. */
6605 if (isascii (*p))
6606 *p = tolower (*p);
6610 static char *
6611 mac_to_x_fontname (name, size, style, charset)
6612 const char *name;
6613 int size;
6614 Style style;
6615 char *charset;
6617 Str31 foundry, cs;
6618 Str255 family;
6619 char xf[256], *result;
6620 unsigned char *p;
6622 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6623 charset = cs;
6624 else
6626 strcpy(foundry, "Apple");
6627 strcpy(family, name);
6630 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6631 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
6632 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
6634 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6635 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6636 for (p = result; *p; p++)
6637 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6638 for some locales. */
6639 if (isascii (*p))
6640 *p = tolower (*p);
6641 return result;
6645 /* Parse fully-specified and instantiated X11 font spec XF, and store
6646 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6647 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6648 caller must allocate at least 256 and 32 bytes respectively. For
6649 ordinary Mac fonts, the value stored to FAMILY should just be their
6650 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6651 intlfonts collection contain their charset designation in their
6652 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6653 types of font names are handled accordingly. */
6655 const int kDefaultFontSize = 12;
6657 static int
6658 parse_x_font_name (xf, family, size, style, charset)
6659 const char *xf;
6660 char *family;
6661 int *size;
6662 Style *style;
6663 char *charset;
6665 Str31 foundry, weight;
6666 int point_size, avgwidth;
6667 char slant[2], *p;
6669 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6670 foundry, family, weight, slant, size,
6671 &point_size, &avgwidth, charset) != 8
6672 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6673 foundry, family, weight, slant, size,
6674 &point_size, &avgwidth, charset) != 8)
6675 return 0;
6677 if (*size == 0)
6679 if (point_size > 0)
6680 *size = point_size / 10;
6681 else if (avgwidth > 0)
6682 *size = avgwidth / 10;
6684 if (*size == 0)
6685 *size = kDefaultFontSize;
6687 *style = normal;
6688 if (strcmp (weight, "bold") == 0)
6689 *style |= bold;
6690 if (*slant == 'i')
6691 *style |= italic;
6693 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
6695 int foundry_len = strlen (foundry), family_len = strlen (family);
6697 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
6699 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6700 but take overlap into account. */
6701 memmove (family + foundry_len + 1, family, family_len);
6702 memcpy (family, foundry, foundry_len);
6703 family[foundry_len] = '-';
6704 family[foundry_len + 1 + family_len] = '-';
6705 strcpy (family + foundry_len + 1 + family_len + 1, charset);
6707 else
6708 return 0;
6711 for (p = family; *p; p++)
6712 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6713 for some locales. */
6714 if (isascii (*p))
6715 *p = tolower (*p);
6717 return 1;
6721 static void
6722 add_font_name_table_entry (char *font_name)
6724 if (font_name_table_size == 0)
6726 font_name_table_size = 256;
6727 font_name_table = (char **)
6728 xmalloc (font_name_table_size * sizeof (char *));
6730 else if (font_name_count + 1 >= font_name_table_size)
6732 font_name_table_size *= 2;
6733 font_name_table = (char **)
6734 xrealloc (font_name_table,
6735 font_name_table_size * sizeof (char *));
6738 font_name_table[font_name_count++] = font_name;
6741 static void
6742 add_mac_font_name (name, size, style, charset)
6743 const char *name;
6744 int size;
6745 Style style;
6746 const char *charset;
6748 if (size > 0)
6749 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
6750 else
6752 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
6753 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
6754 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
6755 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
6756 charset));
6760 #if USE_ATSUI
6761 static FMFontStyle
6762 fm_get_style_from_font (font)
6763 FMFont font;
6765 OSStatus err;
6766 FMFontStyle style = normal;
6767 ByteCount len;
6768 UInt16 mac_style;
6769 FMFontFamily font_family;
6770 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
6772 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
6773 some font (e.g., Optima) even if it is `bold'. */
6774 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
6775 sizeof (mac_style), &mac_style, &len);
6776 if (err == noErr
6777 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
6778 style = EndianU16_BtoN (mac_style);
6779 else
6780 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
6782 return style;
6785 static ATSUFontID
6786 atsu_find_font_from_family_name (family)
6787 const char *family;
6789 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
6790 unsigned hash_code;
6791 int i;
6792 Lisp_Object rest, best;
6793 FMFontStyle min_style, style;
6795 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
6796 &hash_code);
6797 if (i < 0)
6798 return kATSUInvalidFontID;
6800 rest = HASH_VALUE (h, i);
6801 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
6802 return cons_to_long (rest);
6804 rest = Fnreverse (rest);
6805 best = XCAR (rest);
6806 rest = XCDR (rest);
6807 if (!NILP (rest)
6808 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
6811 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
6812 if (style < min_style)
6814 best = XCAR (rest);
6815 if (style == normal)
6816 break;
6817 else
6818 min_style = style;
6820 rest = XCDR (rest);
6822 while (!NILP (rest));
6824 HASH_VALUE (h, i) = best;
6825 return cons_to_long (best);
6828 static Lisp_Object
6829 fm_style_to_face_attributes (fm_style)
6830 FMFontStyle fm_style;
6832 Lisp_Object tem;
6834 fm_style &= (bold | italic);
6835 tem = assq_no_quit (make_number (fm_style),
6836 fm_style_face_attributes_alist);
6837 if (!NILP (tem))
6838 return XCDR (tem);
6840 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
6841 QCslant, fm_style & italic ? Qitalic : Qnormal);
6842 fm_style_face_attributes_alist =
6843 Fcons (Fcons (make_number (fm_style), tem),
6844 fm_style_face_attributes_alist);
6846 return tem;
6849 static Lisp_Object
6850 atsu_find_font_family_name (font_id)
6851 ATSUFontID font_id;
6853 OSStatus err;
6854 ByteCount len;
6855 Lisp_Object family = Qnil;
6857 err = ATSUFindFontName (font_id, kFontFamilyName,
6858 kFontMacintoshPlatform, kFontNoScript,
6859 kFontNoLanguage, 0, NULL, &len, NULL);
6860 if (err == noErr)
6862 family = make_uninit_string (len);
6863 err = ATSUFindFontName (font_id, kFontFamilyName,
6864 kFontMacintoshPlatform, kFontNoScript,
6865 kFontNoLanguage, len, SDATA (family),
6866 NULL, NULL);
6868 if (err == noErr)
6869 decode_mac_font_name (SDATA (family), len + 1, Qnil);
6871 return family;
6874 Lisp_Object
6875 mac_atsu_font_face_attributes (font_id)
6876 ATSUFontID font_id;
6878 Lisp_Object family, style_attrs;
6880 family = atsu_find_font_family_name (font_id);
6881 if (NILP (family))
6882 return Qnil;
6883 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
6884 return Fcons (QCfamily, Fcons (family, style_attrs));
6886 #endif
6888 /* Sets up the table font_name_table to contain the list of all fonts
6889 in the system the first time the table is used so that the Resource
6890 Manager need not be accessed every time this information is
6891 needed. */
6893 static void
6894 init_font_name_table ()
6896 #if TARGET_API_MAC_CARBON
6897 FMFontFamilyIterator ffi;
6898 FMFontFamilyInstanceIterator ffii;
6899 FMFontFamily ff;
6900 Lisp_Object text_encoding_info_alist;
6901 struct gcpro gcpro1;
6903 text_encoding_info_alist = create_text_encoding_info_alist ();
6905 #if USE_ATSUI
6906 #if USE_CG_TEXT_DRAWING
6907 init_cg_text_anti_aliasing_threshold ();
6908 #endif
6909 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6910 text_encoding_info_alist)))
6912 OSStatus err;
6913 struct Lisp_Hash_Table *h;
6914 unsigned hash_code;
6915 ItemCount nfonts, i;
6916 ATSUFontID *font_ids = NULL;
6917 Lisp_Object prev_family = Qnil;
6918 int j;
6920 atsu_font_id_hash =
6921 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
6922 make_float (DEFAULT_REHASH_SIZE),
6923 make_float (DEFAULT_REHASH_THRESHOLD),
6924 Qnil, Qnil, Qnil);
6925 h = XHASH_TABLE (atsu_font_id_hash);
6927 err = ATSUFontCount (&nfonts);
6928 if (err == noErr)
6930 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
6931 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
6933 if (err == noErr)
6934 for (i = 0; i < nfonts; i++)
6936 Lisp_Object family;
6938 family = atsu_find_font_family_name (font_ids[i]);
6939 if (NILP (family) || SREF (family, 0) == '.')
6940 continue;
6941 if (!NILP (Fequal (prev_family, family)))
6942 family = prev_family;
6943 else
6944 j = hash_lookup (h, family, &hash_code);
6945 if (j < 0)
6947 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
6948 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
6949 Qnil), hash_code);
6951 else if (EQ (prev_family, family))
6952 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
6953 HASH_VALUE (h, j));
6954 prev_family = family;
6956 if (font_ids)
6957 xfree (font_ids);
6959 #endif
6961 /* Create a dummy instance iterator here to avoid creating and
6962 destroying it in the loop. */
6963 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6964 return;
6965 /* Create an iterator to enumerate the font families. */
6966 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6967 != noErr)
6969 FMDisposeFontFamilyInstanceIterator (&ffii);
6970 return;
6973 GCPRO1 (text_encoding_info_alist);
6975 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6977 Str255 name;
6978 FMFont font;
6979 FMFontStyle style;
6980 FMFontSize size;
6981 TextEncoding encoding;
6982 TextEncodingBase sc;
6983 Lisp_Object text_encoding_info, family;
6985 if (FMGetFontFamilyName (ff, name) != noErr)
6986 continue;
6987 p2cstr (name);
6988 if (*name == '.')
6989 continue;
6991 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6992 continue;
6993 sc = GetTextEncodingBase (encoding);
6994 text_encoding_info = assq_no_quit (make_number (sc),
6995 text_encoding_info_alist);
6996 if (NILP (text_encoding_info))
6997 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
6998 text_encoding_info_alist);
6999 decode_mac_font_name (name, sizeof (name),
7000 XCAR (XCDR (text_encoding_info)));
7001 family = build_string (name);
7002 if (!NILP (Fassoc (family, fm_font_family_alist)))
7003 continue;
7004 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7005 fm_font_family_alist);
7007 /* Point the instance iterator at the current font family. */
7008 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7009 continue;
7011 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7012 == noErr)
7014 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7016 if (size > 0 || style == normal)
7017 for (; !NILP (rest); rest = XCDR (rest))
7018 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7022 UNGCPRO;
7024 /* Dispose of the iterators. */
7025 FMDisposeFontFamilyIterator (&ffi);
7026 FMDisposeFontFamilyInstanceIterator (&ffii);
7027 #else /* !TARGET_API_MAC_CARBON */
7028 GrafPtr port;
7029 SInt16 fontnum, old_fontnum;
7030 int num_mac_fonts = CountResources('FOND');
7031 int i, j;
7032 Handle font_handle, font_handle_2;
7033 short id, scriptcode;
7034 ResType type;
7035 Str255 name;
7036 struct FontAssoc *fat;
7037 struct AsscEntry *assc_entry;
7038 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7039 struct gcpro gcpro1;
7041 GetPort (&port); /* save the current font number used */
7042 old_fontnum = port->txFont;
7044 text_encoding_info_alist = create_text_encoding_info_alist ();
7046 GCPRO1 (text_encoding_info_alist);
7048 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7050 font_handle = GetIndResource ('FOND', i);
7051 if (!font_handle)
7052 continue;
7054 GetResInfo (font_handle, &id, &type, name);
7055 GetFNum (name, &fontnum);
7056 p2cstr (name);
7057 if (fontnum == 0 || *name == '.')
7058 continue;
7060 TextFont (fontnum);
7061 scriptcode = FontToScript (fontnum);
7062 text_encoding_info = assq_no_quit (make_number (scriptcode),
7063 text_encoding_info_alist);
7064 if (NILP (text_encoding_info))
7065 text_encoding_info = assq_no_quit (make_number (smRoman),
7066 text_encoding_info_alist);
7067 decode_mac_font_name (name, sizeof (name),
7068 XCAR (XCDR (text_encoding_info)));
7069 family = build_string (name);
7070 if (!NILP (Fassoc (family, fm_font_family_alist)))
7071 continue;
7072 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7073 fm_font_family_alist);
7076 HLock (font_handle);
7078 if (GetResourceSizeOnDisk (font_handle)
7079 >= sizeof (struct FamRec))
7081 fat = (struct FontAssoc *) (*font_handle
7082 + sizeof (struct FamRec));
7083 assc_entry
7084 = (struct AsscEntry *) (*font_handle
7085 + sizeof (struct FamRec)
7086 + sizeof (struct FontAssoc));
7088 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7090 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7092 for (; !NILP (rest); rest = XCDR (rest))
7093 add_mac_font_name (name, assc_entry->fontSize,
7094 assc_entry->fontStyle,
7095 SDATA (XCAR (rest)));
7099 HUnlock (font_handle);
7100 font_handle_2 = GetNextFOND (font_handle);
7101 ReleaseResource (font_handle);
7102 font_handle = font_handle_2;
7104 while (ResError () == noErr && font_handle);
7107 UNGCPRO;
7109 TextFont (old_fontnum);
7110 #endif /* !TARGET_API_MAC_CARBON */
7114 void
7115 mac_clear_font_name_table ()
7117 int i;
7119 for (i = 0; i < font_name_count; i++)
7120 xfree (font_name_table[i]);
7121 xfree (font_name_table);
7122 font_name_table = NULL;
7123 font_name_table_size = font_name_count = 0;
7124 fm_font_family_alist = Qnil;
7128 enum xlfd_scalable_field_index
7130 XLFD_SCL_PIXEL_SIZE,
7131 XLFD_SCL_POINT_SIZE,
7132 XLFD_SCL_AVGWIDTH,
7133 XLFD_SCL_LAST
7136 static const int xlfd_scalable_fields[] =
7138 6, /* PIXEL_SIZE */
7139 7, /* POINT_SIZE */
7140 11, /* AVGWIDTH */
7144 static Lisp_Object
7145 mac_do_list_fonts (pattern, maxnames)
7146 const char *pattern;
7147 int maxnames;
7149 int i, n_fonts = 0;
7150 Lisp_Object font_list = Qnil;
7151 struct xlfdpat *pat;
7152 char *scaled;
7153 const char *ptr;
7154 int scl_val[XLFD_SCL_LAST], *val;
7155 const int *field;
7156 int exact;
7158 if (font_name_table == NULL) /* Initialize when first used. */
7159 init_font_name_table ();
7161 for (i = 0; i < XLFD_SCL_LAST; i++)
7162 scl_val[i] = -1;
7164 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7165 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7166 fonts are scaled according to the specified size. */
7167 ptr = pattern;
7168 i = 0;
7169 field = xlfd_scalable_fields;
7170 val = scl_val;
7171 if (*ptr == '-')
7174 ptr++;
7175 if (i == *field)
7177 if ('0' <= *ptr && *ptr <= '9')
7179 *val = *ptr++ - '0';
7180 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7181 *val = *val * 10 + *ptr++ - '0';
7182 if (*ptr != '-')
7183 *val = -1;
7185 field++;
7186 val++;
7188 ptr = strchr (ptr, '-');
7189 i++;
7191 while (ptr && i < 14);
7193 if (i == 14 && ptr == NULL)
7195 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7196 scl_val[XLFD_SCL_PIXEL_SIZE] =
7197 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7198 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7199 : -1));
7200 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7201 scl_val[XLFD_SCL_POINT_SIZE] =
7202 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7203 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7204 : -1));
7205 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7206 scl_val[XLFD_SCL_AVGWIDTH] =
7207 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7208 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7209 : -1));
7211 else
7212 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7214 pat = xlfdpat_create (pattern);
7215 if (pat == NULL)
7216 return Qnil;
7218 exact = xlfdpat_exact_p (pat);
7220 for (i = 0; i < font_name_count; i++)
7222 if (xlfdpat_match (pat, font_name_table[i]))
7224 font_list = Fcons (build_string (font_name_table[i]), font_list);
7225 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7226 break;
7228 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7229 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7231 int former_len = ptr - font_name_table[i];
7233 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7234 memcpy (scaled, font_name_table[i], former_len);
7235 sprintf (scaled + former_len,
7236 "-%d-%d-72-72-m-%d-%s",
7237 scl_val[XLFD_SCL_PIXEL_SIZE],
7238 scl_val[XLFD_SCL_POINT_SIZE],
7239 scl_val[XLFD_SCL_AVGWIDTH],
7240 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7242 if (xlfdpat_match (pat, scaled))
7244 font_list = Fcons (build_string (scaled), font_list);
7245 xfree (scaled);
7246 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7247 break;
7249 else
7250 xfree (scaled);
7254 xlfdpat_destroy (pat);
7256 return font_list;
7259 /* Return a list of names of available fonts matching PATTERN on frame F.
7261 Frame F null means we have not yet created any frame on Mac, and
7262 consult the first display in x_display_list. MAXNAMES sets a limit
7263 on how many fonts to match. */
7265 Lisp_Object
7266 x_list_fonts (f, pattern, size, maxnames)
7267 struct frame *f;
7268 Lisp_Object pattern;
7269 int size, maxnames;
7271 Lisp_Object list = Qnil, patterns, tem, key;
7272 struct mac_display_info *dpyinfo
7273 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7275 xassert (size <= 0);
7277 patterns = Fassoc (pattern, Valternate_fontname_alist);
7278 if (NILP (patterns))
7279 patterns = Fcons (pattern, Qnil);
7281 for (; CONSP (patterns); patterns = XCDR (patterns))
7283 pattern = XCAR (patterns);
7285 if (!STRINGP (pattern))
7286 continue;
7288 tem = XCAR (XCDR (dpyinfo->name_list_element));
7289 key = Fcons (pattern, make_number (maxnames));
7291 list = Fassoc (key, tem);
7292 if (!NILP (list))
7294 list = Fcdr_safe (list);
7295 /* We have a cashed list. Don't have to get the list again. */
7296 goto label_cached;
7299 BLOCK_INPUT;
7300 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7301 UNBLOCK_INPUT;
7303 /* MAC_TODO: add code for matching outline fonts here */
7305 /* Now store the result in the cache. */
7306 XSETCAR (XCDR (dpyinfo->name_list_element),
7307 Fcons (Fcons (key, list),
7308 XCAR (XCDR (dpyinfo->name_list_element))));
7310 label_cached:
7311 if (NILP (list)) continue; /* Try the remaining alternatives. */
7314 return list;
7318 #if GLYPH_DEBUG
7320 /* Check that FONT is valid on frame F. It is if it can be found in F's
7321 font table. */
7323 static void
7324 x_check_font (f, font)
7325 struct frame *f;
7326 XFontStruct *font;
7328 int i;
7329 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7331 xassert (font != NULL);
7333 for (i = 0; i < dpyinfo->n_fonts; i++)
7334 if (dpyinfo->font_table[i].name
7335 && font == dpyinfo->font_table[i].font)
7336 break;
7338 xassert (i < dpyinfo->n_fonts);
7341 #endif /* GLYPH_DEBUG != 0 */
7343 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7344 Note: There are (broken) X fonts out there with invalid XFontStruct
7345 min_bounds contents. For example, handa@etl.go.jp reports that
7346 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7347 have font->min_bounds.width == 0. */
7349 static INLINE void
7350 x_font_min_bounds (font, w, h)
7351 MacFontStruct *font;
7352 int *w, *h;
7354 *h = FONT_HEIGHT (font);
7355 *w = font->min_bounds.width;
7359 /* Compute the smallest character width and smallest font height over
7360 all fonts available on frame F. Set the members smallest_char_width
7361 and smallest_font_height in F's x_display_info structure to
7362 the values computed. Value is non-zero if smallest_font_height or
7363 smallest_char_width become smaller than they were before. */
7365 static int
7366 x_compute_min_glyph_bounds (f)
7367 struct frame *f;
7369 int i;
7370 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7371 MacFontStruct *font;
7372 int old_width = dpyinfo->smallest_char_width;
7373 int old_height = dpyinfo->smallest_font_height;
7375 dpyinfo->smallest_font_height = 100000;
7376 dpyinfo->smallest_char_width = 100000;
7378 for (i = 0; i < dpyinfo->n_fonts; ++i)
7379 if (dpyinfo->font_table[i].name)
7381 struct font_info *fontp = dpyinfo->font_table + i;
7382 int w, h;
7384 font = (MacFontStruct *) fontp->font;
7385 xassert (font != (MacFontStruct *) ~0);
7386 x_font_min_bounds (font, &w, &h);
7388 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7389 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7392 xassert (dpyinfo->smallest_char_width > 0
7393 && dpyinfo->smallest_font_height > 0);
7395 return (dpyinfo->n_fonts == 1
7396 || dpyinfo->smallest_char_width < old_width
7397 || dpyinfo->smallest_font_height < old_height);
7401 /* Determine whether given string is a fully-specified XLFD: all 14
7402 fields are present, none is '*'. */
7404 static int
7405 is_fully_specified_xlfd (p)
7406 const char *p;
7408 int i;
7409 char *q;
7411 if (*p != '-')
7412 return 0;
7414 for (i = 0; i < 13; i++)
7416 q = strchr (p + 1, '-');
7417 if (q == NULL)
7418 return 0;
7419 if (q - p == 2 && *(p + 1) == '*')
7420 return 0;
7421 p = q;
7424 if (strchr (p + 1, '-') != NULL)
7425 return 0;
7427 if (*(p + 1) == '*' && *(p + 2) == '\0')
7428 return 0;
7430 return 1;
7434 /* mac_load_query_font creates and returns an internal representation
7435 for a font in a MacFontStruct struct. There is really no concept
7436 corresponding to "loading" a font on the Mac. But we check its
7437 existence and find the font number and all other information for it
7438 and store them in the returned MacFontStruct. */
7440 static MacFontStruct *
7441 mac_load_query_font (f, fontname)
7442 struct frame *f;
7443 char *fontname;
7445 int size;
7446 char *name;
7447 Str255 family;
7448 Str31 charset;
7449 SInt16 fontnum;
7450 #if USE_ATSUI
7451 static ATSUFontID font_id;
7452 ATSUStyle mac_style = NULL;
7453 #endif
7454 Style fontface;
7455 #if TARGET_API_MAC_CARBON
7456 TextEncoding encoding;
7457 int scriptcode;
7458 #else
7459 short scriptcode;
7460 #endif
7461 MacFontStruct *font;
7462 XCharStruct *space_bounds = NULL, *pcm;
7464 if (is_fully_specified_xlfd (fontname))
7465 name = fontname;
7466 else
7468 Lisp_Object matched_fonts;
7470 matched_fonts = mac_do_list_fonts (fontname, 1);
7471 if (NILP (matched_fonts))
7472 return NULL;
7473 name = SDATA (XCAR (matched_fonts));
7476 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7477 return NULL;
7479 #if USE_ATSUI
7480 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7482 OSStatus err;
7483 static const ATSUAttributeTag tags[] =
7484 {kATSUFontTag, kATSUSizeTag,
7485 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7486 static const ByteCount sizes[] =
7487 {sizeof (ATSUFontID), sizeof (Fixed),
7488 sizeof (Boolean), sizeof (Boolean)};
7489 static Fixed size_fixed;
7490 static Boolean bold_p, italic_p;
7491 static const ATSUAttributeValuePtr values[] =
7492 {&font_id, &size_fixed,
7493 &bold_p, &italic_p};
7494 static const ATSUFontFeatureType types[] =
7495 {kAllTypographicFeaturesType, kDiacriticsType};
7496 static const ATSUFontFeatureSelector selectors[] =
7497 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
7498 FMFontStyle style;
7500 font_id = atsu_find_font_from_family_name (family);
7501 if (font_id == kATSUInvalidFontID)
7502 return NULL;
7503 size_fixed = Long2Fix (size);
7504 bold_p = (fontface & bold) != 0;
7505 italic_p = (fontface & italic) != 0;
7506 err = ATSUCreateStyle (&mac_style);
7507 if (err != noErr)
7508 return NULL;
7509 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7510 types, selectors);
7511 if (err != noErr)
7512 return NULL;
7513 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7514 tags, sizes, values);
7515 if (err != noErr)
7516 return NULL;
7517 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
7518 if (err != noErr)
7519 fontnum = -1;
7520 scriptcode = kTextEncodingMacUnicode;
7522 else
7523 #endif
7525 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7527 if (NILP (tmp))
7528 return NULL;
7529 fontnum = XINT (XCDR (tmp));
7530 #if TARGET_API_MAC_CARBON
7531 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7532 return NULL;
7533 scriptcode = GetTextEncodingBase (encoding);
7534 #else
7535 scriptcode = FontToScript (fontnum);
7536 #endif
7539 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7541 font->mac_fontnum = fontnum;
7542 font->mac_fontsize = size;
7543 font->mac_fontface = fontface;
7544 font->mac_scriptcode = scriptcode;
7545 #if USE_ATSUI
7546 font->mac_style = mac_style;
7547 #if USE_CG_TEXT_DRAWING
7548 font->cg_font = NULL;
7549 font->cg_glyphs = NULL;
7550 #endif
7551 #endif
7553 /* Apple Japanese (SJIS) font is listed as both
7554 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7555 (Roman script) in init_font_name_table (). The latter should be
7556 treated as a one-byte font. */
7557 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7558 font->mac_scriptcode = smRoman;
7560 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
7562 #if USE_ATSUI
7563 if (font->mac_style)
7565 OSStatus err;
7566 UniChar c;
7568 font->min_byte1 = 0;
7569 font->max_byte1 = 0xff;
7570 font->min_char_or_byte2 = 0;
7571 font->max_char_or_byte2 = 0xff;
7573 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
7574 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
7575 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
7576 pcm_init (font->bounds.rows[0], 0x100);
7578 #if USE_CG_TEXT_DRAWING
7579 if (fontnum != -1)
7581 FMFontStyle style;
7582 ATSFontRef ats_font;
7584 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
7585 &font_id, &style);
7586 /* Use CG text drawing if italic/bold is not synthesized. */
7587 if (err == noErr && style == fontface)
7589 ats_font = FMGetATSFontRefFromFont (font_id);
7590 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7594 if (font->cg_font)
7596 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7597 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7599 #endif
7600 space_bounds = font->bounds.rows[0] + 0x20;
7601 err = mac_query_char_extents (font->mac_style, 0x20,
7602 &font->ascent, &font->descent,
7603 space_bounds,
7604 #if USE_CG_TEXT_DRAWING
7605 (font->cg_glyphs ? font->cg_glyphs + 0x20
7606 : NULL)
7607 #else
7608 NULL
7609 #endif
7611 if (err != noErr
7612 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
7614 mac_unload_font (&one_mac_display_info, font);
7615 return NULL;
7618 pcm = font->bounds.rows[0];
7619 for (c = 0x21; c <= 0xff; c++)
7621 if (c == 0xad)
7622 /* Soft hyphen is not supported in ATSUI. */
7623 continue;
7624 else if (c == 0x7f)
7626 #if USE_CG_TEXT_DRAWING
7627 if (font->cg_glyphs)
7629 c = 0x9f;
7630 pcm = NULL;
7631 continue;
7633 #endif
7634 break;
7637 mac_query_char_extents (font->mac_style, c, NULL, NULL,
7638 pcm ? pcm + c : NULL,
7639 #if USE_CG_TEXT_DRAWING
7640 (font->cg_glyphs ? font->cg_glyphs + c
7641 : NULL)
7642 #else
7643 NULL
7644 #endif
7647 #if USE_CG_TEXT_DRAWING
7648 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
7650 /* Don't use CG text drawing if font substitution occurs in
7651 ASCII or Latin-1 characters. */
7652 CGFontRelease (font->cg_font);
7653 font->cg_font = NULL;
7654 xfree (font->cg_glyphs);
7655 font->cg_glyphs = NULL;
7656 if (pcm == NULL)
7657 break;
7659 #endif
7662 else
7663 #endif
7665 OSStatus err;
7666 FontInfo the_fontinfo;
7667 int is_two_byte_font;
7669 mac_begin_clip (f, NULL);
7671 TextFont (fontnum);
7672 TextSize (size);
7673 TextFace (fontface);
7675 GetFontInfo (&the_fontinfo);
7677 font->ascent = the_fontinfo.ascent;
7678 font->descent = the_fontinfo.descent;
7680 is_two_byte_font = (font->mac_scriptcode == smJapanese
7681 || font->mac_scriptcode == smTradChinese
7682 || font->mac_scriptcode == smSimpChinese
7683 || font->mac_scriptcode == smKorean);
7685 if (is_two_byte_font)
7687 int char_width;
7689 font->min_byte1 = 0xa1;
7690 font->max_byte1 = 0xfe;
7691 font->min_char_or_byte2 = 0xa1;
7692 font->max_char_or_byte2 = 0xfe;
7694 /* Use the width of an "ideographic space" of that font
7695 because the_fontinfo.widMax returns the wrong width for
7696 some fonts. */
7697 switch (font->mac_scriptcode)
7699 case smJapanese:
7700 font->min_byte1 = 0x81;
7701 font->max_byte1 = 0xfc;
7702 font->min_char_or_byte2 = 0x40;
7703 font->max_char_or_byte2 = 0xfc;
7704 char_width = StringWidth("\p\x81\x40");
7705 break;
7706 case smTradChinese:
7707 font->min_char_or_byte2 = 0x40;
7708 char_width = StringWidth("\p\xa1\x40");
7709 break;
7710 case smSimpChinese:
7711 char_width = StringWidth("\p\xa1\xa1");
7712 break;
7713 case smKorean:
7714 char_width = StringWidth("\p\xa1\xa1");
7715 break;
7718 font->bounds.per_char = NULL;
7720 if (fontface & italic)
7721 font->max_bounds.rbearing = char_width + 1;
7722 else
7723 font->max_bounds.rbearing = char_width;
7724 font->max_bounds.lbearing = 0;
7725 font->max_bounds.width = char_width;
7726 font->max_bounds.ascent = the_fontinfo.ascent;
7727 font->max_bounds.descent = the_fontinfo.descent;
7729 font->min_bounds = font->max_bounds;
7731 else
7733 int c;
7735 font->min_byte1 = font->max_byte1 = 0;
7736 font->min_char_or_byte2 = 0x20;
7737 font->max_char_or_byte2 = 0xff;
7739 font->bounds.per_char =
7740 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7741 bzero (font->bounds.per_char,
7742 sizeof (XCharStruct) * (0xff - 0x20 + 1));
7744 space_bounds = font->bounds.per_char;
7745 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
7746 &font->descent, space_bounds, NULL);
7747 if (err != noErr || space_bounds->width <= 0)
7749 mac_unload_font (&one_mac_display_info, font);
7750 return NULL;
7753 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
7754 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
7757 mac_end_clip (f, NULL);
7760 if (space_bounds)
7762 int c;
7764 font->min_bounds = font->max_bounds = *space_bounds;
7765 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
7766 if (pcm->width > 0)
7768 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
7769 pcm->lbearing);
7770 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
7771 pcm->rbearing);
7772 font->min_bounds.width = min (font->min_bounds.width,
7773 pcm->width);
7774 font->min_bounds.ascent = min (font->min_bounds.ascent,
7775 pcm->ascent);
7776 font->min_bounds.descent = min (font->min_bounds.descent,
7777 pcm->descent);
7779 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
7780 pcm->lbearing);
7781 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
7782 pcm->rbearing);
7783 font->max_bounds.width = max (font->max_bounds.width,
7784 pcm->width);
7785 font->max_bounds.ascent = max (font->max_bounds.ascent,
7786 pcm->ascent);
7787 font->max_bounds.descent = max (font->max_bounds.descent,
7788 pcm->descent);
7790 if (
7791 #if USE_ATSUI
7792 font->mac_style == NULL &&
7793 #endif
7794 font->max_bounds.width == font->min_bounds.width
7795 && font->min_bounds.lbearing >= 0
7796 && font->max_bounds.rbearing <= font->max_bounds.width)
7798 /* Fixed width and no overhangs. */
7799 xfree (font->bounds.per_char);
7800 font->bounds.per_char = NULL;
7804 #if !defined (MAC_OS8) || USE_ATSUI
7805 /* AppKit and WebKit do some adjustment to the heights of Courier,
7806 Helvetica, and Times. This only works on the environments where
7807 srcCopy text transfer mode is never used. */
7808 if (
7809 #ifdef MAC_OS8 /* implies USE_ATSUI */
7810 font->mac_style &&
7811 #endif
7812 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
7813 || strcmp (family, "times") == 0))
7814 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
7815 #endif
7817 return font;
7821 void
7822 mac_unload_font (dpyinfo, font)
7823 struct mac_display_info *dpyinfo;
7824 XFontStruct *font;
7826 xfree (font->full_name);
7827 #if USE_ATSUI
7828 if (font->mac_style)
7830 int i;
7832 for (i = font->min_byte1; i <= font->max_byte1; i++)
7833 if (font->bounds.rows[i])
7834 xfree (font->bounds.rows[i]);
7835 xfree (font->bounds.rows);
7836 ATSUDisposeStyle (font->mac_style);
7838 else
7839 #endif
7840 if (font->bounds.per_char)
7841 xfree (font->bounds.per_char);
7842 #if USE_CG_TEXT_DRAWING
7843 if (font->cg_font)
7844 CGFontRelease (font->cg_font);
7845 if (font->cg_glyphs)
7846 xfree (font->cg_glyphs);
7847 #endif
7848 xfree (font);
7852 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7853 pointer to the structure font_info while allocating it dynamically.
7854 If SIZE is 0, load any size of font.
7855 If loading is failed, return NULL. */
7857 struct font_info *
7858 x_load_font (f, fontname, size)
7859 struct frame *f;
7860 register char *fontname;
7861 int size;
7863 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7864 Lisp_Object font_names;
7866 /* Get a list of all the fonts that match this name. Once we
7867 have a list of matching fonts, we compare them against the fonts
7868 we already have by comparing names. */
7869 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7871 if (!NILP (font_names))
7873 Lisp_Object tail;
7874 int i;
7876 for (i = 0; i < dpyinfo->n_fonts; i++)
7877 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7878 if (dpyinfo->font_table[i].name
7879 && (!strcmp (dpyinfo->font_table[i].name,
7880 SDATA (XCAR (tail)))
7881 || !strcmp (dpyinfo->font_table[i].full_name,
7882 SDATA (XCAR (tail)))))
7883 return (dpyinfo->font_table + i);
7885 else
7886 return NULL;
7888 /* Load the font and add it to the table. */
7890 struct MacFontStruct *font;
7891 struct font_info *fontp;
7892 int i;
7894 fontname = (char *) SDATA (XCAR (font_names));
7896 BLOCK_INPUT;
7897 font = mac_load_query_font (f, fontname);
7898 UNBLOCK_INPUT;
7899 if (!font)
7900 return NULL;
7902 /* Find a free slot in the font table. */
7903 for (i = 0; i < dpyinfo->n_fonts; ++i)
7904 if (dpyinfo->font_table[i].name == NULL)
7905 break;
7907 /* If no free slot found, maybe enlarge the font table. */
7908 if (i == dpyinfo->n_fonts
7909 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7911 int sz;
7912 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7913 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
7914 dpyinfo->font_table
7915 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
7918 fontp = dpyinfo->font_table + i;
7919 if (i == dpyinfo->n_fonts)
7920 ++dpyinfo->n_fonts;
7922 /* Now fill in the slots of *FONTP. */
7923 BLOCK_INPUT;
7924 bzero (fontp, sizeof (*fontp));
7925 fontp->font = font;
7926 fontp->font_idx = i;
7927 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
7928 bcopy (fontname, fontp->name, strlen (fontname) + 1);
7930 if (font->min_bounds.width == font->max_bounds.width)
7932 /* Fixed width font. */
7933 fontp->average_width = fontp->space_width = font->min_bounds.width;
7935 else
7937 XChar2b char2b;
7938 XCharStruct *pcm;
7940 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
7941 pcm = mac_per_char_metric (font, &char2b, 0);
7942 if (pcm)
7943 fontp->space_width = pcm->width;
7944 else
7945 fontp->space_width = FONT_WIDTH (font);
7947 if (pcm)
7949 int width = pcm->width;
7950 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
7951 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
7952 width += pcm->width;
7953 fontp->average_width = width / 95;
7955 else
7956 fontp->average_width = FONT_WIDTH (font);
7959 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
7960 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
7962 fontp->size = font->max_bounds.width;
7963 fontp->height = FONT_HEIGHT (font);
7965 /* For some font, ascent and descent in max_bounds field is
7966 larger than the above value. */
7967 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
7968 if (max_height > fontp->height)
7969 fontp->height = max_height;
7972 /* The slot `encoding' specifies how to map a character
7973 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7974 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7975 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7976 2:0xA020..0xFF7F). For the moment, we don't know which charset
7977 uses this font. So, we set information in fontp->encoding[1]
7978 which is never used by any charset. If mapping can't be
7979 decided, set FONT_ENCODING_NOT_DECIDED. */
7980 if (font->mac_scriptcode == smJapanese)
7981 fontp->encoding[1] = 4;
7982 else
7984 fontp->encoding[1]
7985 = (font->max_byte1 == 0
7986 /* 1-byte font */
7987 ? (font->min_char_or_byte2 < 0x80
7988 ? (font->max_char_or_byte2 < 0x80
7989 ? 0 /* 0x20..0x7F */
7990 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
7991 : 1) /* 0xA0..0xFF */
7992 /* 2-byte font */
7993 : (font->min_byte1 < 0x80
7994 ? (font->max_byte1 < 0x80
7995 ? (font->min_char_or_byte2 < 0x80
7996 ? (font->max_char_or_byte2 < 0x80
7997 ? 0 /* 0x2020..0x7F7F */
7998 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
7999 : 3) /* 0x20A0..0x7FFF */
8000 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8001 : (font->min_char_or_byte2 < 0x80
8002 ? (font->max_char_or_byte2 < 0x80
8003 ? 2 /* 0xA020..0xFF7F */
8004 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8005 : 1))); /* 0xA0A0..0xFFFF */
8008 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8009 fontp->baseline_offset
8010 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8011 ? (long) value : 0);
8012 fontp->relative_compose
8013 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8014 ? (long) value : 0);
8015 fontp->default_ascent
8016 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8017 ? (long) value : 0);
8018 #else
8019 fontp->baseline_offset = 0;
8020 fontp->relative_compose = 0;
8021 fontp->default_ascent = 0;
8022 #endif
8024 /* Set global flag fonts_changed_p to non-zero if the font loaded
8025 has a character with a smaller width than any other character
8026 before, or if the font loaded has a smaller height than any
8027 other font loaded before. If this happens, it will make a
8028 glyph matrix reallocation necessary. */
8029 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8030 UNBLOCK_INPUT;
8031 return fontp;
8036 /* Return a pointer to struct font_info of a font named FONTNAME for
8037 frame F. If no such font is loaded, return NULL. */
8039 struct font_info *
8040 x_query_font (f, fontname)
8041 struct frame *f;
8042 register char *fontname;
8044 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8045 int i;
8047 for (i = 0; i < dpyinfo->n_fonts; i++)
8048 if (dpyinfo->font_table[i].name
8049 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8050 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8051 return (dpyinfo->font_table + i);
8052 return NULL;
8056 /* Find a CCL program for a font specified by FONTP, and set the member
8057 `encoder' of the structure. */
8059 void
8060 x_find_ccl_program (fontp)
8061 struct font_info *fontp;
8063 Lisp_Object list, elt;
8065 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8067 elt = XCAR (list);
8068 if (CONSP (elt)
8069 && STRINGP (XCAR (elt))
8070 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8071 >= 0))
8072 break;
8074 if (! NILP (list))
8076 struct ccl_program *ccl
8077 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8079 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8080 xfree (ccl);
8081 else
8082 fontp->font_encoder = ccl;
8087 /* The Mac Event loop code */
8089 #if !TARGET_API_MAC_CARBON
8090 #include <Events.h>
8091 #include <Quickdraw.h>
8092 #include <Balloons.h>
8093 #include <Devices.h>
8094 #include <Fonts.h>
8095 #include <Gestalt.h>
8096 #include <Menus.h>
8097 #include <Processes.h>
8098 #include <Sound.h>
8099 #include <ToolUtils.h>
8100 #include <TextUtils.h>
8101 #include <Dialogs.h>
8102 #include <Script.h>
8103 #include <Types.h>
8104 #include <Resources.h>
8106 #if __MWERKS__
8107 #include <unix.h>
8108 #endif
8109 #endif /* ! TARGET_API_MAC_CARBON */
8111 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8112 Lisp_Object Qreverse;
8115 /* Modifier associated with the control key, or nil to ignore. */
8116 Lisp_Object Vmac_control_modifier;
8118 /* Modifier associated with the option key, or nil to ignore. */
8119 Lisp_Object Vmac_option_modifier;
8121 /* Modifier associated with the command key, or nil to ignore. */
8122 Lisp_Object Vmac_command_modifier;
8124 /* Modifier associated with the function key, or nil to ignore. */
8125 Lisp_Object Vmac_function_modifier;
8127 /* True if the option and command modifiers should be used to emulate
8128 a three button mouse */
8129 Lisp_Object Vmac_emulate_three_button_mouse;
8131 #if TARGET_API_MAC_CARBON
8132 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8133 mouse-2, instead of mouse-3. */
8134 int mac_wheel_button_is_mouse_2;
8136 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8137 for processing before Emacs sees it. */
8138 int mac_pass_command_to_system;
8140 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8141 for processing before Emacs sees it. */
8142 int mac_pass_control_to_system;
8143 #endif
8145 /* Whether or not the screen configuration has changed. */
8146 int mac_screen_config_changed = 0;
8148 /* Apple Events */
8149 #if TARGET_API_MAC_CARBON
8150 Lisp_Object Qhi_command;
8151 #ifdef MAC_OSX
8152 Lisp_Object Qtoolbar_switch_mode;
8153 #endif
8154 #if USE_MAC_TSM
8155 Lisp_Object Qtext_input;
8156 Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8157 Lisp_Object Vmac_ts_active_input_overlay, Vmac_ts_active_input_buf;
8158 static Lisp_Object Vmac_ts_script_language_on_focus;
8159 static Lisp_Object saved_ts_script_language_on_focus;
8160 static ScriptLanguageRecord saved_ts_language;
8161 static Component saved_ts_component;
8162 #endif
8163 #ifdef MAC_OSX
8164 Lisp_Object Qservice, Qpaste, Qperform;
8165 Lisp_Object Qmouse_drag_overlay;
8166 #endif
8167 #endif /* TARGET_API_MAC_CARBON */
8168 extern Lisp_Object Qundefined;
8169 extern int XTread_socket P_ ((int, int, struct input_event *));
8170 extern void init_apple_event_handler P_ ((void));
8171 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8172 Lisp_Object *, Lisp_Object *,
8173 Lisp_Object *));
8174 extern OSErr init_coercion_handler P_ ((void));
8176 /* Table for translating Mac keycode to X keysym values. Contributed
8177 by Sudhir Shenoy.
8178 Mapping for special keys is now identical to that in Apple X11
8179 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8180 on the right of the Cmd key on laptops, and fn + `enter' (->
8181 <linefeed>). */
8182 const unsigned char keycode_to_xkeysym_table[] = {
8183 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8184 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8185 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8187 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8188 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8189 /*0x38*/ 0, 0, 0, 0,
8190 /*0x3C*/ 0, 0, 0, 0,
8192 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8193 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8194 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8195 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0,
8197 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8198 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8199 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8200 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8202 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8203 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8204 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8205 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8207 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8208 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8209 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8210 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8213 #ifdef MAC_OSX
8214 /* Table for translating Mac keycode with the laptop `fn' key to that
8215 without it. Destination symbols in comments are keys on US
8216 keyboard, and they may not be the same on other types of keyboards.
8217 If the destination is identical to the source, it doesn't map `fn'
8218 key to a modifier. */
8219 static const unsigned char fn_keycode_to_keycode_table[] = {
8220 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8221 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8222 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8224 /*0x30*/ 0, 0, 0, 0,
8225 /*0x34*/ 0, 0, 0, 0,
8226 /*0x38*/ 0, 0, 0, 0,
8227 /*0x3C*/ 0, 0, 0, 0,
8229 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8230 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8231 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8232 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0,
8234 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8235 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8236 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8237 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8239 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8240 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8241 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
8242 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8244 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
8245 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8246 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
8247 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
8249 #endif /* MAC_OSX */
8252 #if TARGET_API_MAC_CARBON
8253 mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
8254 #else
8255 mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
8256 #endif
8258 unsigned int result = 0;
8259 if ((mods | unmapped_mods) & shiftKey)
8260 result |= shift_modifier;
8262 /* Deactivated to simplify configuration:
8263 if Vmac_option_modifier is non-NIL, we fully process the Option
8264 key. Otherwise, we only process it if an additional Ctrl or Command
8265 is pressed. That way the system may convert the character to a
8266 composed one.
8267 if ((mods & optionKey) &&
8268 (( !NILP(Vmac_option_modifier) ||
8269 ((mods & cmdKey) || (mods & controlKey))))) */
8271 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
8272 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8273 if (INTEGERP(val))
8274 result |= XUINT(val);
8276 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8277 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8278 if (INTEGERP(val))
8279 result |= XUINT(val);
8281 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8282 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8283 if (INTEGERP(val))
8284 result |= XUINT(val);
8287 #ifdef MAC_OSX
8288 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8289 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8290 if (INTEGERP(val))
8291 result |= XUINT(val);
8293 #endif
8295 return result;
8298 UInt32
8299 mac_mapped_modifiers (modifiers, key_code)
8300 UInt32 modifiers, key_code;
8302 UInt32 mapped_modifiers_all =
8303 (NILP (Vmac_control_modifier) ? 0 : controlKey)
8304 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
8305 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
8307 #ifdef MAC_OSX
8308 mapped_modifiers_all |=
8309 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
8311 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
8312 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
8313 no longer means laptop's `fn' key is down for the following keys:
8314 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
8315 Down, the arrow keys, and Clear. We ignore the corresponding bit
8316 if that key can be entered without the `fn' key on laptops. */
8317 if (modifiers & kEventKeyModifierFnMask
8318 && key_code <= 0x7f
8319 && fn_keycode_to_keycode_table[key_code] == key_code)
8320 modifiers &= ~kEventKeyModifierFnMask;
8321 #endif
8323 return mapped_modifiers_all & modifiers;
8327 mac_get_emulated_btn ( UInt32 modifiers )
8329 int result = 0;
8330 if (!NILP (Vmac_emulate_three_button_mouse)) {
8331 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
8332 if (modifiers & cmdKey)
8333 result = cmdIs3 ? 2 : 1;
8334 else if (modifiers & optionKey)
8335 result = cmdIs3 ? 1 : 2;
8337 return result;
8340 #ifdef MAC_OSX
8341 void
8342 mac_get_selected_range (w, range)
8343 struct window *w;
8344 CFRange *range;
8346 Lisp_Object overlay = find_symbol_value (Qmouse_drag_overlay);
8347 struct buffer *b = XBUFFER (w->buffer);
8348 int begv = BUF_BEGV (b), zv = BUF_ZV (b);
8349 int start, end;
8351 if (OVERLAYP (overlay)
8352 && EQ (Foverlay_buffer (overlay), w->buffer)
8353 && (start = XINT (Foverlay_start (overlay)),
8354 end = XINT (Foverlay_end (overlay)),
8355 start != end))
8357 else
8359 if (w == XWINDOW (selected_window) && b == current_buffer)
8360 start = PT;
8361 else
8362 start = marker_position (w->pointm);
8364 if (NILP (Vtransient_mark_mode) || NILP (b->mark_active))
8365 end = start;
8366 else
8368 int mark_pos = marker_position (b->mark);
8370 if (start <= mark_pos)
8371 end = mark_pos;
8372 else
8374 end = start;
8375 start = mark_pos;
8380 if (start != end)
8382 if (start < begv)
8383 start = begv;
8384 else if (start > zv)
8385 start = zv;
8387 if (end < begv)
8388 end = begv;
8389 else if (end > zv)
8390 end = zv;
8393 range->location = start - begv;
8394 range->length = end - start;
8397 /* Store the text of the buffer BUF from START to END as Unicode
8398 characters in CHARACTERS. Return non-zero if successful. */
8401 mac_store_buffer_text_to_unicode_chars (buf, start, end, characters)
8402 struct buffer *buf;
8403 int start, end;
8404 UniChar *characters;
8406 int start_byte, end_byte, char_count, byte_count;
8407 struct coding_system coding;
8408 unsigned char *dst = (unsigned char *) characters;
8410 start_byte = buf_charpos_to_bytepos (buf, start);
8411 end_byte = buf_charpos_to_bytepos (buf, end);
8412 char_count = end - start;
8413 byte_count = end_byte - start_byte;
8415 if (setup_coding_system (
8416 #ifdef WORDS_BIG_ENDIAN
8417 intern ("utf-16be")
8418 #else
8419 intern ("utf-16le")
8420 #endif
8421 , &coding) < 0)
8422 return 0;
8424 coding.src_multibyte = !NILP (buf->enable_multibyte_characters);
8425 coding.dst_multibyte = 0;
8426 coding.mode |= CODING_MODE_LAST_BLOCK;
8427 coding.composing = COMPOSITION_DISABLED;
8429 if (BUF_GPT_BYTE (buf) <= start_byte || end_byte <= BUF_GPT_BYTE (buf))
8430 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8431 byte_count, char_count * sizeof (UniChar));
8432 else
8434 int first_byte_count = BUF_GPT_BYTE (buf) - start_byte;
8436 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8437 first_byte_count, char_count * sizeof (UniChar));
8438 if (coding.result == CODING_FINISH_NORMAL)
8439 encode_coding (&coding,
8440 BUF_BYTE_ADDRESS (buf, start_byte + first_byte_count),
8441 dst + coding.produced,
8442 byte_count - first_byte_count,
8443 char_count * sizeof (UniChar) - coding.produced);
8446 if (coding.result != CODING_FINISH_NORMAL)
8447 return 0;
8449 return 1;
8452 void
8453 mac_ax_selected_text_range (f, range)
8454 struct frame *f;
8455 CFRange *range;
8457 mac_get_selected_range (XWINDOW (f->selected_window), range);
8460 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8461 unsigned int
8462 mac_ax_number_of_characters (f)
8463 struct frame *f;
8465 struct buffer *b = XBUFFER (XWINDOW (f->selected_window)->buffer);
8467 return BUF_ZV (b) - BUF_BEGV (b);
8469 #endif
8470 #endif
8472 #if USE_MAC_TSM
8473 OSStatus
8474 mac_restore_keyboard_input_source ()
8476 OSStatus err = noErr;
8477 ScriptLanguageRecord slrec, *slptr = NULL;
8479 if (EQ (Vmac_ts_script_language_on_focus, Qt)
8480 && EQ (saved_ts_script_language_on_focus, Qt))
8481 slptr = &saved_ts_language;
8482 else if (CONSP (Vmac_ts_script_language_on_focus)
8483 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8484 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
8485 && CONSP (saved_ts_script_language_on_focus)
8486 && EQ (XCAR (saved_ts_script_language_on_focus),
8487 XCAR (Vmac_ts_script_language_on_focus))
8488 && EQ (XCDR (saved_ts_script_language_on_focus),
8489 XCDR (Vmac_ts_script_language_on_focus)))
8491 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8492 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8493 slptr = &slrec;
8496 if (slptr)
8498 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8499 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
8500 kKeyboardInputMethodClass);
8501 #else
8502 err = SetDefaultInputMethod (saved_ts_component, slptr);
8503 #endif
8504 if (err == noErr)
8505 err = SetTextServiceLanguage (slptr);
8507 /* Seems to be needed on Mac OS X 10.2. */
8508 if (err == noErr)
8509 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
8512 return err;
8515 void
8516 mac_save_keyboard_input_source ()
8518 OSStatus err;
8519 ScriptLanguageRecord slrec, *slptr = NULL;
8521 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
8523 if (EQ (Vmac_ts_script_language_on_focus, Qt))
8525 err = GetTextServiceLanguage (&saved_ts_language);
8526 if (err == noErr)
8527 slptr = &saved_ts_language;
8529 else if (CONSP (Vmac_ts_script_language_on_focus)
8530 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8531 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
8533 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8534 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8535 slptr = &slrec;
8538 if (slptr)
8540 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8541 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
8542 kKeyboardInputMethodClass);
8543 #else
8544 GetDefaultInputMethod (&saved_ts_component, slptr);
8545 #endif
8548 #endif
8550 #if TARGET_API_MAC_CARBON
8551 /***** Code to handle C-g testing *****/
8552 extern int quit_char;
8553 extern int make_ctrl_char P_ ((int));
8556 mac_quit_char_key_p (modifiers, key_code)
8557 UInt32 modifiers, key_code;
8559 UInt32 char_code, mapped_modifiers;
8560 unsigned long some_state = 0;
8561 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8562 int c, emacs_modifiers;
8564 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
8565 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8566 key_code |= (modifiers & ~mapped_modifiers);
8567 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
8568 if (char_code & ~0xff)
8569 return 0;
8571 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8572 if (emacs_modifiers & ctrl_modifier)
8573 c = make_ctrl_char (char_code);
8575 c |= (emacs_modifiers
8576 & (meta_modifier | alt_modifier
8577 | hyper_modifier | super_modifier));
8579 return c == quit_char;
8581 #endif
8583 static void
8584 mac_set_unicode_keystroke_event (code, buf)
8585 UniChar code;
8586 struct input_event *buf;
8588 int charset_id, c1, c2;
8590 if (code < 0x80)
8592 buf->kind = ASCII_KEYSTROKE_EVENT;
8593 buf->code = code;
8595 else if (code < 0x100)
8597 if (code < 0xA0)
8598 charset_id = CHARSET_8_BIT_CONTROL;
8599 else
8600 charset_id = charset_latin_iso8859_1;
8601 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8602 buf->code = MAKE_CHAR (charset_id, code, 0);
8604 else
8606 if (code < 0x2500)
8607 charset_id = charset_mule_unicode_0100_24ff,
8608 code -= 0x100;
8609 else if (code < 0x33FF)
8610 charset_id = charset_mule_unicode_2500_33ff,
8611 code -= 0x2500;
8612 else if (code >= 0xE000)
8613 charset_id = charset_mule_unicode_e000_ffff,
8614 code -= 0xE000;
8615 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
8616 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8617 buf->code = MAKE_CHAR (charset_id, c1, c2);
8621 void
8622 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
8623 EventKind action;
8624 unsigned char char_code;
8625 UInt32 key_code, modifiers;
8626 unsigned long timestamp;
8627 struct input_event *buf;
8629 static SInt16 last_key_script = -1;
8630 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
8631 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8633 #ifdef MAC_OSX
8634 if (mapped_modifiers & kEventKeyModifierFnMask
8635 && key_code <= 0x7f
8636 && fn_keycode_to_keycode_table[key_code])
8637 key_code = fn_keycode_to_keycode_table[key_code];
8638 #endif
8640 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
8642 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
8643 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
8645 else if (mapped_modifiers)
8647 /* translate the keycode back to determine the original key */
8648 #ifdef MAC_OSX
8649 UCKeyboardLayout *uchr_ptr = NULL;
8650 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8651 OSStatus err;
8652 KeyboardLayoutRef layout;
8654 err = KLGetCurrentKeyboardLayout (&layout);
8655 if (err == noErr)
8656 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
8657 (const void **) &uchr_ptr);
8658 #else
8659 static SInt16 last_key_layout_id = 0;
8660 static Handle uchr_handle = (Handle)-1;
8661 SInt16 current_key_layout_id =
8662 GetScriptVariable (current_key_script, smScriptKeys);
8664 if (uchr_handle == (Handle)-1
8665 || last_key_layout_id != current_key_layout_id)
8667 uchr_handle = GetResource ('uchr', current_key_layout_id);
8668 last_key_layout_id = current_key_layout_id;
8670 if (uchr_handle)
8671 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
8672 #endif
8674 if (uchr_ptr)
8676 OSStatus status;
8677 UInt16 key_action = action - keyDown;
8678 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
8679 UInt32 keyboard_type = LMGetKbdType ();
8680 SInt32 dead_key_state = 0;
8681 UniChar code;
8682 UniCharCount actual_length;
8684 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
8685 modifier_key_state, keyboard_type,
8686 kUCKeyTranslateNoDeadKeysMask,
8687 &dead_key_state,
8688 1, &actual_length, &code);
8689 if (status == noErr && actual_length == 1)
8690 mac_set_unicode_keystroke_event (code, buf);
8692 #endif /* MAC_OSX */
8694 if (buf->kind == NO_EVENT)
8696 /* This code comes from Keyboard Resource, Appendix C of IM
8697 - Text. This is necessary since shift is ignored in KCHR
8698 table translation when option or command is pressed. It
8699 also does not translate correctly control-shift chars
8700 like C-% so mask off shift here also. */
8701 /* Mask off modifier keys that are mapped to some Emacs
8702 modifiers. */
8703 int new_modifiers = modifiers & ~mapped_modifiers;
8704 /* set high byte of keycode to modifier high byte*/
8705 int new_key_code = key_code | new_modifiers;
8706 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8707 unsigned long some_state = 0;
8708 UInt32 new_char_code;
8710 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
8711 if (new_char_code == 0)
8712 /* Seems like a dead key. Append up-stroke. */
8713 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
8714 &some_state);
8715 if (new_char_code)
8717 buf->kind = ASCII_KEYSTROKE_EVENT;
8718 buf->code = new_char_code & 0xff;
8723 if (buf->kind == NO_EVENT)
8725 buf->kind = ASCII_KEYSTROKE_EVENT;
8726 buf->code = char_code;
8729 buf->modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8730 buf->modifiers |= (extra_keyboard_modifiers
8731 & (meta_modifier | alt_modifier
8732 | hyper_modifier | super_modifier));
8734 #if TARGET_API_MAC_CARBON
8735 if (buf->kind == ASCII_KEYSTROKE_EVENT
8736 && buf->code >= 0x80 && buf->modifiers)
8738 OSStatus err;
8739 TextEncoding encoding = kTextEncodingMacRoman;
8740 TextToUnicodeInfo ttu_info;
8742 UpgradeScriptInfoToTextEncoding (current_key_script,
8743 kTextLanguageDontCare,
8744 kTextRegionDontCare,
8745 NULL, &encoding);
8746 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
8747 if (err == noErr)
8749 UniChar code;
8750 Str255 pstr;
8751 ByteCount unicode_len;
8753 pstr[0] = 1;
8754 pstr[1] = buf->code;
8755 err = ConvertFromPStringToUnicode (ttu_info, pstr,
8756 sizeof (UniChar),
8757 &unicode_len, &code);
8758 if (err == noErr && unicode_len == sizeof (UniChar))
8759 mac_set_unicode_keystroke_event (code, buf);
8760 DisposeTextToUnicodeInfo (&ttu_info);
8763 #endif
8765 if (buf->kind == ASCII_KEYSTROKE_EVENT
8766 && buf->code >= 0x80
8767 && last_key_script != current_key_script)
8769 struct input_event event;
8771 EVENT_INIT (event);
8772 event.kind = LANGUAGE_CHANGE_EVENT;
8773 event.arg = Qnil;
8774 event.code = current_key_script;
8775 event.timestamp = timestamp;
8776 kbd_buffer_store_event (&event);
8777 last_key_script = current_key_script;
8781 void
8782 mac_store_apple_event (class, id, desc)
8783 Lisp_Object class, id;
8784 const AEDesc *desc;
8786 struct input_event buf;
8788 EVENT_INIT (buf);
8790 buf.kind = MAC_APPLE_EVENT;
8791 buf.x = class;
8792 buf.y = id;
8793 XSETFRAME (buf.frame_or_window,
8794 mac_focus_frame (&one_mac_display_info));
8795 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
8796 is safe to use them during read_socket_hook. */
8797 buf.arg = mac_aedesc_to_lisp (desc);
8798 kbd_buffer_store_event (&buf);
8801 #if TARGET_API_MAC_CARBON
8802 OSStatus
8803 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
8804 event, num_params, names, types)
8805 AEEventClass class;
8806 AEEventID id;
8807 Lisp_Object class_key, id_key;
8808 EventRef event;
8809 UInt32 num_params;
8810 const EventParamName *names;
8811 const EventParamType *types;
8813 OSStatus err = eventNotHandledErr;
8814 Lisp_Object binding;
8816 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
8817 if (!NILP (binding) && !EQ (binding, Qundefined))
8819 if (INTEGERP (binding))
8820 err = XINT (binding);
8821 else
8823 struct input_event buf;
8825 EVENT_INIT (buf);
8827 buf.kind = MAC_APPLE_EVENT;
8828 buf.x = class_key;
8829 buf.y = id_key;
8830 XSETFRAME (buf.frame_or_window,
8831 mac_focus_frame (&one_mac_display_info));
8832 /* Now that Lisp object allocations are protected by
8833 BLOCK_INPUT, it is safe to use them during
8834 read_socket_hook. */
8835 buf.arg = Fcons (build_string ("aevt"),
8836 mac_event_parameters_to_lisp (event, num_params,
8837 names, types));
8838 kbd_buffer_store_event (&buf);
8839 mac_wakeup_from_rne ();
8843 return err;
8845 #endif /* TARGET_API_MAC_CARBON */
8847 static pascal void
8848 mac_handle_dm_notification (event)
8849 AppleEvent *event;
8851 mac_screen_config_changed = 1;
8854 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8855 static void
8856 mac_handle_cg_display_reconfig (display, flags, user_info)
8857 CGDirectDisplayID display;
8858 CGDisplayChangeSummaryFlags flags;
8859 void *user_info;
8861 mac_screen_config_changed = 1;
8863 #endif
8865 static OSErr
8866 init_dm_notification_handler ()
8868 OSErr err = noErr;
8870 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8871 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8872 if (CGDisplayRegisterReconfigurationCallback != NULL)
8873 #endif
8875 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
8876 NULL);
8878 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8879 else /* CGDisplayRegisterReconfigurationCallback == NULL */
8880 #endif
8881 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
8882 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8884 static DMNotificationUPP handle_dm_notificationUPP = NULL;
8885 ProcessSerialNumber psn;
8887 if (handle_dm_notificationUPP == NULL)
8888 handle_dm_notificationUPP =
8889 NewDMNotificationUPP (mac_handle_dm_notification);
8891 err = GetCurrentProcess (&psn);
8892 if (err == noErr)
8893 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
8895 #endif
8897 return err;
8900 void
8901 mac_get_screen_info (dpyinfo)
8902 struct mac_display_info *dpyinfo;
8904 #ifdef MAC_OSX
8905 /* HasDepth returns true if it is possible to have a 32 bit display,
8906 but this may not be what is actually used. Mac OSX can do better. */
8907 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
8908 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
8910 CGDisplayErr err;
8911 CGDisplayCount ndisps;
8912 CGDirectDisplayID *displays;
8914 err = CGGetActiveDisplayList (0, NULL, &ndisps);
8915 if (err == noErr)
8917 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
8918 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
8920 if (err == noErr)
8922 CGRect bounds = CGRectZero;
8924 while (ndisps-- > 0)
8925 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
8926 dpyinfo->height = CGRectGetHeight (bounds);
8927 dpyinfo->width = CGRectGetWidth (bounds);
8929 else
8931 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
8932 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
8935 #else /* !MAC_OSX */
8937 GDHandle gdh = GetMainDevice ();
8938 Rect rect = (**gdh).gdRect;
8940 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
8941 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
8942 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
8943 break;
8945 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
8946 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
8947 UnionRect (&rect, &(**gdh).gdRect, &rect);
8949 dpyinfo->height = rect.bottom - rect.top;
8950 dpyinfo->width = rect.right - rect.left;
8952 #endif /* !MAC_OSX */
8956 /***********************************************************************
8957 Initialization (Mac OS Classic)
8958 ***********************************************************************/
8960 #ifdef MAC_OS8
8961 extern void init_emacs_passwd_dir ();
8962 extern int emacs_main (int, char **, char **);
8964 extern void initialize_applescript();
8965 extern void terminate_applescript();
8967 static void
8968 do_get_menus (void)
8970 Handle menubar_handle;
8971 MenuRef menu;
8973 menubar_handle = GetNewMBar (128);
8974 if(menubar_handle == NULL)
8975 abort ();
8976 SetMenuBar (menubar_handle);
8977 DrawMenuBar ();
8979 #if !TARGET_API_MAC_CARBON
8980 menu = GetMenuRef (M_APPLE);
8981 if (menu != NULL)
8982 AppendResMenu (menu, 'DRVR');
8983 else
8984 abort ();
8985 #endif
8988 static void
8989 do_init_managers (void)
8991 #if !TARGET_API_MAC_CARBON
8992 InitGraf (&qd.thePort);
8993 InitFonts ();
8994 FlushEvents (everyEvent, 0);
8995 InitWindows ();
8996 InitMenus ();
8997 TEInit ();
8998 InitDialogs (NULL);
8999 #endif /* !TARGET_API_MAC_CARBON */
9000 InitCursor ();
9002 #if !TARGET_API_MAC_CARBON
9003 /* set up some extra stack space for use by emacs */
9004 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
9006 /* MaxApplZone must be called for AppleScript to execute more
9007 complicated scripts */
9008 MaxApplZone ();
9009 MoreMasters ();
9010 #endif /* !TARGET_API_MAC_CARBON */
9013 static void
9014 do_check_ram_size (void)
9016 SInt32 physical_ram_size, logical_ram_size;
9018 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9019 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9020 || physical_ram_size > (1 << VALBITS)
9021 || logical_ram_size > (1 << VALBITS))
9023 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9024 exit (1);
9028 #if __profile__
9029 void
9030 profiler_exit_proc ()
9032 ProfilerDump ("\pEmacs.prof");
9033 ProfilerTerm ();
9035 #endif
9037 /* These few functions implement Emacs as a normal Mac application
9038 (almost): set up the heap and the Toolbox, handle necessary system
9039 events plus a few simple menu events. They also set up Emacs's
9040 access to functions defined in the rest of this file. Emacs uses
9041 function hooks to perform all its terminal I/O. A complete list of
9042 these functions appear in termhooks.h. For what they do, read the
9043 comments there and see also w32term.c and xterm.c. What's
9044 noticeably missing here is the event loop, which is normally
9045 present in most Mac application. After performing the necessary
9046 Mac initializations, main passes off control to emacs_main
9047 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9048 (defined further below) to read input. This is where
9049 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9051 #undef main
9053 main (void)
9055 #if __profile__ /* is the profiler on? */
9056 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
9057 exit(1);
9058 #endif
9060 #if __MWERKS__
9061 /* set creator and type for files created by MSL */
9062 _fcreator = MAC_EMACS_CREATOR_CODE;
9063 _ftype = 'TEXT';
9064 #endif
9066 do_init_managers ();
9068 do_get_menus ();
9070 #ifndef USE_LSB_TAG
9071 do_check_ram_size ();
9072 #endif
9074 init_emacs_passwd_dir ();
9076 init_environ ();
9078 init_coercion_handler ();
9080 initialize_applescript ();
9082 init_apple_event_handler ();
9084 init_dm_notification_handler ();
9087 char **argv;
9088 int argc = 0;
9090 /* set up argv array from STR# resource */
9091 get_string_list (&argv, ARGV_STRING_LIST_ID);
9092 while (argv[argc])
9093 argc++;
9095 /* free up AppleScript resources on exit */
9096 atexit (terminate_applescript);
9098 #if __profile__ /* is the profiler on? */
9099 atexit (profiler_exit_proc);
9100 #endif
9102 /* 3rd param "envp" never used in emacs_main */
9103 (void) emacs_main (argc, argv, 0);
9106 /* Never reached - real exit in Fkill_emacs */
9107 return 0;
9110 /* Need to override CodeWarrior's input function so no conversion is
9111 done on newlines Otherwise compiled functions in .elc files will be
9112 read incorrectly. Defined in ...:MSL C:MSL
9113 Common:Source:buffer_io.c. */
9114 #ifdef __MWERKS__
9115 void
9116 __convert_to_newlines (unsigned char * p, size_t * n)
9118 #pragma unused(p,n)
9121 void
9122 __convert_from_newlines (unsigned char * p, size_t * n)
9124 #pragma unused(p,n)
9126 #endif
9128 void
9129 make_mac_terminal_frame (struct frame *f)
9131 Lisp_Object frame;
9132 Rect r;
9134 XSETFRAME (frame, f);
9136 f->output_method = output_mac;
9137 f->output_data.mac = (struct mac_output *)
9138 xmalloc (sizeof (struct mac_output));
9139 bzero (f->output_data.mac, sizeof (struct mac_output));
9141 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9143 FRAME_COLS (f) = 96;
9144 FRAME_LINES (f) = 4;
9146 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9147 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9149 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9151 f->output_data.mac->cursor_pixel = 0;
9152 f->output_data.mac->border_pixel = 0x00ff00;
9153 f->output_data.mac->mouse_pixel = 0xff00ff;
9154 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9156 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9157 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9158 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9159 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9160 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9161 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9163 FRAME_FONTSET (f) = -1;
9164 f->output_data.mac->explicit_parent = 0;
9165 f->left_pos = 8;
9166 f->top_pos = 32;
9167 f->border_width = 0;
9169 f->internal_border_width = 0;
9171 f->auto_raise = 1;
9172 f->auto_lower = 1;
9174 f->new_text_cols = 0;
9175 f->new_text_lines = 0;
9177 SetRect (&r, f->left_pos, f->top_pos,
9178 f->left_pos + FRAME_PIXEL_WIDTH (f),
9179 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9181 BLOCK_INPUT;
9183 if (!(FRAME_MAC_WINDOW (f) =
9184 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9185 (WindowRef) -1, 1, (long) f->output_data.mac)))
9186 abort ();
9187 /* so that update events can find this mac_output struct */
9188 f->output_data.mac->mFP = f; /* point back to emacs frame */
9190 UNBLOCK_INPUT;
9192 x_make_gc (f);
9194 /* Need to be initialized for unshow_buffer in window.c. */
9195 selected_window = f->selected_window;
9197 Fmodify_frame_parameters (frame,
9198 Fcons (Fcons (Qfont,
9199 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9200 Fmodify_frame_parameters (frame,
9201 Fcons (Fcons (Qforeground_color,
9202 build_string ("black")), Qnil));
9203 Fmodify_frame_parameters (frame,
9204 Fcons (Fcons (Qbackground_color,
9205 build_string ("white")), Qnil));
9207 #endif /* MAC_OS8 */
9210 /***********************************************************************
9211 Initialization
9212 ***********************************************************************/
9214 static int mac_initialized = 0;
9216 static XrmDatabase
9217 mac_make_rdb (xrm_option)
9218 const char *xrm_option;
9220 XrmDatabase database;
9222 database = xrm_get_preference_database (NULL);
9223 if (xrm_option)
9224 xrm_merge_string_database (database, xrm_option);
9226 return database;
9229 struct mac_display_info *
9230 mac_term_init (display_name, xrm_option, resource_name)
9231 Lisp_Object display_name;
9232 char *xrm_option;
9233 char *resource_name;
9235 struct mac_display_info *dpyinfo;
9237 BLOCK_INPUT;
9239 if (!mac_initialized)
9241 mac_initialize ();
9242 mac_initialized = 1;
9245 if (x_display_list)
9246 error ("Sorry, this version can only handle one display");
9248 dpyinfo = &one_mac_display_info;
9249 bzero (dpyinfo, sizeof (*dpyinfo));
9251 #ifdef MAC_OSX
9252 dpyinfo->mac_id_name
9253 = (char *) xmalloc (SCHARS (Vinvocation_name)
9254 + SCHARS (Vsystem_name)
9255 + 2);
9256 sprintf (dpyinfo->mac_id_name, "%s@%s",
9257 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9258 #else
9259 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9260 strcpy (dpyinfo->mac_id_name, "Mac Display");
9261 #endif
9263 dpyinfo->reference_count = 0;
9264 dpyinfo->resx = 72.0;
9265 dpyinfo->resy = 72.0;
9267 mac_get_screen_info (dpyinfo);
9269 dpyinfo->grabbed = 0;
9270 dpyinfo->root_window = NULL;
9271 dpyinfo->image_cache = make_image_cache ();
9273 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9274 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9275 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9276 dpyinfo->mouse_face_window = Qnil;
9277 dpyinfo->mouse_face_overlay = Qnil;
9278 dpyinfo->mouse_face_hidden = 0;
9280 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9282 /* Put this display on the chain. */
9283 dpyinfo->next = x_display_list;
9284 x_display_list = dpyinfo;
9286 /* Put it on x_display_name_list. */
9287 x_display_name_list = Fcons (Fcons (display_name,
9288 Fcons (Qnil, dpyinfo->xrdb)),
9289 x_display_name_list);
9290 dpyinfo->name_list_element = XCAR (x_display_name_list);
9292 UNBLOCK_INPUT;
9294 return dpyinfo;
9297 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9299 void
9300 x_delete_display (dpyinfo)
9301 struct mac_display_info *dpyinfo;
9303 int i;
9305 /* Discard this display from x_display_name_list and x_display_list.
9306 We can't use Fdelq because that can quit. */
9307 if (! NILP (x_display_name_list)
9308 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9309 x_display_name_list = XCDR (x_display_name_list);
9310 else
9312 Lisp_Object tail;
9314 tail = x_display_name_list;
9315 while (CONSP (tail) && CONSP (XCDR (tail)))
9317 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9319 XSETCDR (tail, XCDR (XCDR (tail)));
9320 break;
9322 tail = XCDR (tail);
9326 if (x_display_list == dpyinfo)
9327 x_display_list = dpyinfo->next;
9328 else
9330 struct x_display_info *tail;
9332 for (tail = x_display_list; tail; tail = tail->next)
9333 if (tail->next == dpyinfo)
9334 tail->next = tail->next->next;
9337 /* Free the font names in the font table. */
9338 for (i = 0; i < dpyinfo->n_fonts; i++)
9339 if (dpyinfo->font_table[i].name)
9341 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9342 xfree (dpyinfo->font_table[i].full_name);
9343 xfree (dpyinfo->font_table[i].name);
9346 if (dpyinfo->font_table)
9348 if (dpyinfo->font_table->font_encoder)
9349 xfree (dpyinfo->font_table->font_encoder);
9350 xfree (dpyinfo->font_table);
9352 if (dpyinfo->mac_id_name)
9353 xfree (dpyinfo->mac_id_name);
9355 if (x_display_list == 0)
9357 mac_clear_font_name_table ();
9358 bzero (dpyinfo, sizeof (*dpyinfo));
9363 /* Set up use of X before we make the first connection. */
9365 extern frame_parm_handler mac_frame_parm_handlers[];
9367 static struct redisplay_interface x_redisplay_interface =
9369 mac_frame_parm_handlers,
9370 x_produce_glyphs,
9371 x_write_glyphs,
9372 x_insert_glyphs,
9373 x_clear_end_of_line,
9374 x_scroll_run,
9375 x_after_update_window_line,
9376 x_update_window_begin,
9377 x_update_window_end,
9378 x_cursor_to,
9379 x_flush,
9380 #if USE_CG_DRAWING
9381 mac_flush_display_optional,
9382 #else
9383 0, /* flush_display_optional */
9384 #endif
9385 x_clear_window_mouse_face,
9386 x_get_glyph_overhangs,
9387 x_fix_overlapping_area,
9388 x_draw_fringe_bitmap,
9389 #if USE_CG_DRAWING
9390 mac_define_fringe_bitmap,
9391 mac_destroy_fringe_bitmap,
9392 #else
9393 0, /* define_fringe_bitmap */
9394 0, /* destroy_fringe_bitmap */
9395 #endif
9396 mac_per_char_metric,
9397 mac_encode_char,
9398 mac_compute_glyph_string_overhangs,
9399 x_draw_glyph_string,
9400 mac_define_frame_cursor,
9401 mac_clear_frame_area,
9402 mac_draw_window_cursor,
9403 mac_draw_vertical_window_border,
9404 mac_shift_glyphs_for_insert
9407 void
9408 mac_initialize ()
9410 rif = &x_redisplay_interface;
9412 clear_frame_hook = x_clear_frame;
9413 ins_del_lines_hook = x_ins_del_lines;
9414 delete_glyphs_hook = x_delete_glyphs;
9415 ring_bell_hook = XTring_bell;
9416 reset_terminal_modes_hook = XTreset_terminal_modes;
9417 set_terminal_modes_hook = XTset_terminal_modes;
9418 update_begin_hook = x_update_begin;
9419 update_end_hook = x_update_end;
9420 set_terminal_window_hook = XTset_terminal_window;
9421 read_socket_hook = XTread_socket;
9422 frame_up_to_date_hook = XTframe_up_to_date;
9423 mouse_position_hook = XTmouse_position;
9424 frame_rehighlight_hook = XTframe_rehighlight;
9425 frame_raise_lower_hook = XTframe_raise_lower;
9427 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9428 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9429 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9430 judge_scroll_bars_hook = XTjudge_scroll_bars;
9432 scroll_region_ok = 1; /* we'll scroll partial frames */
9433 char_ins_del_ok = 1;
9434 line_ins_del_ok = 1; /* we'll just blt 'em */
9435 fast_clear_end_of_line = 1; /* X does this well */
9436 memory_below_frame = 0; /* we don't remember what scrolls
9437 off the bottom */
9438 baud_rate = 19200;
9440 last_tool_bar_item = -1;
9442 /* Try to use interrupt input; if we can't, then start polling. */
9443 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9445 BLOCK_INPUT;
9447 #if TARGET_API_MAC_CARBON
9448 #ifdef MAC_OSX
9449 init_coercion_handler ();
9451 init_dm_notification_handler ();
9452 #endif
9454 install_application_handler ();
9456 mac_toolbox_initialize ();
9458 #ifdef MAC_OSX
9459 if (!inhibit_window_system)
9461 static const ProcessSerialNumber psn = {0, kCurrentProcess};
9463 SetFrontProcess (&psn);
9465 #endif
9466 #endif
9468 #if USE_CG_DRAWING
9469 init_cg_color ();
9471 mac_init_fringe ();
9472 #endif
9474 UNBLOCK_INPUT;
9478 void
9479 syms_of_macterm ()
9481 #if 0
9482 staticpro (&x_error_message_string);
9483 x_error_message_string = Qnil;
9484 #endif
9486 Qcontrol = intern ("control"); staticpro (&Qcontrol);
9487 Qmeta = intern ("meta"); staticpro (&Qmeta);
9488 Qalt = intern ("alt"); staticpro (&Qalt);
9489 Qhyper = intern ("hyper"); staticpro (&Qhyper);
9490 Qsuper = intern ("super"); staticpro (&Qsuper);
9491 Qmodifier_value = intern ("modifier-value");
9492 staticpro (&Qmodifier_value);
9494 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
9495 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
9496 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9497 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9498 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9500 #if TARGET_API_MAC_CARBON
9501 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
9502 #ifdef MAC_OSX
9503 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
9504 staticpro (&Qtoolbar_switch_mode);
9505 #if USE_MAC_FONT_PANEL
9506 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
9507 Qselection = intern ("selection"); staticpro (&Qselection);
9508 #endif
9510 Qservice = intern ("service"); staticpro (&Qservice);
9511 Qpaste = intern ("paste"); staticpro (&Qpaste);
9512 Qperform = intern ("perform"); staticpro (&Qperform);
9514 Qmouse_drag_overlay = intern ("mouse-drag-overlay");
9515 staticpro (&Qmouse_drag_overlay);
9516 #endif
9517 #if USE_MAC_TSM
9518 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
9519 Qupdate_active_input_area = intern ("update-active-input-area");
9520 staticpro (&Qupdate_active_input_area);
9521 Qunicode_for_key_event = intern ("unicode-for-key-event");
9522 staticpro (&Qunicode_for_key_event);
9523 #endif
9524 #endif
9526 #ifdef MAC_OSX
9527 Fprovide (intern ("mac-carbon"), Qnil);
9528 #endif
9530 staticpro (&Qreverse);
9531 Qreverse = intern ("reverse");
9533 staticpro (&x_display_name_list);
9534 x_display_name_list = Qnil;
9536 staticpro (&last_mouse_scroll_bar);
9537 last_mouse_scroll_bar = Qnil;
9539 staticpro (&fm_font_family_alist);
9540 fm_font_family_alist = Qnil;
9542 #if USE_ATSUI
9543 staticpro (&atsu_font_id_hash);
9544 atsu_font_id_hash = Qnil;
9546 staticpro (&fm_style_face_attributes_alist);
9547 fm_style_face_attributes_alist = Qnil;
9548 #endif
9550 #if USE_MAC_TSM
9551 staticpro (&saved_ts_script_language_on_focus);
9552 saved_ts_script_language_on_focus = Qnil;
9553 #endif
9555 /* We don't yet support this, but defining this here avoids whining
9556 from cus-start.el and other places, like "M-x set-variable". */
9557 DEFVAR_BOOL ("x-use-underline-position-properties",
9558 &x_use_underline_position_properties,
9559 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9560 A value of nil means ignore them. If you encounter fonts with bogus
9561 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9562 to 4.1, set this to nil.
9564 NOTE: Not supported on Mac yet. */);
9565 x_use_underline_position_properties = 0;
9567 DEFVAR_BOOL ("x-underline-at-descent-line",
9568 &x_underline_at_descent_line,
9569 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
9570 A value of nil means to draw the underline according to the value of the
9571 variable `x-use-underline-position-properties', which is usually at the
9572 baseline level. The default value is nil. */);
9573 x_underline_at_descent_line = 0;
9575 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9576 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9577 #ifdef USE_TOOLKIT_SCROLL_BARS
9578 Vx_toolkit_scroll_bars = Qt;
9579 #else
9580 Vx_toolkit_scroll_bars = Qnil;
9581 #endif
9583 staticpro (&last_mouse_motion_frame);
9584 last_mouse_motion_frame = Qnil;
9586 /* Variables to configure modifier key assignment. */
9588 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
9589 doc: /* *Modifier key assumed when the Mac control key is pressed.
9590 The value can be `control', `meta', `alt', `hyper', or `super' for the
9591 respective modifier. The default is `control'. */);
9592 Vmac_control_modifier = Qcontrol;
9594 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9595 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
9596 The value can be `control', `meta', `alt', `hyper', or `super' for the
9597 respective modifier. If the value is nil then the key will act as the
9598 normal Mac control modifier, and the option key can be used to compose
9599 characters depending on the chosen Mac keyboard setting. */);
9600 Vmac_option_modifier = Qnil;
9602 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
9603 doc: /* *Modifier key assumed when the Mac command key is pressed.
9604 The value can be `control', `meta', `alt', `hyper', or `super' for the
9605 respective modifier. The default is `meta'. */);
9606 Vmac_command_modifier = Qmeta;
9608 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
9609 doc: /* *Modifier key assumed when the Mac function key is pressed.
9610 The value can be `control', `meta', `alt', `hyper', or `super' for the
9611 respective modifier. Note that remapping the function key may lead to
9612 unexpected results for some keys on non-US/GB keyboards. */);
9613 Vmac_function_modifier = Qnil;
9615 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9616 &Vmac_emulate_three_button_mouse,
9617 doc: /* *Specify a way of three button mouse emulation.
9618 The value can be nil, t, or the symbol `reverse'.
9619 A value of nil means that no emulation should be done and the modifiers
9620 should be placed on the mouse-1 event.
9621 t means that when the option-key is held down while pressing the mouse
9622 button, the click will register as mouse-2 and while the command-key
9623 is held down, the click will register as mouse-3.
9624 The symbol `reverse' means that the option-key will register for
9625 mouse-3 and the command-key will register for mouse-2. */);
9626 Vmac_emulate_three_button_mouse = Qnil;
9628 #if TARGET_API_MAC_CARBON
9629 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
9630 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
9631 Otherwise, the right click will be treated as mouse-2 and the wheel
9632 button will be mouse-3. */);
9633 mac_wheel_button_is_mouse_2 = 1;
9635 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
9636 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
9637 mac_pass_command_to_system = 1;
9639 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
9640 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
9641 mac_pass_control_to_system = 1;
9643 #endif
9645 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
9646 doc: /* *If non-nil, allow anti-aliasing.
9647 The text will be rendered using Core Graphics text rendering which
9648 may anti-alias the text. */);
9649 #if USE_CG_DRAWING
9650 mac_use_core_graphics = 1;
9651 #else
9652 mac_use_core_graphics = 0;
9653 #endif
9655 /* Register an entry for `mac-roman' so that it can be used when
9656 creating the terminal frame on Mac OS 9 before loading
9657 term/mac-win.elc. */
9658 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
9659 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
9660 Each entry should be of the form:
9662 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
9664 where CHARSET-NAME is a string used in font names to identify the
9665 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
9666 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
9667 Vmac_charset_info_alist =
9668 Fcons (list3 (build_string ("mac-roman"),
9669 make_number (smRoman), Qnil), Qnil);
9671 #if USE_MAC_TSM
9672 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
9673 doc: /* Overlay used to display Mac TSM active input area. */);
9674 Vmac_ts_active_input_overlay = Qnil;
9676 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf,
9677 doc: /* Byte sequence of the current Mac TSM active input area. */);
9678 /* `empty_string' is not ready yet on Mac OS Classic. */
9679 Vmac_ts_active_input_buf = build_string ("");
9681 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
9682 doc: /* *How to change Mac TSM script/language when a frame gets focus.
9683 If the value is t, the input script and language are restored to those
9684 used in the last focus frame. If the value is a pair of integers, the
9685 input script and language codes, which are defined in the Script
9686 Manager, are set to its car and cdr parts, respectively. Otherwise,
9687 Emacs doesn't set them and thus follows the system default behavior. */);
9688 Vmac_ts_script_language_on_focus = Qnil;
9689 #endif
9692 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9693 (do not change this comment) */