(Other Plists): Fix incorrect example. Suggested by Florian Beck.
[emacs.git] / src / macterm.c
blob8a0b2d61846801b8855b70339802bc94c396e498
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 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 #if USE_MAC_IMAGE_IO
404 CGContextRef context;
405 XImagePtr ximg = p;
406 CGColorSpaceRef color_space;
407 CGImageAlphaInfo alpha_info;
408 CGFloat gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
410 if (y1 != y2)
411 gx1 += 0.5f, gx2 += 0.5f;
412 if (x1 != x2)
413 gy1 += 0.5f, gy2 += 0.5f;
415 if (ximg->bits_per_pixel == 32)
417 color_space = mac_cg_color_space_rgb;
418 alpha_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
420 else
422 color_space = NULL;
423 alpha_info = kCGImageAlphaOnly;
425 context = CGBitmapContextCreate (ximg->data, ximg->width, ximg->height, 8,
426 ximg->bytes_per_line, color_space,
427 alpha_info);
428 if (ximg->bits_per_pixel == 32)
429 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
430 else
431 CGContextSetGrayStrokeColor (context, gc->xgcv.foreground / 255.0f, 1.0);
432 CGContextMoveToPoint (context, gx1, gy1);
433 CGContextAddLineToPoint (context, gx2, gy2);
434 CGContextClosePath (context);
435 CGContextStrokePath (context);
436 CGContextRelease (context);
437 #else
438 CGrafPtr old_port;
439 GDHandle old_gdh;
441 if (x1 == x2)
443 if (y1 > y2)
444 y1--;
445 else if (y2 > y1)
446 y2--;
448 else if (y1 == y2)
450 if (x1 > x2)
451 x1--;
452 else
453 x2--;
456 GetGWorld (&old_port, &old_gdh);
457 SetGWorld (p, NULL);
459 RGBForeColor (GC_FORE_COLOR (gc));
461 LockPixels (GetGWorldPixMap (p));
462 MoveTo (x1, y1);
463 LineTo (x2, y2);
464 UnlockPixels (GetGWorldPixMap (p));
466 SetGWorld (old_port, old_gdh);
467 #endif
471 static void
472 mac_erase_rectangle (f, gc, x, y, width, height)
473 struct frame *f;
474 GC gc;
475 int x, y;
476 unsigned int width, height;
478 #if USE_CG_DRAWING
480 CGContextRef context;
482 context = mac_begin_cg_clip (f, gc);
483 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
484 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
485 mac_end_cg_clip (f);
487 #else
489 Rect r;
491 mac_begin_clip (f, gc);
492 RGBBackColor (GC_BACK_COLOR (gc));
493 SetRect (&r, x, y, x + width, y + height);
494 EraseRect (&r);
495 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
496 mac_end_clip (f, gc);
498 #endif
502 /* Mac version of XClearArea. */
504 void
505 mac_clear_area (f, x, y, width, height)
506 struct frame *f;
507 int x, y;
508 unsigned int width, height;
510 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
513 /* Mac version of XClearWindow. */
515 static void
516 mac_clear_window (f)
517 struct frame *f;
519 #if USE_CG_DRAWING
521 CGContextRef context;
522 GC gc = FRAME_NORMAL_GC (f);
524 context = mac_begin_cg_clip (f, NULL);
525 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
526 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
527 FRAME_PIXEL_HEIGHT (f)));
528 mac_end_cg_clip (f);
530 #else /* !USE_CG_DRAWING */
531 mac_begin_clip (f, NULL);
532 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
533 #if TARGET_API_MAC_CARBON
535 Rect r;
537 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
538 EraseRect (&r);
540 #else /* not TARGET_API_MAC_CARBON */
541 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
542 #endif /* not TARGET_API_MAC_CARBON */
543 mac_end_clip (f, NULL);
544 #endif
548 /* Mac replacement for XCopyArea. */
550 #if USE_CG_DRAWING
551 static void
552 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
553 dest_x, dest_y, overlay_p)
554 CGImageRef image;
555 struct frame *f;
556 GC gc;
557 int src_x, src_y;
558 unsigned int width, height;
559 int dest_x, dest_y, overlay_p;
561 CGContextRef context;
562 CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
563 CGRect dest_rect = mac_rect_make (f, dest_x, dest_y, width, height);
565 context = mac_begin_cg_clip (f, gc);
566 if (!overlay_p)
568 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
569 CGContextFillRect (context, dest_rect);
571 CGContextClipToRect (context, dest_rect);
572 CGContextScaleCTM (context, 1, -1);
573 CGContextTranslateCTM (context, 0, -port_height);
574 if (CGImageIsMask (image))
575 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
576 CGContextDrawImage (context,
577 mac_rect_make (f, dest_x - src_x,
578 port_height - (dest_y - src_y
579 + CGImageGetHeight (image)),
580 CGImageGetWidth (image),
581 CGImageGetHeight (image)),
582 image);
583 mac_end_cg_clip (f);
586 #else /* !USE_CG_DRAWING */
588 static void
589 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
590 struct frame *f;
591 GC gc;
592 int x, y, width, height;
593 unsigned short *bits;
594 int overlay_p;
596 BitMap bitmap;
597 Rect r;
599 bitmap.rowBytes = sizeof(unsigned short);
600 bitmap.baseAddr = (char *)bits;
601 SetRect (&(bitmap.bounds), 0, 0, width, height);
603 mac_begin_clip (f, gc);
604 RGBForeColor (GC_FORE_COLOR (gc));
605 RGBBackColor (GC_BACK_COLOR (gc));
606 SetRect (&r, x, y, x + width, y + height);
607 #if TARGET_API_MAC_CARBON
609 CGrafPtr port;
611 GetPort (&port);
612 LockPortBits (port);
613 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
614 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
615 UnlockPortBits (port);
617 #else /* not TARGET_API_MAC_CARBON */
618 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
619 overlay_p ? srcOr : srcCopy, 0);
620 #endif /* not TARGET_API_MAC_CARBON */
621 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
622 mac_end_clip (f, gc);
624 #endif /* !USE_CG_DRAWING */
627 /* Mac replacement for XCreateBitmapFromBitmapData. */
629 static void
630 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
631 BitMap *bitmap;
632 char *bits;
633 int w, h;
635 static const unsigned char swap_nibble[16]
636 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
637 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
638 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
639 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
640 int i, j, w1;
641 char *p;
643 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
644 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
645 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
646 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
647 for (i = 0; i < h; i++)
649 p = bitmap->baseAddr + i * bitmap->rowBytes;
650 for (j = 0; j < w1; j++)
652 /* Bitswap XBM bytes to match how Mac does things. */
653 unsigned char c = *bits++;
654 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
655 | (swap_nibble[(c>>4) & 0xf]));
659 SetRect (&(bitmap->bounds), 0, 0, w, h);
663 static void
664 mac_free_bitmap (bitmap)
665 BitMap *bitmap;
667 xfree (bitmap->baseAddr);
671 Pixmap
672 XCreatePixmap (display, w, width, height, depth)
673 Display *display;
674 Window w;
675 unsigned int width, height;
676 unsigned int depth;
678 #if USE_MAC_IMAGE_IO
679 XImagePtr ximg;
681 ximg = xmalloc (sizeof (*ximg));
682 ximg->width = width;
683 ximg->height = height;
684 ximg->bits_per_pixel = depth == 1 ? 8 : 32;
685 ximg->bytes_per_line = width * (ximg->bits_per_pixel / 8);
686 ximg->data = xmalloc (ximg->bytes_per_line * height);
687 return ximg;
688 #else
689 Pixmap pixmap;
690 Rect r;
691 QDErr err;
693 #ifdef MAC_OS8
694 SetPortWindowPort (w);
695 #endif
696 SetRect (&r, 0, 0, width, height);
697 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
698 if (depth == 1)
699 #endif
700 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
701 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
702 else
703 /* CreateCGImageFromPixMaps requires ARGB format. */
704 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
705 #endif
706 if (err != noErr)
707 return NULL;
708 return pixmap;
709 #endif
713 Pixmap
714 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
715 Display *display;
716 Window w;
717 char *data;
718 unsigned int width, height;
719 unsigned long fg, bg;
720 unsigned int depth;
722 Pixmap pixmap;
723 BitMap bitmap;
724 #if USE_MAC_IMAGE_IO
725 CGDataProviderRef provider;
726 CGImageRef image_mask;
727 CGContextRef context;
729 pixmap = XCreatePixmap (display, w, width, height, depth);
730 if (pixmap == NULL)
731 return NULL;
733 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
734 provider = CGDataProviderCreateWithData (NULL, bitmap.baseAddr,
735 bitmap.rowBytes * height, NULL);
736 image_mask = CGImageMaskCreate (width, height, 1, 1, bitmap.rowBytes,
737 provider, NULL, 0);
738 CGDataProviderRelease (provider);
740 context = CGBitmapContextCreate (pixmap->data, width, height, 8,
741 pixmap->bytes_per_line,
742 mac_cg_color_space_rgb,
743 kCGImageAlphaNoneSkipFirst
744 | kCGBitmapByteOrder32Host);
746 CG_SET_FILL_COLOR (context, fg);
747 CGContextFillRect (context, CGRectMake (0, 0, width, height));
748 CG_SET_FILL_COLOR (context, bg);
749 CGContextDrawImage (context, CGRectMake (0, 0, width, height), image_mask);
750 CGContextRelease (context);
751 CGImageRelease (image_mask);
752 #else
753 CGrafPtr old_port;
754 GDHandle old_gdh;
755 static GC gc = NULL;
757 if (gc == NULL)
758 gc = XCreateGC (display, w, 0, NULL);
760 pixmap = XCreatePixmap (display, w, width, height, depth);
761 if (pixmap == NULL)
762 return NULL;
764 GetGWorld (&old_port, &old_gdh);
765 SetGWorld (pixmap, NULL);
766 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
767 XSetForeground (display, gc, fg);
768 XSetBackground (display, gc, bg);
769 RGBForeColor (GC_FORE_COLOR (gc));
770 RGBBackColor (GC_BACK_COLOR (gc));
771 LockPixels (GetGWorldPixMap (pixmap));
772 #if TARGET_API_MAC_CARBON
773 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
774 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
775 #else /* not TARGET_API_MAC_CARBON */
776 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
777 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
778 #endif /* not TARGET_API_MAC_CARBON */
779 UnlockPixels (GetGWorldPixMap (pixmap));
780 SetGWorld (old_port, old_gdh);
781 #endif
782 mac_free_bitmap (&bitmap);
784 return pixmap;
788 void
789 XFreePixmap (display, pixmap)
790 Display *display;
791 Pixmap pixmap;
793 #if USE_MAC_IMAGE_IO
794 if (pixmap)
796 if (pixmap->data)
797 xfree (pixmap->data);
798 xfree (pixmap);
800 #else
801 DisposeGWorld (pixmap);
802 #endif
806 /* Mac replacement for XFillRectangle. */
808 static void
809 mac_fill_rectangle (f, gc, x, y, width, height)
810 struct frame *f;
811 GC gc;
812 int x, y;
813 unsigned int width, height;
815 #if USE_CG_DRAWING
816 CGContextRef context;
818 context = mac_begin_cg_clip (f, gc);
819 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
820 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
821 mac_end_cg_clip (f);
822 #else
823 Rect r;
825 mac_begin_clip (f, gc);
826 RGBForeColor (GC_FORE_COLOR (gc));
827 SetRect (&r, x, y, x + width, y + height);
828 PaintRect (&r); /* using foreground color of gc */
829 mac_end_clip (f, gc);
830 #endif
834 /* Mac replacement for XDrawRectangle: dest is a window. */
836 static void
837 mac_draw_rectangle (f, gc, x, y, width, height)
838 struct frame *f;
839 GC gc;
840 int x, y;
841 unsigned int width, height;
843 #if USE_CG_DRAWING
844 CGContextRef context;
846 context = mac_begin_cg_clip (f, gc);
847 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
848 CGContextStrokeRect (context,
849 CGRectMake (x + 0.5f, y + 0.5f, width, height));
850 mac_end_cg_clip (f);
851 #else
852 Rect r;
854 mac_begin_clip (f, gc);
855 RGBForeColor (GC_FORE_COLOR (gc));
856 SetRect (&r, x, y, x + width + 1, y + height + 1);
857 FrameRect (&r); /* using foreground color of gc */
858 mac_end_clip (f, gc);
859 #endif
863 static void
864 mac_invert_rectangle (f, x, y, width, height)
865 struct frame *f;
866 int x, y;
867 unsigned int width, height;
869 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
870 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
871 if (CGContextSetBlendMode != NULL)
872 #endif
874 CGContextRef context;
876 context = mac_begin_cg_clip (f, NULL);
877 CGContextSetRGBFillColor (context, 1.0f, 1.0f, 1.0f, 1.0f);
878 CGContextSetBlendMode (context, kCGBlendModeDifference);
879 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
880 mac_end_cg_clip (f);
882 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
883 else /* CGContextSetBlendMode == NULL */
884 #endif
885 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
886 #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)
888 Rect r;
890 mac_begin_clip (f, NULL);
891 SetRect (&r, x, y, x + width, y + height);
892 InvertRect (&r);
893 mac_end_clip (f, NULL);
895 #endif
899 #if USE_ATSUI
900 static OSStatus
901 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
902 ConstUniCharArrayPtr text;
903 UniCharCount text_length;
904 ATSUStyle style;
905 ATSUTextLayout *text_layout;
907 OSStatus err;
908 static ATSUTextLayout saved_text_layout = NULL;
910 if (saved_text_layout == NULL)
912 static const UniCharCount lengths[] = {kATSUToTextEnd};
913 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
914 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
915 static ATSLineLayoutOptions line_layout =
916 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
917 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
918 | kATSLineUseQDRendering
919 #else
920 kATSLineIsDisplayOnly | kATSLineFractDisable
921 #endif
923 static const ATSUAttributeValuePtr values[] = {&line_layout};
925 err = ATSUCreateTextLayoutWithTextPtr (text,
926 kATSUFromTextBeginning,
927 kATSUToTextEnd,
928 text_length,
929 1, lengths, &style,
930 &saved_text_layout);
931 if (err == noErr)
932 err = ATSUSetLayoutControls (saved_text_layout,
933 sizeof (tags) / sizeof (tags[0]),
934 tags, sizes, values);
935 if (err == noErr)
936 err = ATSUSetTransientFontMatching (saved_text_layout, true);
938 else
940 err = ATSUSetRunStyle (saved_text_layout, style,
941 kATSUFromTextBeginning, kATSUToTextEnd);
942 if (err == noErr)
943 err = ATSUSetTextPointerLocation (saved_text_layout, text,
944 kATSUFromTextBeginning,
945 kATSUToTextEnd,
946 text_length);
949 if (err == noErr)
950 *text_layout = saved_text_layout;
951 return err;
955 static void
956 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
957 overstrike_p, bytes_per_char)
958 struct frame *f;
959 GC gc;
960 int x, y;
961 char *buf;
962 int nchars, bg_width, overstrike_p, bytes_per_char;
964 OSStatus err;
965 ATSUTextLayout text_layout;
967 xassert (bytes_per_char == 2);
969 #ifndef WORDS_BIG_ENDIAN
971 int i;
972 UniChar *text = (UniChar *)buf;
974 for (i = 0; i < nchars; i++)
975 text[i] = EndianU16_BtoN (text[i]);
977 #endif
978 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
979 nchars,
980 GC_FONT (gc)->mac_style,
981 &text_layout);
982 if (err != noErr)
983 return;
984 #ifdef MAC_OSX
985 if (!mac_use_core_graphics)
987 #endif
988 mac_begin_clip (f, gc);
989 RGBForeColor (GC_FORE_COLOR (gc));
990 if (bg_width)
992 Rect r;
994 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
995 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
996 RGBBackColor (GC_BACK_COLOR (gc));
997 EraseRect (&r);
998 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1000 MoveTo (x, y);
1001 ATSUDrawText (text_layout,
1002 kATSUFromTextBeginning, kATSUToTextEnd,
1003 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1004 if (overstrike_p)
1006 MoveTo (x + 1, y);
1007 ATSUDrawText (text_layout,
1008 kATSUFromTextBeginning, kATSUToTextEnd,
1009 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1011 mac_end_clip (f, gc);
1012 #ifdef MAC_OSX
1014 else
1016 static CGContextRef context;
1017 CGFloat port_height = FRAME_PIXEL_HEIGHT (f);
1018 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1019 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1020 static const ATSUAttributeValuePtr values[] = {&context};
1022 #if USE_CG_DRAWING
1023 context = mac_begin_cg_clip (f, gc);
1024 #else
1025 CGrafPtr port;
1027 GetPort (&port);
1028 QDBeginCGContext (port, &context);
1029 if (gc->n_clip_rects || bg_width)
1031 CGContextTranslateCTM (context, 0, port_height);
1032 CGContextScaleCTM (context, 1, -1);
1033 if (gc->n_clip_rects)
1034 CGContextClipToRects (context, gc->clip_rects,
1035 gc->n_clip_rects);
1036 #endif
1037 if (bg_width)
1039 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1040 CGContextFillRect (context,
1041 mac_rect_make (f,
1042 x, y - FONT_BASE (GC_FONT (gc)),
1043 bg_width,
1044 FONT_HEIGHT (GC_FONT (gc))));
1046 CGContextScaleCTM (context, 1, -1);
1047 CGContextTranslateCTM (context, 0, -port_height);
1048 #if !USE_CG_DRAWING
1050 #endif
1051 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1052 err = ATSUSetLayoutControls (text_layout,
1053 sizeof (tags) / sizeof (tags[0]),
1054 tags, sizes, values);
1055 if (err == noErr)
1057 ATSUDrawText (text_layout,
1058 kATSUFromTextBeginning, kATSUToTextEnd,
1059 Long2Fix (x), Long2Fix (port_height - y));
1060 if (overstrike_p)
1061 ATSUDrawText (text_layout,
1062 kATSUFromTextBeginning, kATSUToTextEnd,
1063 Long2Fix (x + 1), Long2Fix (port_height - y));
1065 #if USE_CG_DRAWING
1066 mac_end_cg_clip (f);
1067 context = NULL;
1068 #else
1069 CGContextSynchronize (context);
1070 QDEndCGContext (port, &context);
1071 #endif
1072 #if 0
1073 /* This doesn't work on Mac OS X 10.1. */
1074 ATSUClearLayoutControls (text_layout,
1075 sizeof (tags) / sizeof (tags[0]), tags);
1076 #else
1077 ATSUSetLayoutControls (text_layout,
1078 sizeof (tags) / sizeof (tags[0]),
1079 tags, sizes, values);
1080 #endif
1082 #endif /* MAC_OSX */
1084 #endif /* USE_ATSUI */
1087 static void
1088 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1089 overstrike_p, bytes_per_char)
1090 struct frame *f;
1091 GC gc;
1092 int x, y;
1093 char *buf;
1094 int nchars, bg_width, overstrike_p, bytes_per_char;
1096 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1097 UInt32 savedFlags;
1098 #endif
1100 mac_begin_clip (f, gc);
1101 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1102 if (mac_use_core_graphics)
1103 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1104 #endif
1105 RGBForeColor (GC_FORE_COLOR (gc));
1106 #ifdef MAC_OS8
1107 if (bg_width)
1109 RGBBackColor (GC_BACK_COLOR (gc));
1110 TextMode (srcCopy);
1112 else
1113 TextMode (srcOr);
1114 #else
1115 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1116 because:
1117 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1118 into an offscreen graphics world first. So performance gain
1119 cannot be expected.)
1120 - It lowers rendering quality.
1121 - Some fonts leave garbage on cursor movement. */
1122 if (bg_width)
1124 Rect r;
1126 RGBBackColor (GC_BACK_COLOR (gc));
1127 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1128 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1129 EraseRect (&r);
1131 TextMode (srcOr);
1132 #endif
1133 TextFont (GC_FONT (gc)->mac_fontnum);
1134 TextSize (GC_FONT (gc)->mac_fontsize);
1135 TextFace (GC_FONT (gc)->mac_fontface);
1136 MoveTo (x, y);
1137 DrawText (buf, 0, nchars * bytes_per_char);
1138 if (overstrike_p)
1140 TextMode (srcOr);
1141 MoveTo (x + 1, y);
1142 DrawText (buf, 0, nchars * bytes_per_char);
1144 if (bg_width)
1145 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1146 mac_end_clip (f, gc);
1148 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1149 if (mac_use_core_graphics)
1150 SwapQDTextFlags(savedFlags);
1151 #endif
1155 static INLINE void
1156 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1157 overstrike_p, bytes_per_char)
1158 struct frame *f;
1159 GC gc;
1160 int x, y;
1161 char *buf;
1162 int nchars, bg_width, overstrike_p, bytes_per_char;
1164 #if USE_ATSUI
1165 if (GC_FONT (gc)->mac_style)
1166 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1167 overstrike_p, bytes_per_char);
1168 else
1169 #endif /* USE_ATSUI */
1170 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1171 overstrike_p, bytes_per_char);
1175 /* Mac replacement for XDrawImageString. */
1177 static void
1178 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1179 struct frame *f;
1180 GC gc;
1181 int x, y;
1182 char *buf;
1183 int nchars, bg_width, overstrike_p;
1185 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1186 overstrike_p, 1);
1190 /* Mac replacement for XDrawImageString16. */
1192 static void
1193 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1194 struct frame *f;
1195 GC gc;
1196 int x, y;
1197 XChar2b *buf;
1198 int nchars, bg_width, overstrike_p;
1200 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1201 overstrike_p, 2);
1205 /* Mac replacement for XQueryTextExtents, but takes a character. If
1206 STYLE is NULL, measurement is done by QuickDraw Text routines for
1207 the font of the current graphics port. If CG_GLYPH is not NULL,
1208 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1210 static OSStatus
1211 mac_query_char_extents (style, c,
1212 font_ascent_return, font_descent_return,
1213 overall_return, cg_glyph)
1214 #if USE_ATSUI
1215 ATSUStyle style;
1216 #else
1217 void *style;
1218 #endif
1219 int c;
1220 int *font_ascent_return, *font_descent_return;
1221 XCharStruct *overall_return;
1222 #if USE_CG_TEXT_DRAWING
1223 CGGlyph *cg_glyph;
1224 #else
1225 void *cg_glyph;
1226 #endif
1228 OSStatus err = noErr;
1229 int width;
1230 Rect char_bounds;
1232 #if USE_ATSUI
1233 if (style)
1235 ATSUTextLayout text_layout;
1236 UniChar ch = c;
1238 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1239 if (err == noErr
1240 && (font_ascent_return || font_descent_return || overall_return))
1242 ATSTrapezoid glyph_bounds;
1244 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1245 kATSUFromTextBeginning, kATSUToTextEnd,
1246 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1247 kATSUseFractionalOrigins,
1248 #else
1249 kATSUseDeviceOrigins,
1250 #endif
1251 1, &glyph_bounds, NULL);
1252 if (err == noErr)
1254 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1255 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1257 width = Fix2Long (glyph_bounds.upperRight.x
1258 - glyph_bounds.upperLeft.x);
1259 if (font_ascent_return)
1260 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1261 if (font_descent_return)
1262 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1265 if (err == noErr && overall_return)
1267 err = ATSUMeasureTextImage (text_layout,
1268 kATSUFromTextBeginning, kATSUToTextEnd,
1269 0, 0, &char_bounds);
1270 if (err == noErr)
1271 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1272 #if USE_CG_TEXT_DRAWING
1273 if (err == noErr && cg_glyph)
1275 OSStatus err1;
1276 ATSUGlyphInfoArray glyph_info_array;
1277 ByteCount count = sizeof (ATSUGlyphInfoArray);
1279 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1280 kATSUToTextEnd, NULL, NULL, NULL);
1281 if (err1 == noErr)
1282 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1283 kATSUToTextEnd, &count,
1284 &glyph_info_array);
1285 if (err1 == noErr
1286 /* Make sure that we don't have to make layout
1287 adjustments. */
1288 && glyph_info_array.glyphs[0].deltaY == 0.0f
1289 && glyph_info_array.glyphs[0].idealX == 0.0f
1290 && glyph_info_array.glyphs[0].screenX == 0)
1292 xassert (glyph_info_array.glyphs[0].glyphID);
1293 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1295 else
1296 *cg_glyph = 0;
1298 #endif
1301 else
1302 #endif
1304 if (font_ascent_return || font_descent_return)
1306 FontInfo font_info;
1308 GetFontInfo (&font_info);
1309 if (font_ascent_return)
1310 *font_ascent_return = font_info.ascent;
1311 if (font_descent_return)
1312 *font_descent_return = font_info.descent;
1314 if (overall_return)
1316 char ch = c;
1318 width = CharWidth (ch);
1319 QDTextBounds (1, &ch, &char_bounds);
1320 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1324 return err;
1328 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1330 static int
1331 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1332 XFontStruct *font_struct;
1333 XChar2b *string;
1334 int nchars;
1335 XCharStruct *overall_return;
1337 int i;
1338 short width = 0, lbearing = 0, rbearing = 0;
1339 XCharStruct *pcm;
1341 for (i = 0; i < nchars; i++)
1343 pcm = mac_per_char_metric (font_struct, string, 0);
1344 if (pcm == NULL)
1345 width += FONT_WIDTH (font_struct);
1346 else
1348 lbearing = min (lbearing, width + pcm->lbearing);
1349 rbearing = max (rbearing, width + pcm->rbearing);
1350 width += pcm->width;
1352 string++;
1355 overall_return->lbearing = lbearing;
1356 overall_return->rbearing = rbearing;
1357 overall_return->width = width;
1359 /* What's the meaning of the return value of XTextExtents16? */
1363 #if USE_CG_TEXT_DRAWING
1364 static int cg_text_anti_aliasing_threshold = 8;
1366 static void
1367 init_cg_text_anti_aliasing_threshold ()
1369 int threshold;
1370 Boolean valid_p;
1372 threshold =
1373 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1374 kCFPreferencesCurrentApplication,
1375 &valid_p);
1376 if (valid_p)
1377 cg_text_anti_aliasing_threshold = threshold;
1380 static int
1381 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1382 struct frame *f;
1383 GC gc;
1384 int x, y;
1385 XChar2b *buf;
1386 int nchars, bg_width, overstrike_p;
1388 CGFloat port_height, gx, gy;
1389 int i;
1390 CGContextRef context;
1391 CGGlyph *glyphs;
1392 CGSize *advances;
1394 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1395 return 0;
1397 port_height = FRAME_PIXEL_HEIGHT (f);
1398 gx = x;
1399 gy = port_height - y;
1400 glyphs = (CGGlyph *)buf;
1401 advances = alloca (sizeof (CGSize) * nchars);
1402 if (advances == NULL)
1403 return 0;
1404 for (i = 0; i < nchars; i++)
1406 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1408 advances[i].width = pcm->width;
1409 advances[i].height = 0;
1410 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1411 buf++;
1414 #if USE_CG_DRAWING
1415 context = mac_begin_cg_clip (f, gc);
1416 #else
1417 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1418 if (gc->n_clip_rects || bg_width)
1420 CGContextTranslateCTM (context, 0, port_height);
1421 CGContextScaleCTM (context, 1, -1);
1422 if (gc->n_clip_rects)
1423 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1424 #endif
1425 if (bg_width)
1427 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1428 CGContextFillRect
1429 (context,
1430 mac_rect_make (f, gx, y - FONT_BASE (GC_FONT (gc)),
1431 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1433 CGContextScaleCTM (context, 1, -1);
1434 CGContextTranslateCTM (context, 0, -port_height);
1435 #if !USE_CG_DRAWING
1437 #endif
1438 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1439 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1440 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1441 CGContextSetTextMatrix (context, CGAffineTransformIdentity);
1442 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1443 CGContextSetShouldAntialias (context, false);
1444 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1445 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1446 if (CGContextShowGlyphsWithAdvances != NULL)
1447 #endif
1449 CGContextSetTextPosition (context, gx, gy);
1450 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1451 if (overstrike_p)
1453 CGContextSetTextPosition (context, gx + 1.0f, gy);
1454 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1457 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1458 else /* CGContextShowGlyphsWithAdvances == NULL */
1459 #endif
1460 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1461 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1463 for (i = 0; i < nchars; i++)
1465 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1466 if (overstrike_p)
1467 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1468 gx += advances[i].width;
1471 #endif
1472 #if USE_CG_DRAWING
1473 mac_end_cg_clip (f);
1474 #else
1475 CGContextSynchronize (context);
1476 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1477 #endif
1479 return 1;
1481 #endif
1484 #if !USE_CG_DRAWING
1485 /* Mac replacement for XCopyArea: dest must be window. */
1487 static void
1488 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1489 Pixmap src;
1490 struct frame *f;
1491 GC gc;
1492 int src_x, src_y;
1493 unsigned int width, height;
1494 int dest_x, dest_y;
1496 Rect src_r, dest_r;
1498 mac_begin_clip (f, gc);
1500 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1501 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1503 ForeColor (blackColor);
1504 BackColor (whiteColor);
1506 LockPixels (GetGWorldPixMap (src));
1507 #if TARGET_API_MAC_CARBON
1509 CGrafPtr port;
1511 GetPort (&port);
1512 LockPortBits (port);
1513 CopyBits (GetPortBitMapForCopyBits (src),
1514 GetPortBitMapForCopyBits (port),
1515 &src_r, &dest_r, srcCopy, 0);
1516 UnlockPortBits (port);
1518 #else /* not TARGET_API_MAC_CARBON */
1519 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1520 &src_r, &dest_r, srcCopy, 0);
1521 #endif /* not TARGET_API_MAC_CARBON */
1522 UnlockPixels (GetGWorldPixMap (src));
1524 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1526 mac_end_clip (f, gc);
1530 static void
1531 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1532 width, height, dest_x, dest_y)
1533 Pixmap src, mask;
1534 struct frame *f;
1535 GC gc;
1536 int src_x, src_y;
1537 unsigned int width, height;
1538 int dest_x, dest_y;
1540 Rect src_r, dest_r;
1542 mac_begin_clip (f, gc);
1544 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1545 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1547 ForeColor (blackColor);
1548 BackColor (whiteColor);
1550 LockPixels (GetGWorldPixMap (src));
1551 LockPixels (GetGWorldPixMap (mask));
1552 #if TARGET_API_MAC_CARBON
1554 CGrafPtr port;
1556 GetPort (&port);
1557 LockPortBits (port);
1558 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1559 GetPortBitMapForCopyBits (port),
1560 &src_r, &src_r, &dest_r);
1561 UnlockPortBits (port);
1563 #else /* not TARGET_API_MAC_CARBON */
1564 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1565 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1566 #endif /* not TARGET_API_MAC_CARBON */
1567 UnlockPixels (GetGWorldPixMap (mask));
1568 UnlockPixels (GetGWorldPixMap (src));
1570 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1572 mac_end_clip (f, gc);
1574 #endif /* !USE_CG_DRAWING */
1577 /* Mac replacement for XCopyArea: used only for scrolling. */
1579 #if TARGET_API_MAC_CARBON
1580 /* Defined in mactoolbox.c. */
1581 extern void mac_scroll_area P_ ((struct frame *, GC, int, int,
1582 unsigned int, unsigned int, int, int));
1583 #else /* not TARGET_API_MAC_CARBON */
1584 static void
1585 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1586 struct frame *f;
1587 GC gc;
1588 int src_x, src_y;
1589 unsigned int width, height;
1590 int dest_x, dest_y;
1592 Rect src_r, dest_r;
1593 WindowRef w = FRAME_MAC_WINDOW (f);
1595 mac_begin_clip (f, gc);
1597 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1598 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1600 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1601 color mapping in CopyBits. Otherwise, it will be slow. */
1602 ForeColor (blackColor);
1603 BackColor (whiteColor);
1604 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1606 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1608 mac_end_clip (f, gc);
1610 #endif /* not TARGET_API_MAC_CARBON */
1613 /* Mac replacement for XChangeGC. */
1615 static void
1616 XChangeGC (display, gc, mask, xgcv)
1617 Display *display;
1618 GC gc;
1619 unsigned long mask;
1620 XGCValues *xgcv;
1622 if (mask & GCForeground)
1623 XSetForeground (display, gc, xgcv->foreground);
1624 if (mask & GCBackground)
1625 XSetBackground (display, gc, xgcv->background);
1626 if (mask & GCFont)
1627 XSetFont (display, gc, xgcv->font);
1631 /* Mac replacement for XCreateGC. */
1634 XCreateGC (display, d, mask, xgcv)
1635 Display *display;
1636 void *d;
1637 unsigned long mask;
1638 XGCValues *xgcv;
1640 GC gc = xmalloc (sizeof (*gc));
1642 bzero (gc, sizeof (*gc));
1643 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1644 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1645 if (CGColorGetTypeID != NULL)
1646 #endif
1648 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1649 CGColorRetain (gc->cg_fore_color);
1650 CGColorRetain (gc->cg_back_color);
1652 #endif
1653 XChangeGC (display, gc, mask, xgcv);
1655 return gc;
1659 /* Used in xfaces.c. */
1661 void
1662 XFreeGC (display, gc)
1663 Display *display;
1664 GC gc;
1666 if (gc->clip_region)
1667 DisposeRgn (gc->clip_region);
1668 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1669 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1670 if (CGColorGetTypeID != NULL)
1671 #endif
1673 CGColorRelease (gc->cg_fore_color);
1674 CGColorRelease (gc->cg_back_color);
1676 #endif
1677 xfree (gc);
1681 /* Mac replacement for XGetGCValues. */
1683 static void
1684 XGetGCValues (display, gc, mask, xgcv)
1685 Display *display;
1686 GC gc;
1687 unsigned long mask;
1688 XGCValues *xgcv;
1690 if (mask & GCForeground)
1691 xgcv->foreground = gc->xgcv.foreground;
1692 if (mask & GCBackground)
1693 xgcv->background = gc->xgcv.background;
1694 if (mask & GCFont)
1695 xgcv->font = gc->xgcv.font;
1699 /* Mac replacement for XSetForeground. */
1701 void
1702 XSetForeground (display, gc, color)
1703 Display *display;
1704 GC gc;
1705 unsigned long color;
1707 if (gc->xgcv.foreground != color)
1709 gc->xgcv.foreground = color;
1710 gc->fore_color.red = RED16_FROM_ULONG (color);
1711 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1712 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1713 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1714 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1715 if (CGColorGetTypeID != NULL)
1716 #endif
1718 CGColorRelease (gc->cg_fore_color);
1719 if (color == 0)
1721 gc->cg_fore_color = mac_cg_color_black;
1722 CGColorRetain (gc->cg_fore_color);
1724 else
1726 CGFloat rgba[4];
1728 rgba[0] = gc->fore_color.red / 65535.0f;
1729 rgba[1] = gc->fore_color.green / 65535.0f;
1730 rgba[2] = gc->fore_color.blue / 65535.0f;
1731 rgba[3] = 1.0f;
1732 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1735 #endif
1740 /* Mac replacement for XSetBackground. */
1742 void
1743 XSetBackground (display, gc, color)
1744 Display *display;
1745 GC gc;
1746 unsigned long color;
1748 if (gc->xgcv.background != color)
1750 gc->xgcv.background = color;
1751 gc->back_color.red = RED16_FROM_ULONG (color);
1752 gc->back_color.green = GREEN16_FROM_ULONG (color);
1753 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1754 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1755 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1756 if (CGColorGetTypeID != NULL)
1757 #endif
1759 CGColorRelease (gc->cg_back_color);
1760 if (color == 0)
1762 gc->cg_back_color = mac_cg_color_black;
1763 CGColorRetain (gc->cg_back_color);
1765 else
1767 CGFloat rgba[4];
1769 rgba[0] = gc->back_color.red / 65535.0f;
1770 rgba[1] = gc->back_color.green / 65535.0f;
1771 rgba[2] = gc->back_color.blue / 65535.0f;
1772 rgba[3] = 1.0f;
1773 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1776 #endif
1781 /* Mac replacement for XSetFont. */
1783 static void
1784 XSetFont (display, gc, font)
1785 Display *display;
1786 GC gc;
1787 XFontStruct *font;
1789 gc->xgcv.font = font;
1793 /* Mac replacement for XSetClipRectangles. */
1795 static void
1796 mac_set_clip_rectangles (f, gc, rectangles, n)
1797 struct frame *f;
1798 GC gc;
1799 Rect *rectangles;
1800 int n;
1802 int i;
1804 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1806 gc->n_clip_rects = n;
1807 if (n > 0)
1809 if (gc->clip_region == NULL)
1810 gc->clip_region = NewRgn ();
1811 RectRgn (gc->clip_region, rectangles);
1812 if (n > 1)
1814 RgnHandle region = NewRgn ();
1816 for (i = 1; i < n; i++)
1818 RectRgn (region, rectangles + i);
1819 UnionRgn (gc->clip_region, region, gc->clip_region);
1821 DisposeRgn (region);
1824 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1825 for (i = 0; i < n; i++)
1827 Rect *rect = rectangles + i;
1829 gc->clip_rects[i] = mac_rect_make (f, rect->left, rect->top,
1830 rect->right - rect->left,
1831 rect->bottom - rect->top);
1833 #endif
1837 /* Mac replacement for XSetClipMask. */
1839 static INLINE void
1840 mac_reset_clip_rectangles (f, gc)
1841 struct frame *f;
1842 GC gc;
1844 gc->n_clip_rects = 0;
1847 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1848 Calls to XFlush should be unnecessary because the X output buffer
1849 is flushed automatically as needed by calls to XPending,
1850 XNextEvent, or XWindowEvent according to the XFlush man page.
1851 XTread_socket calls XPending. Removing XFlush improves
1852 performance. */
1854 #define XFlush(DISPLAY) (void) 0
1857 /***********************************************************************
1858 Starting and ending an update
1859 ***********************************************************************/
1861 /* Start an update of frame F. This function is installed as a hook
1862 for update_begin, i.e. it is called when update_begin is called.
1863 This function is called prior to calls to x_update_window_begin for
1864 each window being updated. */
1866 static void
1867 x_update_begin (f)
1868 struct frame *f;
1870 BLOCK_INPUT;
1871 mac_update_begin (f);
1872 UNBLOCK_INPUT;
1876 /* Start update of window W. Set the global variable updated_window
1877 to the window being updated and set output_cursor to the cursor
1878 position of W. */
1880 static void
1881 x_update_window_begin (w)
1882 struct window *w;
1884 struct frame *f = XFRAME (WINDOW_FRAME (w));
1885 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1887 updated_window = w;
1888 set_output_cursor (&w->cursor);
1890 BLOCK_INPUT;
1892 if (f == display_info->mouse_face_mouse_frame)
1894 /* Don't do highlighting for mouse motion during the update. */
1895 display_info->mouse_face_defer = 1;
1897 /* If F needs to be redrawn, simply forget about any prior mouse
1898 highlighting. */
1899 if (FRAME_GARBAGED_P (f))
1900 display_info->mouse_face_window = Qnil;
1902 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1903 their mouse_face_p flag set, which means that they are always
1904 unequal to rows in a desired matrix which never have that
1905 flag set. So, rows containing mouse-face glyphs are never
1906 scrolled, and we don't have to switch the mouse highlight off
1907 here to prevent it from being scrolled. */
1909 /* Can we tell that this update does not affect the window
1910 where the mouse highlight is? If so, no need to turn off.
1911 Likewise, don't do anything if the frame is garbaged;
1912 in that case, the frame's current matrix that we would use
1913 is all wrong, and we will redisplay that line anyway. */
1914 if (!NILP (display_info->mouse_face_window)
1915 && w == XWINDOW (display_info->mouse_face_window))
1917 int i;
1919 for (i = 0; i < w->desired_matrix->nrows; ++i)
1920 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1921 break;
1923 if (i < w->desired_matrix->nrows)
1924 clear_mouse_face (display_info);
1926 #endif /* 0 */
1929 UNBLOCK_INPUT;
1933 /* Draw a vertical window border from (x,y0) to (x,y1) */
1935 static void
1936 mac_draw_vertical_window_border (w, x, y0, y1)
1937 struct window *w;
1938 int x, y0, y1;
1940 struct frame *f = XFRAME (WINDOW_FRAME (w));
1941 struct face *face;
1943 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1944 if (face)
1945 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1946 face->foreground);
1948 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1951 /* End update of window W (which is equal to updated_window).
1953 Draw vertical borders between horizontally adjacent windows, and
1954 display W's cursor if CURSOR_ON_P is non-zero.
1956 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1957 glyphs in mouse-face were overwritten. In that case we have to
1958 make sure that the mouse-highlight is properly redrawn.
1960 W may be a menu bar pseudo-window in case we don't have X toolkit
1961 support. Such windows don't have a cursor, so don't display it
1962 here. */
1964 static void
1965 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1966 struct window *w;
1967 int cursor_on_p, mouse_face_overwritten_p;
1969 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1971 if (!w->pseudo_window_p)
1973 BLOCK_INPUT;
1975 if (cursor_on_p)
1976 display_and_set_cursor (w, 1, output_cursor.hpos,
1977 output_cursor.vpos,
1978 output_cursor.x, output_cursor.y);
1980 if (draw_window_fringes (w, 1))
1981 x_draw_vertical_border (w);
1983 UNBLOCK_INPUT;
1986 /* If a row with mouse-face was overwritten, arrange for
1987 XTframe_up_to_date to redisplay the mouse highlight. */
1988 if (mouse_face_overwritten_p)
1990 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1991 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1992 dpyinfo->mouse_face_window = Qnil;
1995 updated_window = NULL;
1999 /* End update of frame F. This function is installed as a hook in
2000 update_end. */
2002 static void
2003 x_update_end (f)
2004 struct frame *f;
2006 /* Mouse highlight may be displayed again. */
2007 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
2009 BLOCK_INPUT;
2010 mac_update_end (f);
2011 XFlush (FRAME_MAC_DISPLAY (f));
2012 UNBLOCK_INPUT;
2016 /* This function is called from various places in xdisp.c whenever a
2017 complete update has been performed. The global variable
2018 updated_window is not available here. */
2020 static void
2021 XTframe_up_to_date (f)
2022 struct frame *f;
2024 if (FRAME_MAC_P (f))
2026 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2028 if (dpyinfo->mouse_face_deferred_gc
2029 || f == dpyinfo->mouse_face_mouse_frame)
2031 BLOCK_INPUT;
2032 if (dpyinfo->mouse_face_mouse_frame)
2033 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2034 dpyinfo->mouse_face_mouse_x,
2035 dpyinfo->mouse_face_mouse_y);
2036 dpyinfo->mouse_face_deferred_gc = 0;
2037 UNBLOCK_INPUT;
2040 mac_frame_up_to_date (f);
2045 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2046 arrow bitmaps, or clear the fringes if no bitmaps are required
2047 before DESIRED_ROW is made current. The window being updated is
2048 found in updated_window. This function is called from
2049 update_window_line only if it is known that there are differences
2050 between bitmaps to be drawn between current row and DESIRED_ROW. */
2052 static void
2053 x_after_update_window_line (desired_row)
2054 struct glyph_row *desired_row;
2056 struct window *w = updated_window;
2057 struct frame *f;
2058 int width, height;
2060 xassert (w);
2062 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2063 desired_row->redraw_fringe_bitmaps_p = 1;
2065 /* When a window has disappeared, make sure that no rest of
2066 full-width rows stays visible in the internal border. Could
2067 check here if updated_window is the leftmost/rightmost window,
2068 but I guess it's not worth doing since vertically split windows
2069 are almost never used, internal border is rarely set, and the
2070 overhead is very small. */
2071 if (windows_or_buffers_changed
2072 && desired_row->full_width_p
2073 && (f = XFRAME (w->frame),
2074 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2075 width != 0)
2076 && (height = desired_row->visible_height,
2077 height > 0))
2079 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2081 /* Internal border is drawn below the tool bar. */
2082 if (WINDOWP (f->tool_bar_window)
2083 && w == XWINDOW (f->tool_bar_window))
2084 y -= width;
2086 BLOCK_INPUT;
2087 mac_clear_area (f, 0, y, width, height);
2088 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2089 UNBLOCK_INPUT;
2094 /* Draw the bitmap WHICH in one of the left or right fringes of
2095 window W. ROW is the glyph row for which to display the bitmap; it
2096 determines the vertical position at which the bitmap has to be
2097 drawn. */
2099 static void
2100 x_draw_fringe_bitmap (w, row, p)
2101 struct window *w;
2102 struct glyph_row *row;
2103 struct draw_fringe_bitmap_params *p;
2105 struct frame *f = XFRAME (WINDOW_FRAME (w));
2106 Display *display = FRAME_MAC_DISPLAY (f);
2107 struct face *face = p->face;
2108 int rowY;
2109 int overlay_p = p->overlay_p;
2111 #ifdef MAC_OSX
2112 if (!overlay_p)
2114 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2116 #if 0 /* MAC_TODO: stipple */
2117 /* In case the same realized face is used for fringes and
2118 for something displayed in the text (e.g. face `region' on
2119 mono-displays, the fill style may have been changed to
2120 FillSolid in x_draw_glyph_string_background. */
2121 if (face->stipple)
2122 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2123 else
2124 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2125 #endif
2127 /* If the fringe is adjacent to the left (right) scroll bar of a
2128 leftmost (rightmost, respectively) window, then extend its
2129 background to the gap between the fringe and the bar. */
2130 if ((WINDOW_LEFTMOST_P (w)
2131 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2132 || (WINDOW_RIGHTMOST_P (w)
2133 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2135 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2137 if (sb_width > 0)
2139 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2140 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2141 * FRAME_COLUMN_WIDTH (f));
2143 if (bx < 0
2144 && (left + width == p->x
2145 || p->x + p->wd == left))
2147 /* Bitmap fills the fringe and we need background
2148 extension. */
2149 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2151 bx = p->x;
2152 nx = p->wd;
2153 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2154 row->y));
2155 ny = row->visible_height;
2158 if (bx >= 0)
2160 if (left + width == bx)
2162 bx = left + sb_width;
2163 nx += width - sb_width;
2165 else if (bx + nx == left)
2166 nx += width - sb_width;
2171 if (bx >= 0)
2173 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2174 /* The fringe background has already been filled. */
2175 overlay_p = 1;
2178 #if 0 /* MAC_TODO: stipple */
2179 if (!face->stipple)
2180 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2181 #endif
2183 #endif /* MAC_OSX */
2185 /* Must clip because of partially visible lines. */
2186 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2187 if (p->y < rowY)
2189 /* Adjust position of "bottom aligned" bitmap on partially
2190 visible last row. */
2191 int oldY = row->y;
2192 int oldVH = row->visible_height;
2193 row->visible_height = p->h;
2194 row->y -= rowY - p->y;
2195 x_clip_to_row (w, row, -1, face->gc);
2196 row->y = oldY;
2197 row->visible_height = oldVH;
2199 else
2200 x_clip_to_row (w, row, -1, face->gc);
2202 #ifndef MAC_OSX
2203 if (p->bx >= 0 && !p->overlay_p)
2205 #if 0 /* MAC_TODO: stipple */
2206 /* In case the same realized face is used for fringes and
2207 for something displayed in the text (e.g. face `region' on
2208 mono-displays, the fill style may have been changed to
2209 FillSolid in x_draw_glyph_string_background. */
2210 if (face->stipple)
2211 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2212 else
2213 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2214 #endif
2216 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2218 #if 0 /* MAC_TODO: stipple */
2219 if (!face->stipple)
2220 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2221 #endif
2223 #endif /* !MAC_OSX */
2225 if (p->which
2226 #if USE_CG_DRAWING
2227 && p->which < max_fringe_bmp
2228 #endif
2231 XGCValues gcv;
2233 XGetGCValues (display, face->gc, GCForeground, &gcv);
2234 XSetForeground (display, face->gc,
2235 (p->cursor_p
2236 ? (p->overlay_p ? face->background
2237 : f->output_data.mac->cursor_pixel)
2238 : face->foreground));
2239 #if USE_CG_DRAWING
2240 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2241 p->wd, p->h, p->x, p->y, overlay_p);
2242 #else
2243 mac_draw_bitmap (f, face->gc, p->x, p->y,
2244 p->wd, p->h, p->bits + p->dh, overlay_p);
2245 #endif
2246 XSetForeground (display, face->gc, gcv.foreground);
2249 mac_reset_clip_rectangles (f, face->gc);
2252 #if USE_CG_DRAWING
2253 static void
2254 mac_define_fringe_bitmap (which, bits, h, wd)
2255 int which;
2256 unsigned short *bits;
2257 int h, wd;
2259 int i;
2260 CGDataProviderRef provider;
2262 if (which >= max_fringe_bmp)
2264 i = max_fringe_bmp;
2265 max_fringe_bmp = which + 20;
2266 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2267 while (i < max_fringe_bmp)
2268 fringe_bmp[i++] = 0;
2271 for (i = 0; i < h; i++)
2272 bits[i] = ~bits[i];
2274 BLOCK_INPUT;
2276 provider = CGDataProviderCreateWithData (NULL, bits,
2277 sizeof (unsigned short) * h, NULL);
2278 if (provider)
2280 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2281 sizeof (unsigned short),
2282 provider, NULL, 0);
2283 CGDataProviderRelease (provider);
2286 UNBLOCK_INPUT;
2289 static void
2290 mac_destroy_fringe_bitmap (which)
2291 int which;
2293 if (which >= max_fringe_bmp)
2294 return;
2296 if (fringe_bmp[which])
2298 BLOCK_INPUT;
2299 CGImageRelease (fringe_bmp[which]);
2300 UNBLOCK_INPUT;
2302 fringe_bmp[which] = 0;
2304 #endif
2307 /* This is called when starting Emacs and when restarting after
2308 suspend. When starting Emacs, no window is mapped. And nothing
2309 must be done to Emacs's own window if it is suspended (though that
2310 rarely happens). */
2312 static void
2313 XTset_terminal_modes ()
2317 /* This is called when exiting or suspending Emacs. Exiting will make
2318 the windows go away, and suspending requires no action. */
2320 static void
2321 XTreset_terminal_modes ()
2327 /***********************************************************************
2328 Display Iterator
2329 ***********************************************************************/
2331 /* Function prototypes of this page. */
2333 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2334 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2337 static void
2338 pcm_init (pcm, count)
2339 XCharStruct *pcm;
2340 int count;
2342 bzero (pcm, sizeof (XCharStruct) * count);
2343 while (--count >= 0)
2345 pcm->descent = PCM_INVALID;
2346 pcm++;
2350 static enum pcm_status
2351 pcm_get_status (pcm)
2352 const XCharStruct *pcm;
2354 int height = pcm->ascent + pcm->descent;
2356 /* Negative height means some special status. */
2357 return height >= 0 ? PCM_VALID : height;
2360 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2361 is not contained in the font. */
2363 static INLINE XCharStruct *
2364 x_per_char_metric (font, char2b)
2365 XFontStruct *font;
2366 XChar2b *char2b;
2368 /* The result metric information. */
2369 XCharStruct *pcm = NULL;
2371 xassert (font && char2b);
2373 #if USE_ATSUI
2374 if (font->mac_style)
2376 XCharStruct **row = font->bounds.rows + char2b->byte1;
2378 if (*row == NULL)
2380 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2381 pcm_init (*row, 0x100);
2383 pcm = *row + char2b->byte2;
2384 if (pcm_get_status (pcm) != PCM_VALID)
2386 BLOCK_INPUT;
2387 mac_query_char_extents (font->mac_style,
2388 (char2b->byte1 << 8) + char2b->byte2,
2389 NULL, NULL, pcm, NULL);
2390 UNBLOCK_INPUT;
2393 else
2395 #endif
2396 if (font->bounds.per_char != NULL)
2398 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2400 /* min_char_or_byte2 specifies the linear character index
2401 corresponding to the first element of the per_char array,
2402 max_char_or_byte2 is the index of the last character. A
2403 character with non-zero CHAR2B->byte1 is not in the font.
2404 A character with byte2 less than min_char_or_byte2 or
2405 greater max_char_or_byte2 is not in the font. */
2406 if (char2b->byte1 == 0
2407 && char2b->byte2 >= font->min_char_or_byte2
2408 && char2b->byte2 <= font->max_char_or_byte2)
2409 pcm = font->bounds.per_char
2410 + (char2b->byte2 - font->min_char_or_byte2);
2412 else
2414 /* If either min_byte1 or max_byte1 are nonzero, both
2415 min_char_or_byte2 and max_char_or_byte2 are less than
2416 256, and the 2-byte character index values corresponding
2417 to the per_char array element N (counting from 0) are:
2419 byte1 = N/D + min_byte1
2420 byte2 = N\D + min_char_or_byte2
2422 where:
2424 D = max_char_or_byte2 - min_char_or_byte2 + 1
2425 / = integer division
2426 \ = integer modulus */
2427 if (char2b->byte1 >= font->min_byte1
2428 && char2b->byte1 <= font->max_byte1
2429 && char2b->byte2 >= font->min_char_or_byte2
2430 && char2b->byte2 <= font->max_char_or_byte2)
2432 pcm = (font->bounds.per_char
2433 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2434 * (char2b->byte1 - font->min_byte1))
2435 + (char2b->byte2 - font->min_char_or_byte2));
2439 else
2441 /* If the per_char pointer is null, all glyphs between the first
2442 and last character indexes inclusive have the same
2443 information, as given by both min_bounds and max_bounds. */
2444 if (char2b->byte2 >= font->min_char_or_byte2
2445 && char2b->byte2 <= font->max_char_or_byte2)
2446 pcm = &font->max_bounds;
2448 #if USE_ATSUI
2450 #endif
2452 return ((pcm == NULL
2453 || (pcm->width == 0
2454 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2455 && (pcm->rbearing - pcm->lbearing) == 0
2456 #endif
2458 ? NULL : pcm);
2461 /* RIF:
2464 static XCharStruct *
2465 mac_per_char_metric (font, char2b, font_type)
2466 XFontStruct *font;
2467 XChar2b *char2b;
2468 int font_type;
2470 return x_per_char_metric (font, char2b);
2473 /* RIF:
2474 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2475 the two-byte form of C. Encoding is returned in *CHAR2B. */
2477 static int
2478 mac_encode_char (c, char2b, font_info, two_byte_p)
2479 int c;
2480 XChar2b *char2b;
2481 struct font_info *font_info;
2482 int *two_byte_p;
2484 int charset = CHAR_CHARSET (c);
2485 XFontStruct *font = font_info->font;
2487 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2488 This may be either a program in a special encoder language or a
2489 fixed encoding. */
2490 if (font_info->font_encoder)
2492 /* It's a program. */
2493 struct ccl_program *ccl = font_info->font_encoder;
2495 check_ccl_update (ccl);
2496 if (CHARSET_DIMENSION (charset) == 1)
2498 ccl->reg[0] = charset;
2499 ccl->reg[1] = char2b->byte2;
2500 ccl->reg[2] = -1;
2502 else
2504 ccl->reg[0] = charset;
2505 ccl->reg[1] = char2b->byte1;
2506 ccl->reg[2] = char2b->byte2;
2509 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2511 /* We assume that MSBs are appropriately set/reset by CCL
2512 program. */
2513 if (font->max_byte1 == 0) /* 1-byte font */
2514 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2515 else
2516 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2518 else if (font_info->encoding[charset])
2520 /* Fixed encoding scheme. See fontset.h for the meaning of the
2521 encoding numbers. */
2522 int enc = font_info->encoding[charset];
2524 if ((enc == 1 || enc == 2)
2525 && CHARSET_DIMENSION (charset) == 2)
2526 char2b->byte1 |= 0x80;
2528 if (enc == 1 || enc == 3)
2529 char2b->byte2 |= 0x80;
2531 if (enc == 4)
2533 int sjis1, sjis2;
2535 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2536 char2b->byte1 = sjis1;
2537 char2b->byte2 = sjis2;
2541 if (two_byte_p)
2542 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2544 return FONT_TYPE_UNKNOWN;
2549 /***********************************************************************
2550 Glyph display
2551 ***********************************************************************/
2555 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2556 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2557 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2558 int));
2559 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2560 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2561 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2562 static void x_draw_glyph_string P_ ((struct glyph_string *));
2563 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2564 static void x_set_cursor_gc P_ ((struct glyph_string *));
2565 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2566 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2567 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2568 unsigned long *, double, int));*/
2569 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2570 double, int, unsigned long));
2571 static void x_setup_relief_colors P_ ((struct glyph_string *));
2572 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2573 static void x_draw_image_relief P_ ((struct glyph_string *));
2574 static void x_draw_image_foreground P_ ((struct glyph_string *));
2575 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2576 int, int, int));
2577 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2578 int, int, int, int, int, int,
2579 Rect *));
2580 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2581 int, int, int, Rect *));
2583 #if GLYPH_DEBUG
2584 static void x_check_font P_ ((struct frame *, XFontStruct *));
2585 #endif
2588 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2589 face. */
2591 static void
2592 x_set_cursor_gc (s)
2593 struct glyph_string *s;
2595 if (s->font == FRAME_FONT (s->f)
2596 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2597 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2598 && !s->cmp)
2599 s->gc = s->f->output_data.mac->cursor_gc;
2600 else
2602 /* Cursor on non-default face: must merge. */
2603 XGCValues xgcv;
2604 unsigned long mask;
2606 xgcv.background = s->f->output_data.mac->cursor_pixel;
2607 xgcv.foreground = s->face->background;
2609 /* If the glyph would be invisible, try a different foreground. */
2610 if (xgcv.foreground == xgcv.background)
2611 xgcv.foreground = s->face->foreground;
2612 if (xgcv.foreground == xgcv.background)
2613 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2614 if (xgcv.foreground == xgcv.background)
2615 xgcv.foreground = s->face->foreground;
2617 /* Make sure the cursor is distinct from text in this face. */
2618 if (xgcv.background == s->face->background
2619 && xgcv.foreground == s->face->foreground)
2621 xgcv.background = s->face->foreground;
2622 xgcv.foreground = s->face->background;
2625 IF_DEBUG (x_check_font (s->f, s->font));
2626 xgcv.font = s->font;
2627 mask = GCForeground | GCBackground | GCFont;
2629 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2630 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2631 mask, &xgcv);
2632 else
2633 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2634 = XCreateGC (s->display, s->window, mask, &xgcv);
2636 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2641 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2643 static void
2644 x_set_mouse_face_gc (s)
2645 struct glyph_string *s;
2647 int face_id;
2648 struct face *face;
2650 /* What face has to be used last for the mouse face? */
2651 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2652 face = FACE_FROM_ID (s->f, face_id);
2653 if (face == NULL)
2654 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2656 if (s->first_glyph->type == CHAR_GLYPH)
2657 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2658 else
2659 face_id = FACE_FOR_CHAR (s->f, face, 0);
2660 s->face = FACE_FROM_ID (s->f, face_id);
2661 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2663 /* If font in this face is same as S->font, use it. */
2664 if (s->font == s->face->font)
2665 s->gc = s->face->gc;
2666 else
2668 /* Otherwise construct scratch_cursor_gc with values from FACE
2669 but font FONT. */
2670 XGCValues xgcv;
2671 unsigned long mask;
2673 xgcv.background = s->face->background;
2674 xgcv.foreground = s->face->foreground;
2675 IF_DEBUG (x_check_font (s->f, s->font));
2676 xgcv.font = s->font;
2677 mask = GCForeground | GCBackground | GCFont;
2679 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2680 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2681 mask, &xgcv);
2682 else
2683 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2684 = XCreateGC (s->display, s->window, mask, &xgcv);
2686 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2689 xassert (s->gc != 0);
2693 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2694 Faces to use in the mode line have already been computed when the
2695 matrix was built, so there isn't much to do, here. */
2697 static INLINE void
2698 x_set_mode_line_face_gc (s)
2699 struct glyph_string *s;
2701 s->gc = s->face->gc;
2705 /* Set S->gc of glyph string S for drawing that glyph string. Set
2706 S->stippled_p to a non-zero value if the face of S has a stipple
2707 pattern. */
2709 static INLINE void
2710 x_set_glyph_string_gc (s)
2711 struct glyph_string *s;
2713 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2715 if (s->hl == DRAW_NORMAL_TEXT)
2717 s->gc = s->face->gc;
2718 s->stippled_p = s->face->stipple != 0;
2720 else if (s->hl == DRAW_INVERSE_VIDEO)
2722 x_set_mode_line_face_gc (s);
2723 s->stippled_p = s->face->stipple != 0;
2725 else if (s->hl == DRAW_CURSOR)
2727 x_set_cursor_gc (s);
2728 s->stippled_p = 0;
2730 else if (s->hl == DRAW_MOUSE_FACE)
2732 x_set_mouse_face_gc (s);
2733 s->stippled_p = s->face->stipple != 0;
2735 else if (s->hl == DRAW_IMAGE_RAISED
2736 || s->hl == DRAW_IMAGE_SUNKEN)
2738 s->gc = s->face->gc;
2739 s->stippled_p = s->face->stipple != 0;
2741 else
2743 s->gc = s->face->gc;
2744 s->stippled_p = s->face->stipple != 0;
2747 /* GC must have been set. */
2748 xassert (s->gc != 0);
2752 /* Set clipping for output of glyph string S. S may be part of a mode
2753 line or menu if we don't have X toolkit support. */
2755 static INLINE void
2756 x_set_glyph_string_clipping (s)
2757 struct glyph_string *s;
2759 Rect rects[MAX_CLIP_RECTS];
2760 int n;
2762 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2763 mac_set_clip_rectangles (s->f, s->gc, rects, n);
2767 /* RIF:
2768 Compute left and right overhang of glyph string S. If S is a glyph
2769 string for a composition, assume overhangs don't exist. */
2771 static void
2772 mac_compute_glyph_string_overhangs (s)
2773 struct glyph_string *s;
2775 if (!(s->cmp == NULL
2776 && s->first_glyph->type == CHAR_GLYPH))
2777 return;
2779 if (!s->two_byte_p
2780 #if USE_ATSUI
2781 || s->font->mac_style
2782 #endif
2785 XCharStruct cs;
2787 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2788 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2789 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2791 else
2793 Rect r;
2794 MacFontStruct *font = s->font;
2796 mac_begin_clip (s->f, NULL);
2798 TextFont (font->mac_fontnum);
2799 TextSize (font->mac_fontsize);
2800 TextFace (font->mac_fontface);
2802 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2804 mac_end_clip (s->f, NULL);
2806 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2807 s->left_overhang = r.left < 0 ? -r.left : 0;
2812 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2814 static INLINE void
2815 x_clear_glyph_string_rect (s, x, y, w, h)
2816 struct glyph_string *s;
2817 int x, y, w, h;
2819 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2823 /* Draw the background of glyph_string S. If S->background_filled_p
2824 is non-zero don't draw it. FORCE_P non-zero means draw the
2825 background even if it wouldn't be drawn normally. This is used
2826 when a string preceding S draws into the background of S, or S
2827 contains the first component of a composition. */
2829 static void
2830 x_draw_glyph_string_background (s, force_p)
2831 struct glyph_string *s;
2832 int force_p;
2834 /* Nothing to do if background has already been drawn or if it
2835 shouldn't be drawn in the first place. */
2836 if (!s->background_filled_p)
2838 int box_line_width = max (s->face->box_line_width, 0);
2840 #if 0 /* MAC_TODO: stipple */
2841 if (s->stippled_p)
2843 /* Fill background with a stipple pattern. */
2844 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2845 XFillRectangle (s->display, s->window, s->gc, s->x,
2846 s->y + box_line_width,
2847 s->background_width,
2848 s->height - 2 * box_line_width);
2849 XSetFillStyle (s->display, s->gc, FillSolid);
2850 s->background_filled_p = 1;
2852 else
2853 #endif
2854 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2855 || s->font_not_found_p
2856 || s->extends_to_end_of_line_p
2857 || force_p)
2859 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2860 s->background_width,
2861 s->height - 2 * box_line_width);
2862 s->background_filled_p = 1;
2868 /* Draw the foreground of glyph string S. */
2870 static void
2871 x_draw_glyph_string_foreground (s)
2872 struct glyph_string *s;
2874 int i, x, bg_width;
2876 /* If first glyph of S has a left box line, start drawing the text
2877 of S to the right of that box line. */
2878 if (s->face->box != FACE_NO_BOX
2879 && s->first_glyph->left_box_line_p)
2880 x = s->x + abs (s->face->box_line_width);
2881 else
2882 x = s->x;
2884 /* Draw characters of S as rectangles if S's font could not be
2885 loaded. */
2886 if (s->font_not_found_p)
2888 for (i = 0; i < s->nchars; ++i)
2890 struct glyph *g = s->first_glyph + i;
2891 mac_draw_rectangle (s->f, s->gc, x, s->y,
2892 g->pixel_width - 1, s->height - 1);
2893 x += g->pixel_width;
2896 else
2898 char *char1b = (char *) s->char2b;
2899 int boff = s->font_info->baseline_offset;
2901 if (s->font_info->vertical_centering)
2902 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2904 /* If we can use 8-bit functions, condense S->char2b. */
2905 if (!s->two_byte_p
2906 #if USE_ATSUI
2907 && GC_FONT (s->gc)->mac_style == NULL
2908 #endif
2910 for (i = 0; i < s->nchars; ++i)
2911 char1b[i] = s->char2b[i].byte2;
2913 /* Draw text with XDrawString if background has already been
2914 filled. Otherwise, use XDrawImageString. (Note that
2915 XDrawImageString is usually faster than XDrawString.) Always
2916 use XDrawImageString when drawing the cursor so that there is
2917 no chance that characters under a box cursor are invisible. */
2918 if (s->for_overlaps
2919 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2920 bg_width = 0; /* Corresponds to XDrawString. */
2921 else
2922 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2924 if (s->two_byte_p
2925 #if USE_ATSUI
2926 || GC_FONT (s->gc)->mac_style
2927 #endif
2929 #if USE_CG_TEXT_DRAWING
2930 if (!s->two_byte_p
2931 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
2932 s->char2b, s->nchars, bg_width,
2933 s->face->overstrike))
2935 else
2936 #endif
2937 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2938 s->char2b, s->nchars, bg_width,
2939 s->face->overstrike);
2940 else
2941 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2942 char1b, s->nchars, bg_width,
2943 s->face->overstrike);
2947 /* Draw the foreground of composite glyph string S. */
2949 static void
2950 x_draw_composite_glyph_string_foreground (s)
2951 struct glyph_string *s;
2953 int i, x;
2955 /* If first glyph of S has a left box line, start drawing the text
2956 of S to the right of that box line. */
2957 if (s->face->box != FACE_NO_BOX
2958 && s->first_glyph->left_box_line_p)
2959 x = s->x + abs (s->face->box_line_width);
2960 else
2961 x = s->x;
2963 /* S is a glyph string for a composition. S->gidx is the index of
2964 the first character drawn for glyphs of this composition.
2965 S->gidx == 0 means we are drawing the very first character of
2966 this composition. */
2968 /* Draw a rectangle for the composition if the font for the very
2969 first character of the composition could not be loaded. */
2970 if (s->font_not_found_p)
2972 if (s->gidx == 0)
2973 mac_draw_rectangle (s->f, s->gc, x, s->y,
2974 s->width - 1, s->height - 1);
2976 else
2978 for (i = 0; i < s->nchars; i++, ++s->gidx)
2979 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
2980 /* This is a nonexistent or zero-width glyph such as a
2981 combining diacritic. Draw a rectangle. */
2982 mac_draw_rectangle (s->f, s->gc,
2983 x + s->cmp->offsets[s->gidx * 2], s->y,
2984 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
2985 else
2986 mac_draw_image_string_16 (s->f, s->gc,
2987 x + s->cmp->offsets[s->gidx * 2],
2988 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2989 s->char2b + i, 1, 0, s->face->overstrike);
2994 #ifdef USE_X_TOOLKIT
2996 static struct frame *x_frame_of_widget P_ ((Widget));
2999 /* Return the frame on which widget WIDGET is used.. Abort if frame
3000 cannot be determined. */
3002 static struct frame *
3003 x_frame_of_widget (widget)
3004 Widget widget;
3006 struct x_display_info *dpyinfo;
3007 Lisp_Object tail;
3008 struct frame *f;
3010 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3012 /* Find the top-level shell of the widget. Note that this function
3013 can be called when the widget is not yet realized, so XtWindow
3014 (widget) == 0. That's the reason we can't simply use
3015 x_any_window_to_frame. */
3016 while (!XtIsTopLevelShell (widget))
3017 widget = XtParent (widget);
3019 /* Look for a frame with that top-level widget. Allocate the color
3020 on that frame to get the right gamma correction value. */
3021 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3022 if (GC_FRAMEP (XCAR (tail))
3023 && (f = XFRAME (XCAR (tail)),
3024 (f->output_data.nothing != 1
3025 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3026 && f->output_data.x->widget == widget)
3027 return f;
3029 abort ();
3033 /* Allocate the color COLOR->pixel on the screen and display of
3034 widget WIDGET in colormap CMAP. If an exact match cannot be
3035 allocated, try the nearest color available. Value is non-zero
3036 if successful. This is called from lwlib. */
3039 x_alloc_nearest_color_for_widget (widget, cmap, color)
3040 Widget widget;
3041 Colormap cmap;
3042 XColor *color;
3044 struct frame *f = x_frame_of_widget (widget);
3045 return x_alloc_nearest_color (f, cmap, color);
3049 #endif /* USE_X_TOOLKIT */
3051 #if 0 /* MAC_TODO */
3053 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3054 CMAP. If an exact match can't be allocated, try the nearest color
3055 available. Value is non-zero if successful. Set *COLOR to the
3056 color allocated. */
3059 x_alloc_nearest_color (f, cmap, color)
3060 struct frame *f;
3061 Colormap cmap;
3062 XColor *color;
3064 Display *display = FRAME_X_DISPLAY (f);
3065 Screen *screen = FRAME_X_SCREEN (f);
3066 int rc;
3068 gamma_correct (f, color);
3069 rc = XAllocColor (display, cmap, color);
3070 if (rc == 0)
3072 /* If we got to this point, the colormap is full, so we're going
3073 to try to get the next closest color. The algorithm used is
3074 a least-squares matching, which is what X uses for closest
3075 color matching with StaticColor visuals. */
3076 int nearest, i;
3077 unsigned long nearest_delta = ~0;
3078 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3079 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3081 for (i = 0; i < ncells; ++i)
3082 cells[i].pixel = i;
3083 XQueryColors (display, cmap, cells, ncells);
3085 for (nearest = i = 0; i < ncells; ++i)
3087 long dred = (color->red >> 8) - (cells[i].red >> 8);
3088 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3089 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3090 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3092 if (delta < nearest_delta)
3094 nearest = i;
3095 nearest_delta = delta;
3099 color->red = cells[nearest].red;
3100 color->green = cells[nearest].green;
3101 color->blue = cells[nearest].blue;
3102 rc = XAllocColor (display, cmap, color);
3105 #ifdef DEBUG_X_COLORS
3106 if (rc)
3107 register_color (color->pixel);
3108 #endif /* DEBUG_X_COLORS */
3110 return rc;
3114 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3115 It's necessary to do this instead of just using PIXEL directly to
3116 get color reference counts right. */
3118 unsigned long
3119 x_copy_color (f, pixel)
3120 struct frame *f;
3121 unsigned long pixel;
3123 XColor color;
3125 color.pixel = pixel;
3126 BLOCK_INPUT;
3127 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3128 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3129 UNBLOCK_INPUT;
3130 #ifdef DEBUG_X_COLORS
3131 register_color (pixel);
3132 #endif
3133 return color.pixel;
3137 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3138 It's necessary to do this instead of just using PIXEL directly to
3139 get color reference counts right. */
3141 unsigned long
3142 x_copy_dpy_color (dpy, cmap, pixel)
3143 Display *dpy;
3144 Colormap cmap;
3145 unsigned long pixel;
3147 XColor color;
3149 color.pixel = pixel;
3150 BLOCK_INPUT;
3151 XQueryColor (dpy, cmap, &color);
3152 XAllocColor (dpy, cmap, &color);
3153 UNBLOCK_INPUT;
3154 #ifdef DEBUG_X_COLORS
3155 register_color (pixel);
3156 #endif
3157 return color.pixel;
3160 #endif /* MAC_TODO */
3163 /* Brightness beyond which a color won't have its highlight brightness
3164 boosted.
3166 Nominally, highlight colors for `3d' faces are calculated by
3167 brightening an object's color by a constant scale factor, but this
3168 doesn't yield good results for dark colors, so for colors who's
3169 brightness is less than this value (on a scale of 0-255) have to
3170 use an additional additive factor.
3172 The value here is set so that the default menu-bar/mode-line color
3173 (grey75) will not have its highlights changed at all. */
3174 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3177 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3178 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3179 If this produces the same color as COLOR, try a color where all RGB
3180 values have DELTA added. Return the allocated color in *COLOR.
3181 DISPLAY is the X display, CMAP is the colormap to operate on.
3182 Value is non-zero if successful. */
3184 static int
3185 mac_alloc_lighter_color (f, color, factor, delta)
3186 struct frame *f;
3187 unsigned long *color;
3188 double factor;
3189 int delta;
3191 unsigned long new;
3192 long bright;
3194 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3195 delta /= 256;
3197 /* Change RGB values by specified FACTOR. Avoid overflow! */
3198 xassert (factor >= 0);
3199 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3200 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3201 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3203 /* Calculate brightness of COLOR. */
3204 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3205 + BLUE_FROM_ULONG (*color)) / 6;
3207 /* We only boost colors that are darker than
3208 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3209 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3210 /* Make an additive adjustment to NEW, because it's dark enough so
3211 that scaling by FACTOR alone isn't enough. */
3213 /* How far below the limit this color is (0 - 1, 1 being darker). */
3214 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3215 /* The additive adjustment. */
3216 int min_delta = delta * dimness * factor / 2;
3218 if (factor < 1)
3219 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3220 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3221 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3222 else
3223 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3224 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3225 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3228 if (new == *color)
3229 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3230 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3231 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3233 /* MAC_TODO: Map to palette and retry with delta if same? */
3234 /* MAC_TODO: Free colors (if using palette)? */
3236 if (new == *color)
3237 return 0;
3239 *color = new;
3241 return 1;
3245 /* Set up the foreground color for drawing relief lines of glyph
3246 string S. RELIEF is a pointer to a struct relief containing the GC
3247 with which lines will be drawn. Use a color that is FACTOR or
3248 DELTA lighter or darker than the relief's background which is found
3249 in S->f->output_data.x->relief_background. If such a color cannot
3250 be allocated, use DEFAULT_PIXEL, instead. */
3252 static void
3253 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3254 struct frame *f;
3255 struct relief *relief;
3256 double factor;
3257 int delta;
3258 unsigned long default_pixel;
3260 XGCValues xgcv;
3261 struct mac_output *di = f->output_data.mac;
3262 unsigned long mask = GCForeground;
3263 unsigned long pixel;
3264 unsigned long background = di->relief_background;
3265 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3267 /* MAC_TODO: Free colors (if using palette)? */
3269 /* Allocate new color. */
3270 xgcv.foreground = default_pixel;
3271 pixel = background;
3272 if (dpyinfo->n_planes != 1
3273 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3275 relief->allocated_p = 1;
3276 xgcv.foreground = relief->pixel = pixel;
3279 if (relief->gc == 0)
3281 #if 0 /* MAC_TODO: stipple */
3282 xgcv.stipple = dpyinfo->gray;
3283 mask |= GCStipple;
3284 #endif
3285 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3287 else
3288 XChangeGC (NULL, relief->gc, mask, &xgcv);
3292 /* Set up colors for the relief lines around glyph string S. */
3294 static void
3295 x_setup_relief_colors (s)
3296 struct glyph_string *s;
3298 struct mac_output *di = s->f->output_data.mac;
3299 unsigned long color;
3301 if (s->face->use_box_color_for_shadows_p)
3302 color = s->face->box_color;
3303 else if (s->first_glyph->type == IMAGE_GLYPH
3304 && s->img->pixmap
3305 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3306 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3307 else
3309 XGCValues xgcv;
3311 /* Get the background color of the face. */
3312 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3313 color = xgcv.background;
3316 if (di->white_relief.gc == 0
3317 || color != di->relief_background)
3319 di->relief_background = color;
3320 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3321 WHITE_PIX_DEFAULT (s->f));
3322 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3323 BLACK_PIX_DEFAULT (s->f));
3328 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3329 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3330 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3331 relief. LEFT_P non-zero means draw a relief on the left side of
3332 the rectangle. RIGHT_P non-zero means draw a relief on the right
3333 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3334 when drawing. */
3336 static void
3337 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3338 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3339 struct frame *f;
3340 int left_x, top_y, right_x, bottom_y, width;
3341 int top_p, bot_p, left_p, right_p, raised_p;
3342 Rect *clip_rect;
3344 int i;
3345 GC gc;
3347 if (raised_p)
3348 gc = f->output_data.mac->white_relief.gc;
3349 else
3350 gc = f->output_data.mac->black_relief.gc;
3351 mac_set_clip_rectangles (f, gc, clip_rect, 1);
3353 /* Top. */
3354 if (top_p)
3355 for (i = 0; i < width; ++i)
3356 mac_draw_line (f, gc,
3357 left_x + i * left_p, top_y + i,
3358 right_x + 1 - i * right_p, top_y + i);
3360 /* Left. */
3361 if (left_p)
3362 for (i = 0; i < width; ++i)
3363 mac_draw_line (f, gc,
3364 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3366 mac_reset_clip_rectangles (f, gc);
3367 if (raised_p)
3368 gc = f->output_data.mac->black_relief.gc;
3369 else
3370 gc = f->output_data.mac->white_relief.gc;
3371 mac_set_clip_rectangles (f, gc, clip_rect, 1);
3373 /* Bottom. */
3374 if (bot_p)
3375 for (i = 0; i < width; ++i)
3376 mac_draw_line (f, gc,
3377 left_x + i * left_p, bottom_y - i,
3378 right_x + 1 - i * right_p, bottom_y - i);
3380 /* Right. */
3381 if (right_p)
3382 for (i = 0; i < width; ++i)
3383 mac_draw_line (f, gc,
3384 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3386 mac_reset_clip_rectangles (f, gc);
3390 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3391 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3392 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3393 left side of the rectangle. RIGHT_P non-zero means draw a line
3394 on the right side of the rectangle. CLIP_RECT is the clipping
3395 rectangle to use when drawing. */
3397 static void
3398 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3399 left_p, right_p, clip_rect)
3400 struct glyph_string *s;
3401 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3402 Rect *clip_rect;
3404 XGCValues xgcv;
3406 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3407 XSetForeground (s->display, s->gc, s->face->box_color);
3408 mac_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
3410 /* Top. */
3411 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3412 right_x - left_x + 1, width);
3414 /* Left. */
3415 if (left_p)
3416 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3417 width, bottom_y - top_y + 1);
3419 /* Bottom. */
3420 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3421 right_x - left_x + 1, width);
3423 /* Right. */
3424 if (right_p)
3425 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3426 top_y, width, bottom_y - top_y + 1);
3428 XSetForeground (s->display, s->gc, xgcv.foreground);
3429 mac_reset_clip_rectangles (s->f, s->gc);
3433 /* Draw a box around glyph string S. */
3435 static void
3436 x_draw_glyph_string_box (s)
3437 struct glyph_string *s;
3439 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3440 int left_p, right_p;
3441 struct glyph *last_glyph;
3442 Rect clip_rect;
3444 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3445 ? WINDOW_RIGHT_EDGE_X (s->w)
3446 : window_box_right (s->w, s->area));
3448 /* The glyph that may have a right box line. */
3449 last_glyph = (s->cmp || s->img
3450 ? s->first_glyph
3451 : s->first_glyph + s->nchars - 1);
3453 width = abs (s->face->box_line_width);
3454 raised_p = s->face->box == FACE_RAISED_BOX;
3455 left_x = s->x;
3456 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3457 ? last_x - 1
3458 : min (last_x, s->x + s->background_width) - 1);
3459 top_y = s->y;
3460 bottom_y = top_y + s->height - 1;
3462 left_p = (s->first_glyph->left_box_line_p
3463 || (s->hl == DRAW_MOUSE_FACE
3464 && (s->prev == NULL
3465 || s->prev->hl != s->hl)));
3466 right_p = (last_glyph->right_box_line_p
3467 || (s->hl == DRAW_MOUSE_FACE
3468 && (s->next == NULL
3469 || s->next->hl != s->hl)));
3471 get_glyph_string_clip_rect (s, &clip_rect);
3473 if (s->face->box == FACE_SIMPLE_BOX)
3474 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3475 left_p, right_p, &clip_rect);
3476 else
3478 x_setup_relief_colors (s);
3479 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3480 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3485 /* Draw foreground of image glyph string S. */
3487 static void
3488 x_draw_image_foreground (s)
3489 struct glyph_string *s;
3491 int x = s->x;
3492 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3494 /* If first glyph of S has a left box line, start drawing it to the
3495 right of that line. */
3496 if (s->face->box != FACE_NO_BOX
3497 && s->first_glyph->left_box_line_p
3498 && s->slice.x == 0)
3499 x += abs (s->face->box_line_width);
3501 /* If there is a margin around the image, adjust x- and y-position
3502 by that margin. */
3503 if (s->slice.x == 0)
3504 x += s->img->hmargin;
3505 if (s->slice.y == 0)
3506 y += s->img->vmargin;
3508 if (s->img->pixmap)
3510 x_set_glyph_string_clipping (s);
3512 #if USE_CG_DRAWING
3513 mac_draw_cg_image (s->img->data.ptr_val,
3514 s->f, s->gc, s->slice.x, s->slice.y,
3515 s->slice.width, s->slice.height, x, y, 1);
3516 #endif
3517 if (s->img->mask)
3518 #if !USE_CG_DRAWING
3519 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3520 s->f, s->gc, s->slice.x, s->slice.y,
3521 s->slice.width, s->slice.height, x, y);
3522 #else
3524 #endif
3525 else
3527 #if !USE_CG_DRAWING
3528 mac_copy_area (s->img->pixmap,
3529 s->f, s->gc, s->slice.x, s->slice.y,
3530 s->slice.width, s->slice.height, x, y);
3531 #endif
3533 /* When the image has a mask, we can expect that at
3534 least part of a mouse highlight or a block cursor will
3535 be visible. If the image doesn't have a mask, make
3536 a block cursor visible by drawing a rectangle around
3537 the image. I believe it's looking better if we do
3538 nothing here for mouse-face. */
3539 if (s->hl == DRAW_CURSOR)
3541 int r = s->img->relief;
3542 if (r < 0) r = -r;
3543 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3544 s->slice.width + r*2 - 1,
3545 s->slice.height + r*2 - 1);
3549 else
3550 /* Draw a rectangle if image could not be loaded. */
3551 mac_draw_rectangle (s->f, s->gc, x, y,
3552 s->slice.width - 1, s->slice.height - 1);
3556 /* Draw a relief around the image glyph string S. */
3558 static void
3559 x_draw_image_relief (s)
3560 struct glyph_string *s;
3562 int x0, y0, x1, y1, thick, raised_p;
3563 Rect r;
3564 int x = s->x;
3565 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3567 /* If first glyph of S has a left box line, start drawing it to the
3568 right of that line. */
3569 if (s->face->box != FACE_NO_BOX
3570 && s->first_glyph->left_box_line_p
3571 && s->slice.x == 0)
3572 x += abs (s->face->box_line_width);
3574 /* If there is a margin around the image, adjust x- and y-position
3575 by that margin. */
3576 if (s->slice.x == 0)
3577 x += s->img->hmargin;
3578 if (s->slice.y == 0)
3579 y += s->img->vmargin;
3581 if (s->hl == DRAW_IMAGE_SUNKEN
3582 || s->hl == DRAW_IMAGE_RAISED)
3584 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3585 raised_p = s->hl == DRAW_IMAGE_RAISED;
3587 else
3589 thick = abs (s->img->relief);
3590 raised_p = s->img->relief > 0;
3593 x0 = x - thick;
3594 y0 = y - thick;
3595 x1 = x + s->slice.width + thick - 1;
3596 y1 = y + s->slice.height + thick - 1;
3598 x_setup_relief_colors (s);
3599 get_glyph_string_clip_rect (s, &r);
3600 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3601 s->slice.y == 0,
3602 s->slice.y + s->slice.height == s->img->height,
3603 s->slice.x == 0,
3604 s->slice.x + s->slice.width == s->img->width,
3605 &r);
3609 /* Draw part of the background of glyph string S. X, Y, W, and H
3610 give the rectangle to draw. */
3612 static void
3613 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3614 struct glyph_string *s;
3615 int x, y, w, h;
3617 #if 0 /* MAC_TODO: stipple */
3618 if (s->stippled_p)
3620 /* Fill background with a stipple pattern. */
3621 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3622 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3623 XSetFillStyle (s->display, s->gc, FillSolid);
3625 else
3626 #endif /* MAC_TODO */
3627 x_clear_glyph_string_rect (s, x, y, w, h);
3631 /* Draw image glyph string S.
3633 s->y
3634 s->x +-------------------------
3635 | s->face->box
3637 | +-------------------------
3638 | | s->img->margin
3640 | | +-------------------
3641 | | | the image
3645 static void
3646 x_draw_image_glyph_string (s)
3647 struct glyph_string *s;
3649 int x, y;
3650 int box_line_hwidth = abs (s->face->box_line_width);
3651 int box_line_vwidth = max (s->face->box_line_width, 0);
3652 int height;
3654 height = s->height - 2 * box_line_vwidth;
3657 /* Fill background with face under the image. Do it only if row is
3658 taller than image or if image has a clip mask to reduce
3659 flickering. */
3660 s->stippled_p = s->face->stipple != 0;
3661 if (height > s->slice.height
3662 || s->img->hmargin
3663 || s->img->vmargin
3664 || s->img->mask
3665 || s->img->pixmap == 0
3666 || s->width != s->background_width)
3668 x = s->x;
3669 if (s->first_glyph->left_box_line_p
3670 && s->slice.x == 0)
3671 x += box_line_hwidth;
3673 y = s->y;
3674 if (s->slice.y == 0)
3675 y += box_line_vwidth;
3677 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3679 s->background_filled_p = 1;
3682 /* Draw the foreground. */
3683 x_draw_image_foreground (s);
3685 /* If we must draw a relief around the image, do it. */
3686 if (s->img->relief
3687 || s->hl == DRAW_IMAGE_RAISED
3688 || s->hl == DRAW_IMAGE_SUNKEN)
3689 x_draw_image_relief (s);
3693 /* Draw stretch glyph string S. */
3695 static void
3696 x_draw_stretch_glyph_string (s)
3697 struct glyph_string *s;
3699 xassert (s->first_glyph->type == STRETCH_GLYPH);
3701 if (s->hl == DRAW_CURSOR
3702 && !x_stretch_cursor_p)
3704 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3705 as wide as the stretch glyph. */
3706 int width, background_width = s->background_width;
3707 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3709 if (x < left_x)
3711 background_width -= left_x - x;
3712 x = left_x;
3714 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3716 /* Draw cursor. */
3717 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3719 /* Clear rest using the GC of the original non-cursor face. */
3720 if (width < background_width)
3722 int y = s->y;
3723 int w = background_width - width, h = s->height;
3724 Rect r;
3725 GC gc;
3727 x += width;
3728 if (s->row->mouse_face_p
3729 && cursor_in_mouse_face_p (s->w))
3731 x_set_mouse_face_gc (s);
3732 gc = s->gc;
3734 else
3735 gc = s->face->gc;
3737 get_glyph_string_clip_rect (s, &r);
3738 mac_set_clip_rectangles (s->f, gc, &r, 1);
3740 #if 0 /* MAC_TODO: stipple */
3741 if (s->face->stipple)
3743 /* Fill background with a stipple pattern. */
3744 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3745 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3746 XSetFillStyle (s->display, gc, FillSolid);
3748 else
3749 #endif /* MAC_TODO */
3750 mac_erase_rectangle (s->f, gc, x, y, w, h);
3753 else if (!s->background_filled_p)
3755 int background_width = s->background_width;
3756 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3758 /* Don't draw into left margin, fringe or scrollbar area
3759 except for header line and mode line. */
3760 if (x < left_x && !s->row->mode_line_p)
3762 background_width -= left_x - x;
3763 x = left_x;
3765 if (background_width > 0)
3766 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3769 s->background_filled_p = 1;
3773 /* Draw glyph string S. */
3775 static void
3776 x_draw_glyph_string (s)
3777 struct glyph_string *s;
3779 int relief_drawn_p = 0;
3781 /* If S draws into the background of its successor that does not
3782 draw a cursor, draw the background of the successor first so that
3783 S can draw into it. This makes S->next use XDrawString instead
3784 of XDrawImageString. */
3785 if (s->next && s->right_overhang && !s->for_overlaps
3786 && s->next->hl != DRAW_CURSOR)
3788 xassert (s->next->img == NULL);
3789 x_set_glyph_string_gc (s->next);
3790 x_set_glyph_string_clipping (s->next);
3791 x_draw_glyph_string_background (s->next, 1);
3794 /* Set up S->gc, set clipping and draw S. */
3795 x_set_glyph_string_gc (s);
3797 /* Draw relief (if any) in advance for char/composition so that the
3798 glyph string can be drawn over it. */
3799 if (!s->for_overlaps
3800 && s->face->box != FACE_NO_BOX
3801 && (s->first_glyph->type == CHAR_GLYPH
3802 || s->first_glyph->type == COMPOSITE_GLYPH))
3805 x_set_glyph_string_clipping (s);
3806 x_draw_glyph_string_background (s, 1);
3807 x_draw_glyph_string_box (s);
3808 x_set_glyph_string_clipping (s);
3809 relief_drawn_p = 1;
3811 else
3812 x_set_glyph_string_clipping (s);
3814 switch (s->first_glyph->type)
3816 case IMAGE_GLYPH:
3817 x_draw_image_glyph_string (s);
3818 break;
3820 case STRETCH_GLYPH:
3821 x_draw_stretch_glyph_string (s);
3822 break;
3824 case CHAR_GLYPH:
3825 if (s->for_overlaps)
3826 s->background_filled_p = 1;
3827 else
3828 x_draw_glyph_string_background (s, 0);
3829 x_draw_glyph_string_foreground (s);
3830 break;
3832 case COMPOSITE_GLYPH:
3833 if (s->for_overlaps || s->gidx > 0)
3834 s->background_filled_p = 1;
3835 else
3836 x_draw_glyph_string_background (s, 1);
3837 x_draw_composite_glyph_string_foreground (s);
3838 break;
3840 default:
3841 abort ();
3844 if (!s->for_overlaps)
3846 /* Draw underline. */
3847 if (s->face->underline_p)
3849 unsigned long tem, h;
3850 int y;
3852 #if 0
3853 /* Get the underline thickness. Default is 1 pixel. */
3854 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3855 #endif
3856 h = 1;
3858 y = s->y + s->height - h;
3859 if (!x_underline_at_descent_line)
3861 /* Get the underline position. This is the recommended
3862 vertical offset in pixels from the baseline to the top of
3863 the underline. This is a signed value according to the
3864 specs, and its default is
3866 ROUND ((maximum descent) / 2), with
3867 ROUND(x) = floor (x + 0.5) */
3869 #if 0
3870 if (x_use_underline_position_properties
3871 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3872 y = s->ybase + (long) tem;
3873 else
3874 #endif
3875 if (s->face->font)
3876 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3879 if (s->face->underline_defaulted_p)
3880 mac_fill_rectangle (s->f, s->gc, s->x, y,
3881 s->background_width, h);
3882 else
3884 XGCValues xgcv;
3885 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3886 XSetForeground (s->display, s->gc, s->face->underline_color);
3887 mac_fill_rectangle (s->f, s->gc, s->x, y,
3888 s->background_width, h);
3889 XSetForeground (s->display, s->gc, xgcv.foreground);
3893 /* Draw overline. */
3894 if (s->face->overline_p)
3896 unsigned long dy = 0, h = 1;
3898 if (s->face->overline_color_defaulted_p)
3899 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3900 s->background_width, h);
3901 else
3903 XGCValues xgcv;
3904 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3905 XSetForeground (s->display, s->gc, s->face->overline_color);
3906 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3907 s->background_width, h);
3908 XSetForeground (s->display, s->gc, xgcv.foreground);
3912 /* Draw strike-through. */
3913 if (s->face->strike_through_p)
3915 unsigned long h = 1;
3916 unsigned long dy = (s->height - h) / 2;
3918 if (s->face->strike_through_color_defaulted_p)
3919 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3920 s->width, h);
3921 else
3923 XGCValues xgcv;
3924 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3925 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3926 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3927 s->width, h);
3928 XSetForeground (s->display, s->gc, xgcv.foreground);
3932 /* Draw relief if not yet drawn. */
3933 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3934 x_draw_glyph_string_box (s);
3937 /* Reset clipping. */
3938 mac_reset_clip_rectangles (s->f, s->gc);
3941 /* Shift display to make room for inserted glyphs. */
3943 void
3944 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3945 struct frame *f;
3946 int x, y, width, height, shift_by;
3948 mac_scroll_area (f, f->output_data.mac->normal_gc,
3949 x, y, width, height,
3950 x + shift_by, y);
3953 /* Delete N glyphs at the nominal cursor position. Not implemented
3954 for X frames. */
3956 static void
3957 x_delete_glyphs (n)
3958 register int n;
3960 abort ();
3964 /* Clear entire frame. If updating_frame is non-null, clear that
3965 frame. Otherwise clear the selected frame. */
3967 static void
3968 x_clear_frame ()
3970 struct frame *f;
3972 if (updating_frame)
3973 f = updating_frame;
3974 else
3975 f = SELECTED_FRAME ();
3977 /* Clearing the frame will erase any cursor, so mark them all as no
3978 longer visible. */
3979 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3980 output_cursor.hpos = output_cursor.vpos = 0;
3981 output_cursor.x = -1;
3983 /* We don't set the output cursor here because there will always
3984 follow an explicit cursor_to. */
3985 BLOCK_INPUT;
3986 mac_clear_window (f);
3988 /* We have to clear the scroll bars, too. If we have changed
3989 colors or something like that, then they should be notified. */
3990 x_scroll_bar_clear (f);
3992 XFlush (FRAME_MAC_DISPLAY (f));
3993 UNBLOCK_INPUT;
3998 /* Invert the middle quarter of the frame for .15 sec. */
4000 /* We use the select system call to do the waiting, so we have to make
4001 sure it's available. If it isn't, we just won't do visual bells. */
4003 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4006 /* Subtract the `struct timeval' values X and Y, storing the result in
4007 *RESULT. Return 1 if the difference is negative, otherwise 0. */
4009 static int
4010 timeval_subtract (result, x, y)
4011 struct timeval *result, x, y;
4013 /* Perform the carry for the later subtraction by updating y. This
4014 is safer because on some systems the tv_sec member is unsigned. */
4015 if (x.tv_usec < y.tv_usec)
4017 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4018 y.tv_usec -= 1000000 * nsec;
4019 y.tv_sec += nsec;
4022 if (x.tv_usec - y.tv_usec > 1000000)
4024 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4025 y.tv_usec += 1000000 * nsec;
4026 y.tv_sec -= nsec;
4029 /* Compute the time remaining to wait. tv_usec is certainly
4030 positive. */
4031 result->tv_sec = x.tv_sec - y.tv_sec;
4032 result->tv_usec = x.tv_usec - y.tv_usec;
4034 /* Return indication of whether the result should be considered
4035 negative. */
4036 return x.tv_sec < y.tv_sec;
4039 void
4040 XTflash (f)
4041 struct frame *f;
4043 /* Get the height not including a menu bar widget. */
4044 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4045 /* Height of each line to flash. */
4046 int flash_height = FRAME_LINE_HEIGHT (f);
4047 /* These will be the left and right margins of the rectangles. */
4048 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4049 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4051 int width;
4053 /* Don't flash the area between a scroll bar and the frame
4054 edge it is next to. */
4055 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4057 case vertical_scroll_bar_left:
4058 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4059 break;
4061 case vertical_scroll_bar_right:
4062 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4063 break;
4065 default:
4066 break;
4069 width = flash_right - flash_left;
4071 BLOCK_INPUT;
4073 /* If window is tall, flash top and bottom line. */
4074 if (height > 3 * FRAME_LINE_HEIGHT (f))
4076 mac_invert_rectangle (f, flash_left,
4077 (FRAME_INTERNAL_BORDER_WIDTH (f)
4078 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4079 width, flash_height);
4080 mac_invert_rectangle (f, flash_left,
4081 (height - flash_height
4082 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4083 width, flash_height);
4085 else
4086 /* If it is short, flash it all. */
4087 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4088 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4090 x_flush (f);
4093 struct timeval wakeup;
4095 EMACS_GET_TIME (wakeup);
4097 /* Compute time to wait until, propagating carry from usecs. */
4098 wakeup.tv_usec += 150000;
4099 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4100 wakeup.tv_usec %= 1000000;
4102 /* Keep waiting until past the time wakeup or any input gets
4103 available. */
4104 while (! detect_input_pending ())
4106 struct timeval current;
4107 struct timeval timeout;
4109 EMACS_GET_TIME (current);
4111 /* Break if result would be negative. */
4112 if (timeval_subtract (&current, wakeup, current))
4113 break;
4115 /* How long `select' should wait. */
4116 timeout.tv_sec = 0;
4117 timeout.tv_usec = 10000;
4119 /* Try to wait that long--but we might wake up sooner. */
4120 select (0, NULL, NULL, NULL, &timeout);
4124 /* If window is tall, flash top and bottom line. */
4125 if (height > 3 * FRAME_LINE_HEIGHT (f))
4127 mac_invert_rectangle (f, flash_left,
4128 (FRAME_INTERNAL_BORDER_WIDTH (f)
4129 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4130 width, flash_height);
4131 mac_invert_rectangle (f, flash_left,
4132 (height - flash_height
4133 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4134 width, flash_height);
4136 else
4137 /* If it is short, flash it all. */
4138 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4139 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4141 x_flush (f);
4143 UNBLOCK_INPUT;
4146 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4149 /* Make audible bell. */
4151 void
4152 XTring_bell ()
4154 struct frame *f = SELECTED_FRAME ();
4156 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4157 if (visible_bell)
4158 XTflash (f);
4159 else
4160 #endif
4162 BLOCK_INPUT;
4163 mac_alert_sound_play ();
4164 XFlush (FRAME_MAC_DISPLAY (f));
4165 UNBLOCK_INPUT;
4170 /* Specify how many text lines, from the top of the window,
4171 should be affected by insert-lines and delete-lines operations.
4172 This, and those operations, are used only within an update
4173 that is bounded by calls to x_update_begin and x_update_end. */
4175 static void
4176 XTset_terminal_window (n)
4177 register int n;
4179 /* This function intentionally left blank. */
4184 /***********************************************************************
4185 Line Dance
4186 ***********************************************************************/
4188 /* Perform an insert-lines or delete-lines operation, inserting N
4189 lines or deleting -N lines at vertical position VPOS. */
4191 static void
4192 x_ins_del_lines (vpos, n)
4193 int vpos, n;
4195 abort ();
4199 /* Scroll part of the display as described by RUN. */
4201 static void
4202 x_scroll_run (w, run)
4203 struct window *w;
4204 struct run *run;
4206 struct frame *f = XFRAME (w->frame);
4207 int x, y, width, height, from_y, to_y, bottom_y;
4209 /* Get frame-relative bounding box of the text display area of W,
4210 without mode lines. Include in this box the left and right
4211 fringe of W. */
4212 window_box (w, -1, &x, &y, &width, &height);
4214 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4215 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4216 bottom_y = y + height;
4218 if (to_y < from_y)
4220 /* Scrolling up. Make sure we don't copy part of the mode
4221 line at the bottom. */
4222 if (from_y + run->height > bottom_y)
4223 height = bottom_y - from_y;
4224 else
4225 height = run->height;
4227 else
4229 /* Scolling down. Make sure we don't copy over the mode line.
4230 at the bottom. */
4231 if (to_y + run->height > bottom_y)
4232 height = bottom_y - to_y;
4233 else
4234 height = run->height;
4237 BLOCK_INPUT;
4239 /* Cursor off. Will be switched on again in x_update_window_end. */
4240 updated_window = w;
4241 x_clear_cursor (w);
4243 mac_scroll_area (f, f->output_data.mac->normal_gc,
4244 x, from_y,
4245 width, height,
4246 x, to_y);
4248 UNBLOCK_INPUT;
4253 /***********************************************************************
4254 Exposure Events
4255 ***********************************************************************/
4258 static void
4259 frame_highlight (f)
4260 struct frame *f;
4262 x_update_cursor (f, 1);
4265 static void
4266 frame_unhighlight (f)
4267 struct frame *f;
4269 x_update_cursor (f, 1);
4272 /* The focus has changed. Update the frames as necessary to reflect
4273 the new situation. Note that we can't change the selected frame
4274 here, because the Lisp code we are interrupting might become confused.
4275 Each event gets marked with the frame in which it occurred, so the
4276 Lisp code can tell when the switch took place by examining the events. */
4278 static void
4279 x_new_focus_frame (dpyinfo, frame)
4280 struct x_display_info *dpyinfo;
4281 struct frame *frame;
4283 struct frame *old_focus = dpyinfo->x_focus_frame;
4285 if (frame != dpyinfo->x_focus_frame)
4287 /* Set this before calling other routines, so that they see
4288 the correct value of x_focus_frame. */
4289 dpyinfo->x_focus_frame = frame;
4291 if (old_focus && old_focus->auto_lower)
4292 x_lower_frame (old_focus);
4294 #if 0
4295 selected_frame = frame;
4296 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4297 selected_frame);
4298 Fselect_window (selected_frame->selected_window, Qnil);
4299 choose_minibuf_frame ();
4300 #endif /* ! 0 */
4302 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4303 pending_autoraise_frame = dpyinfo->x_focus_frame;
4304 else
4305 pending_autoraise_frame = 0;
4307 #if USE_MAC_FONT_PANEL
4308 if (frame)
4309 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4310 #endif
4313 x_frame_rehighlight (dpyinfo);
4316 /* Handle FocusIn and FocusOut state changes for FRAME.
4317 If FRAME has focus and there exists more than one frame, puts
4318 a FOCUS_IN_EVENT into *BUFP. */
4320 void
4321 mac_focus_changed (type, dpyinfo, frame, bufp)
4322 int type;
4323 struct mac_display_info *dpyinfo;
4324 struct frame *frame;
4325 struct input_event *bufp;
4327 if (type == activeFlag)
4329 if (dpyinfo->x_focus_event_frame != frame)
4331 x_new_focus_frame (dpyinfo, frame);
4332 dpyinfo->x_focus_event_frame = frame;
4334 /* Don't stop displaying the initial startup message
4335 for a switch-frame event we don't need. */
4336 if (GC_NILP (Vterminal_frame)
4337 && GC_CONSP (Vframe_list)
4338 && !GC_NILP (XCDR (Vframe_list)))
4340 bufp->kind = FOCUS_IN_EVENT;
4341 XSETFRAME (bufp->frame_or_window, frame);
4345 else
4347 if (dpyinfo->x_focus_event_frame == frame)
4349 dpyinfo->x_focus_event_frame = 0;
4350 x_new_focus_frame (dpyinfo, 0);
4355 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4357 void
4358 x_mouse_leave (dpyinfo)
4359 struct x_display_info *dpyinfo;
4361 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4364 /* The focus has changed, or we have redirected a frame's focus to
4365 another frame (this happens when a frame uses a surrogate
4366 mini-buffer frame). Shift the highlight as appropriate.
4368 The FRAME argument doesn't necessarily have anything to do with which
4369 frame is being highlighted or un-highlighted; we only use it to find
4370 the appropriate X display info. */
4372 static void
4373 XTframe_rehighlight (frame)
4374 struct frame *frame;
4376 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4379 static void
4380 x_frame_rehighlight (dpyinfo)
4381 struct x_display_info *dpyinfo;
4383 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4385 if (dpyinfo->x_focus_frame)
4387 dpyinfo->x_highlight_frame
4388 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4389 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4390 : dpyinfo->x_focus_frame);
4391 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4393 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4394 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4397 else
4398 dpyinfo->x_highlight_frame = 0;
4400 if (dpyinfo->x_highlight_frame != old_highlight)
4402 if (old_highlight)
4403 frame_unhighlight (old_highlight);
4404 if (dpyinfo->x_highlight_frame)
4405 frame_highlight (dpyinfo->x_highlight_frame);
4411 /* Convert a keysym to its name. */
4413 char *
4414 x_get_keysym_name (keysym)
4415 int keysym;
4417 char *value;
4419 BLOCK_INPUT;
4420 #if 0
4421 value = XKeysymToString (keysym);
4422 #else
4423 value = 0;
4424 #endif
4425 UNBLOCK_INPUT;
4427 return value;
4432 /* Function to report a mouse movement to the mainstream Emacs code.
4433 The input handler calls this.
4435 We have received a mouse movement event, which is given in *event.
4436 If the mouse is over a different glyph than it was last time, tell
4437 the mainstream emacs code by setting mouse_moved. If not, ask for
4438 another motion event, so we can check again the next time it moves. */
4440 static Point last_mouse_motion_position;
4441 static Lisp_Object last_mouse_motion_frame;
4444 note_mouse_movement (frame, pos)
4445 FRAME_PTR frame;
4446 Point *pos;
4448 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4449 Rect r;
4451 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4452 last_mouse_motion_position = *pos;
4453 XSETFRAME (last_mouse_motion_frame, frame);
4455 if (frame == dpyinfo->mouse_face_mouse_frame
4456 && !PtInRect (*pos, mac_get_frame_bounds (frame, &r)))
4458 /* This case corresponds to LeaveNotify in X11. If we move
4459 outside the frame, then we're certainly no longer on any text
4460 in the frame. */
4461 clear_mouse_face (dpyinfo);
4462 dpyinfo->mouse_face_mouse_frame = 0;
4463 if (!dpyinfo->grabbed)
4464 rif->define_frame_cursor (frame,
4465 frame->output_data.mac->nontext_cursor);
4468 /* Has the mouse moved off the glyph it was on at the last sighting? */
4469 if (frame != last_mouse_glyph_frame
4470 || !PtInRect (*pos, &last_mouse_glyph))
4472 frame->mouse_moved = 1;
4473 last_mouse_scroll_bar = Qnil;
4474 note_mouse_highlight (frame, pos->h, pos->v);
4475 /* Remember which glyph we're now on. */
4476 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4477 last_mouse_glyph_frame = frame;
4478 return 1;
4481 return 0;
4485 /************************************************************************
4486 Mouse Face
4487 ************************************************************************/
4489 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4491 static void
4492 redo_mouse_highlight ()
4494 if (!NILP (last_mouse_motion_frame)
4495 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4496 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4497 last_mouse_motion_position.h,
4498 last_mouse_motion_position.v);
4502 struct frame *
4503 mac_focus_frame (dpyinfo)
4504 struct mac_display_info *dpyinfo;
4506 if (dpyinfo->x_focus_frame)
4507 return dpyinfo->x_focus_frame;
4508 else
4509 /* Mac version may get events, such as a menu bar click, even when
4510 all the frames are invisible. In this case, we regard the
4511 event came to the selected frame. */
4512 return SELECTED_FRAME ();
4516 /* Return the current position of the mouse.
4517 *FP should be a frame which indicates which display to ask about.
4519 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4520 and *PART to the frame, window, and scroll bar part that the mouse
4521 is over. Set *X and *Y to the portion and whole of the mouse's
4522 position on the scroll bar.
4524 If the mouse movement started elsewhere, set *FP to the frame the
4525 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4526 the mouse is over.
4528 Set *TIME to the server time-stamp for the time at which the mouse
4529 was at this position.
4531 Don't store anything if we don't have a valid set of values to report.
4533 This clears the mouse_moved flag, so we can wait for the next mouse
4534 movement. */
4536 static void
4537 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4538 FRAME_PTR *fp;
4539 int insist;
4540 Lisp_Object *bar_window;
4541 enum scroll_bar_part *part;
4542 Lisp_Object *x, *y;
4543 unsigned long *time;
4545 FRAME_PTR f1;
4547 BLOCK_INPUT;
4549 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4550 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4551 else
4553 Lisp_Object frame, tail;
4555 /* Clear the mouse-moved flag for every frame on this display. */
4556 FOR_EACH_FRAME (tail, frame)
4557 XFRAME (frame)->mouse_moved = 0;
4559 last_mouse_scroll_bar = Qnil;
4561 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4562 && FRAME_LIVE_P (last_mouse_frame))
4563 f1 = last_mouse_frame;
4564 else
4565 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4567 if (f1)
4569 /* Ok, we found a frame. Store all the values.
4570 last_mouse_glyph is a rectangle used to reduce the
4571 generation of mouse events. To not miss any motion
4572 events, we must divide the frame into rectangles of the
4573 size of the smallest character that could be displayed
4574 on it, i.e. into the same rectangles that matrices on
4575 the frame are divided into. */
4576 Point mouse_pos;
4578 mac_get_frame_mouse (f1, &mouse_pos);
4579 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4580 &last_mouse_glyph);
4581 last_mouse_glyph_frame = f1;
4583 *bar_window = Qnil;
4584 *part = 0;
4585 *fp = f1;
4586 XSETINT (*x, mouse_pos.h);
4587 XSETINT (*y, mouse_pos.v);
4588 *time = last_mouse_movement_time;
4592 UNBLOCK_INPUT;
4596 /************************************************************************
4597 Scroll bars, general
4598 ************************************************************************/
4600 /* Create a scroll bar and return the scroll bar vector for it. W is
4601 the Emacs window on which to create the scroll bar. TOP, LEFT,
4602 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4603 scroll bar. */
4605 static struct scroll_bar *
4606 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4607 struct window *w;
4608 int top, left, width, height, disp_top, disp_height;
4610 struct frame *f = XFRAME (w->frame);
4611 struct scroll_bar *bar
4612 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4613 Rect r;
4615 BLOCK_INPUT;
4617 XSETWINDOW (bar->window, w);
4618 XSETINT (bar->top, top);
4619 XSETINT (bar->left, left);
4620 XSETINT (bar->width, width);
4621 XSETINT (bar->height, height);
4622 #ifdef MAC_OSX
4623 bar->fringe_extended_p = Qnil;
4624 #endif
4625 bar->redraw_needed_p = Qnil;
4627 SetRect (&r, left, disp_top, left + width, disp_top + disp_height);
4628 mac_create_scroll_bar (bar, &r,
4629 #ifdef USE_TOOLKIT_SCROLL_BARS
4630 false
4631 #else
4632 width < disp_height
4633 #endif
4636 /* Add bar to its frame's list of scroll bars. */
4637 bar->next = FRAME_SCROLL_BARS (f);
4638 bar->prev = Qnil;
4639 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4640 if (!NILP (bar->next))
4641 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4643 UNBLOCK_INPUT;
4644 return bar;
4648 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4649 nil. */
4651 static void
4652 x_scroll_bar_remove (bar)
4653 struct scroll_bar *bar;
4655 BLOCK_INPUT;
4657 /* Destroy the Mac scroll bar control */
4658 mac_dispose_scroll_bar (bar);
4660 /* Disassociate this scroll bar from its window. */
4661 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4663 UNBLOCK_INPUT;
4667 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4668 that we are displaying PORTION characters out of a total of WHOLE
4669 characters, starting at POSITION. If WINDOW has no scroll bar,
4670 create one. */
4672 static void
4673 XTset_vertical_scroll_bar (w, portion, whole, position)
4674 struct window *w;
4675 int portion, whole, position;
4677 struct frame *f = XFRAME (w->frame);
4678 struct scroll_bar *bar;
4679 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4680 int window_y, window_height;
4681 #ifdef MAC_OSX
4682 int fringe_extended_p;
4683 #endif
4685 /* Get window dimensions. */
4686 window_box (w, -1, 0, &window_y, 0, &window_height);
4687 top = window_y;
4688 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4689 height = window_height;
4691 /* Compute the left edge of the scroll bar area. */
4692 left = WINDOW_SCROLL_BAR_AREA_X (w);
4694 /* Compute the width of the scroll bar which might be less than
4695 the width of the area reserved for the scroll bar. */
4696 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4697 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4698 else
4699 sb_width = width;
4701 /* Compute the left edge of the scroll bar. */
4702 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4703 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
4704 else
4705 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
4707 /* Adjustments according to Inside Macintosh to make it look nice */
4708 disp_top = top;
4709 disp_height = height;
4710 #ifdef MAC_OS8
4711 if (disp_top == 0)
4713 disp_top = -1;
4714 disp_height++;
4716 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4718 disp_top++;
4719 disp_height--;
4722 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4723 sb_left++;
4724 #endif
4726 #ifdef MAC_OSX
4727 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
4728 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
4729 && WINDOW_LEFT_FRINGE_WIDTH (w)
4730 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4731 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
4732 else
4733 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
4734 && WINDOW_RIGHT_FRINGE_WIDTH (w)
4735 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4736 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
4737 #endif
4739 /* Does the scroll bar exist yet? */
4740 if (NILP (w->vertical_scroll_bar))
4742 BLOCK_INPUT;
4743 #ifdef MAC_OSX
4744 if (fringe_extended_p)
4745 mac_clear_area (f, sb_left, top, sb_width, height);
4746 else
4747 #endif
4748 mac_clear_area (f, left, top, width, height);
4749 UNBLOCK_INPUT;
4750 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4751 disp_height);
4752 XSETVECTOR (w->vertical_scroll_bar, bar);
4754 else
4756 /* It may just need to be moved and resized. */
4757 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4759 BLOCK_INPUT;
4761 /* If already correctly positioned, do nothing. */
4762 if (XINT (bar->left) == sb_left
4763 && XINT (bar->top) == top
4764 && XINT (bar->width) == sb_width
4765 && XINT (bar->height) == height
4766 #ifdef MAC_OSX
4767 && !NILP (bar->fringe_extended_p) == fringe_extended_p
4768 #endif
4771 if (!NILP (bar->redraw_needed_p))
4772 mac_redraw_scroll_bar (bar);
4774 else
4776 Rect r;
4778 /* Since toolkit scroll bars are smaller than the space reserved
4779 for them on the frame, we have to clear "under" them. */
4780 #ifdef MAC_OSX
4781 if (fringe_extended_p)
4782 mac_clear_area (f, sb_left, top, sb_width, height);
4783 else
4784 #endif
4785 mac_clear_area (f, left, top, width, height);
4787 SetRect (&r, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top,
4788 sb_left + sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4789 disp_top + disp_height);
4790 mac_set_scroll_bar_bounds (bar, &r);
4792 /* Remember new settings. */
4793 XSETINT (bar->left, sb_left);
4794 XSETINT (bar->top, top);
4795 XSETINT (bar->width, sb_width);
4796 XSETINT (bar->height, height);
4799 UNBLOCK_INPUT;
4802 #ifdef MAC_OSX
4803 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
4804 #endif
4805 bar->redraw_needed_p = Qnil;
4807 #ifdef USE_TOOLKIT_SCROLL_BARS
4808 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4809 #else /* not USE_TOOLKIT_SCROLL_BARS */
4810 /* Set the scroll bar's current state, unless we're currently being
4811 dragged. */
4812 if (NILP (bar->dragging))
4814 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4816 if (whole == 0)
4817 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4818 else
4820 int start = ((double) position * top_range) / whole;
4821 int end = ((double) (position + portion) * top_range) / whole;
4822 x_scroll_bar_set_handle (bar, start, end, 0);
4825 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4829 /* The following three hooks are used when we're doing a thorough
4830 redisplay of the frame. We don't explicitly know which scroll bars
4831 are going to be deleted, because keeping track of when windows go
4832 away is a real pain - "Can you say set-window-configuration, boys
4833 and girls?" Instead, we just assert at the beginning of redisplay
4834 that *all* scroll bars are to be removed, and then save a scroll bar
4835 from the fiery pit when we actually redisplay its window. */
4837 /* Arrange for all scroll bars on FRAME to be removed at the next call
4838 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4839 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4841 static void
4842 XTcondemn_scroll_bars (frame)
4843 FRAME_PTR frame;
4845 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4846 while (! NILP (FRAME_SCROLL_BARS (frame)))
4848 Lisp_Object bar;
4849 bar = FRAME_SCROLL_BARS (frame);
4850 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4851 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4852 XSCROLL_BAR (bar)->prev = Qnil;
4853 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4854 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4855 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4860 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4861 Note that WINDOW isn't necessarily condemned at all. */
4863 static void
4864 XTredeem_scroll_bar (window)
4865 struct window *window;
4867 struct scroll_bar *bar;
4868 struct frame *f;
4870 /* We can't redeem this window's scroll bar if it doesn't have one. */
4871 if (NILP (window->vertical_scroll_bar))
4872 abort ();
4874 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4876 /* Unlink it from the condemned list. */
4877 f = XFRAME (WINDOW_FRAME (window));
4878 if (NILP (bar->prev))
4880 /* If the prev pointer is nil, it must be the first in one of
4881 the lists. */
4882 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4883 /* It's not condemned. Everything's fine. */
4884 return;
4885 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4886 window->vertical_scroll_bar))
4887 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4888 else
4889 /* If its prev pointer is nil, it must be at the front of
4890 one or the other! */
4891 abort ();
4893 else
4894 XSCROLL_BAR (bar->prev)->next = bar->next;
4896 if (! NILP (bar->next))
4897 XSCROLL_BAR (bar->next)->prev = bar->prev;
4899 bar->next = FRAME_SCROLL_BARS (f);
4900 bar->prev = Qnil;
4901 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4902 if (! NILP (bar->next))
4903 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4906 /* Remove all scroll bars on FRAME that haven't been saved since the
4907 last call to `*condemn_scroll_bars_hook'. */
4909 static void
4910 XTjudge_scroll_bars (f)
4911 FRAME_PTR f;
4913 Lisp_Object bar, next;
4915 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4917 /* Clear out the condemned list now so we won't try to process any
4918 more events on the hapless scroll bars. */
4919 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4921 for (; ! NILP (bar); bar = next)
4923 struct scroll_bar *b = XSCROLL_BAR (bar);
4925 x_scroll_bar_remove (b);
4927 next = b->next;
4928 b->next = b->prev = Qnil;
4931 /* Now there should be no references to the condemned scroll bars,
4932 and they should get garbage-collected. */
4935 /* The screen has been cleared so we may have changed foreground or
4936 background colors, and the scroll bars may need to be redrawn.
4937 Clear out the scroll bars, and ask for expose events, so we can
4938 redraw them. */
4940 void
4941 x_scroll_bar_clear (f)
4942 FRAME_PTR f;
4944 Lisp_Object bar;
4946 /* We can have scroll bars even if this is 0,
4947 if we just turned off scroll bar mode.
4948 But in that case we should not clear them. */
4949 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4950 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4951 bar = XSCROLL_BAR (bar)->next)
4952 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
4956 /***********************************************************************
4957 Tool-bars
4958 ***********************************************************************/
4959 #if USE_MAC_TOOLBAR
4960 void
4961 mac_move_window_with_gravity (f, win_gravity, left, top)
4962 struct frame *f;
4963 int win_gravity;
4964 short left, top;
4966 Rect inner, outer;
4968 mac_get_window_bounds (f, &inner, &outer);
4970 switch (win_gravity)
4972 case NorthWestGravity:
4973 case WestGravity:
4974 case SouthWestGravity:
4975 left += inner.left - outer.left;
4976 break;
4978 case NorthGravity:
4979 case CenterGravity:
4980 case SouthGravity:
4981 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
4982 break;
4984 case NorthEastGravity:
4985 case EastGravity:
4986 case SouthEastGravity:
4987 left += inner.right - outer.right;
4988 break;
4991 switch (win_gravity)
4993 case NorthWestGravity:
4994 case NorthGravity:
4995 case NorthEastGravity:
4996 top += inner.top - outer.top;
4997 break;
4999 case WestGravity:
5000 case CenterGravity:
5001 case EastGravity:
5002 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
5003 break;
5005 case SouthWestGravity:
5006 case SouthGravity:
5007 case SouthEastGravity:
5008 top += inner.bottom - outer.bottom;
5009 break;
5012 mac_move_window (FRAME_MAC_WINDOW (f), left, top, false);
5015 void
5016 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
5017 struct frame *f;
5018 int win_gravity;
5019 short *left, *top;
5021 Rect inner, outer;
5023 mac_get_window_bounds (f, &inner, &outer);
5025 switch (win_gravity)
5027 case NorthWestGravity:
5028 case WestGravity:
5029 case SouthWestGravity:
5030 *left = outer.left;
5031 break;
5033 case NorthGravity:
5034 case CenterGravity:
5035 case SouthGravity:
5036 *left = outer.left + ((outer.right - outer.left)
5037 - (inner.right - inner.left)) / 2;
5038 break;
5040 case NorthEastGravity:
5041 case EastGravity:
5042 case SouthEastGravity:
5043 *left = outer.right - (inner.right - inner.left);
5044 break;
5047 switch (win_gravity)
5049 case NorthWestGravity:
5050 case NorthGravity:
5051 case NorthEastGravity:
5052 *top = outer.top;
5053 break;
5055 case WestGravity:
5056 case CenterGravity:
5057 case EastGravity:
5058 *top = outer.top + ((outer.bottom - outer.top)
5059 - (inner.bottom - inner.top)) / 2;
5060 break;
5062 case SouthWestGravity:
5063 case SouthGravity:
5064 case SouthEastGravity:
5065 *top = outer.bottom - (inner.bottom - inner.top);
5066 break;
5070 CGImageRef
5071 mac_image_spec_to_cg_image (f, image)
5072 struct frame *f;
5073 Lisp_Object image;
5075 if (!valid_image_p (image))
5076 return NULL;
5077 else
5079 int img_id = lookup_image (f, image);
5080 struct image *img = IMAGE_FROM_ID (f, img_id);
5082 prepare_image_for_display (f, img);
5084 return img->data.ptr_val;
5087 #endif /* USE_MAC_TOOLBAR */
5090 /***********************************************************************
5091 Text Cursor
5092 ***********************************************************************/
5094 /* Set clipping for output in glyph row ROW. W is the window in which
5095 we operate. GC is the graphics context to set clipping in.
5097 ROW may be a text row or, e.g., a mode line. Text rows must be
5098 clipped to the interior of the window dedicated to text display,
5099 mode lines must be clipped to the whole window. */
5101 static void
5102 x_clip_to_row (w, row, area, gc)
5103 struct window *w;
5104 struct glyph_row *row;
5105 int area;
5106 GC gc;
5108 struct frame *f = XFRAME (WINDOW_FRAME (w));
5109 Rect clip_rect;
5110 int window_x, window_y, window_width;
5112 window_box (w, area, &window_x, &window_y, &window_width, 0);
5114 clip_rect.left = window_x;
5115 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5116 clip_rect.top = max (clip_rect.top, window_y);
5117 clip_rect.right = clip_rect.left + window_width;
5118 clip_rect.bottom = clip_rect.top + row->visible_height;
5120 mac_set_clip_rectangles (f, gc, &clip_rect, 1);
5124 /* Draw a hollow box cursor on window W in glyph row ROW. */
5126 static void
5127 x_draw_hollow_cursor (w, row)
5128 struct window *w;
5129 struct glyph_row *row;
5131 struct frame *f = XFRAME (WINDOW_FRAME (w));
5132 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5133 Display *dpy = FRAME_MAC_DISPLAY (f);
5134 int x, y, wd, h;
5135 XGCValues xgcv;
5136 struct glyph *cursor_glyph;
5137 GC gc;
5139 /* Get the glyph the cursor is on. If we can't tell because
5140 the current matrix is invalid or such, give up. */
5141 cursor_glyph = get_phys_cursor_glyph (w);
5142 if (cursor_glyph == NULL)
5143 return;
5145 /* Compute frame-relative coordinates for phys cursor. */
5146 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5147 wd = w->phys_cursor_width;
5149 /* The foreground of cursor_gc is typically the same as the normal
5150 background color, which can cause the cursor box to be invisible. */
5151 xgcv.foreground = f->output_data.mac->cursor_pixel;
5152 if (dpyinfo->scratch_cursor_gc)
5153 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5154 else
5155 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5156 GCForeground, &xgcv);
5157 gc = dpyinfo->scratch_cursor_gc;
5159 /* Set clipping, draw the rectangle, and reset clipping again. */
5160 x_clip_to_row (w, row, TEXT_AREA, gc);
5161 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5162 mac_reset_clip_rectangles (f, gc);
5166 /* Draw a bar cursor on window W in glyph row ROW.
5168 Implementation note: One would like to draw a bar cursor with an
5169 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5170 Unfortunately, I didn't find a font yet that has this property set.
5171 --gerd. */
5173 static void
5174 x_draw_bar_cursor (w, row, width, kind)
5175 struct window *w;
5176 struct glyph_row *row;
5177 int width;
5178 enum text_cursor_kinds kind;
5180 struct frame *f = XFRAME (w->frame);
5181 struct glyph *cursor_glyph;
5183 /* If cursor is out of bounds, don't draw garbage. This can happen
5184 in mini-buffer windows when switching between echo area glyphs
5185 and mini-buffer. */
5186 cursor_glyph = get_phys_cursor_glyph (w);
5187 if (cursor_glyph == NULL)
5188 return;
5190 /* If on an image, draw like a normal cursor. That's usually better
5191 visible than drawing a bar, esp. if the image is large so that
5192 the bar might not be in the window. */
5193 if (cursor_glyph->type == IMAGE_GLYPH)
5195 struct glyph_row *row;
5196 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5197 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5199 else
5201 Display *dpy = FRAME_MAC_DISPLAY (f);
5202 Window window = FRAME_MAC_WINDOW (f);
5203 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5204 unsigned long mask = GCForeground | GCBackground;
5205 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5206 XGCValues xgcv;
5208 /* If the glyph's background equals the color we normally draw
5209 the bar cursor in, the bar cursor in its normal color is
5210 invisible. Use the glyph's foreground color instead in this
5211 case, on the assumption that the glyph's colors are chosen so
5212 that the glyph is legible. */
5213 if (face->background == f->output_data.mac->cursor_pixel)
5214 xgcv.background = xgcv.foreground = face->foreground;
5215 else
5216 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5218 if (gc)
5219 XChangeGC (dpy, gc, mask, &xgcv);
5220 else
5222 gc = XCreateGC (dpy, window, mask, &xgcv);
5223 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5226 if (width < 0)
5227 width = FRAME_CURSOR_WIDTH (f);
5228 width = min (cursor_glyph->pixel_width, width);
5230 w->phys_cursor_width = width;
5231 x_clip_to_row (w, row, TEXT_AREA, gc);
5233 if (kind == BAR_CURSOR)
5234 mac_fill_rectangle (f, gc,
5235 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5236 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5237 width, row->height);
5238 else
5239 mac_fill_rectangle (f, gc,
5240 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5241 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5242 row->height - width),
5243 cursor_glyph->pixel_width,
5244 width);
5246 mac_reset_clip_rectangles (f, gc);
5251 /* RIF: Define cursor CURSOR on frame F. */
5253 static void
5254 mac_define_frame_cursor (f, cursor)
5255 struct frame *f;
5256 Cursor cursor;
5258 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5260 if (dpyinfo->x_focus_frame == f)
5261 SetThemeCursor (cursor);
5265 /* RIF: Clear area on frame F. */
5267 static void
5268 mac_clear_frame_area (f, x, y, width, height)
5269 struct frame *f;
5270 int x, y, width, height;
5272 mac_clear_area (f, x, y, width, height);
5276 /* RIF: Draw cursor on window W. */
5278 static void
5279 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5280 struct window *w;
5281 struct glyph_row *glyph_row;
5282 int x, y;
5283 int cursor_type, cursor_width;
5284 int on_p, active_p;
5286 if (on_p)
5288 w->phys_cursor_type = cursor_type;
5289 w->phys_cursor_on_p = 1;
5291 if (glyph_row->exact_window_width_line_p
5292 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5294 glyph_row->cursor_in_fringe_p = 1;
5295 draw_fringe_bitmap (w, glyph_row, 0);
5297 else
5298 switch (cursor_type)
5300 case HOLLOW_BOX_CURSOR:
5301 x_draw_hollow_cursor (w, glyph_row);
5302 break;
5304 case FILLED_BOX_CURSOR:
5305 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5306 break;
5308 case BAR_CURSOR:
5309 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5310 break;
5312 case HBAR_CURSOR:
5313 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5314 break;
5316 case NO_CURSOR:
5317 w->phys_cursor_width = 0;
5318 break;
5320 default:
5321 abort ();
5327 /* Icons. */
5329 #if 0 /* MAC_TODO: no icon support yet. */
5331 x_bitmap_icon (f, icon)
5332 struct frame *f;
5333 Lisp_Object icon;
5335 HANDLE hicon;
5337 if (FRAME_W32_WINDOW (f) == 0)
5338 return 1;
5340 if (NILP (icon))
5341 hicon = LoadIcon (hinst, EMACS_CLASS);
5342 else if (STRINGP (icon))
5343 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5344 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5345 else if (SYMBOLP (icon))
5347 LPCTSTR name;
5349 if (EQ (icon, intern ("application")))
5350 name = (LPCTSTR) IDI_APPLICATION;
5351 else if (EQ (icon, intern ("hand")))
5352 name = (LPCTSTR) IDI_HAND;
5353 else if (EQ (icon, intern ("question")))
5354 name = (LPCTSTR) IDI_QUESTION;
5355 else if (EQ (icon, intern ("exclamation")))
5356 name = (LPCTSTR) IDI_EXCLAMATION;
5357 else if (EQ (icon, intern ("asterisk")))
5358 name = (LPCTSTR) IDI_ASTERISK;
5359 else if (EQ (icon, intern ("winlogo")))
5360 name = (LPCTSTR) IDI_WINLOGO;
5361 else
5362 return 1;
5364 hicon = LoadIcon (NULL, name);
5366 else
5367 return 1;
5369 if (hicon == NULL)
5370 return 1;
5372 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5373 (LPARAM) hicon);
5375 return 0;
5377 #endif /* MAC_TODO */
5379 /************************************************************************
5380 Handling X errors
5381 ************************************************************************/
5383 /* Display Error Handling functions not used on W32. Listing them here
5384 helps diff stay in step when comparing w32term.c with xterm.c.
5386 x_error_catcher (display, error)
5387 x_catch_errors (dpy)
5388 x_catch_errors_unwind (old_val)
5389 x_check_errors (dpy, format)
5390 x_had_errors_p (dpy)
5391 x_clear_errors (dpy)
5392 x_uncatch_errors (dpy, count)
5393 x_trace_wire ()
5394 x_connection_signal (signalnum)
5395 x_connection_closed (dpy, error_message)
5396 x_error_quitter (display, error)
5397 x_error_handler (display, error)
5398 x_io_error_quitter (display)
5403 /* Changing the font of the frame. */
5405 /* Give frame F the font named FONTNAME as its default font, and
5406 return the full name of that font. FONTNAME may be a wildcard
5407 pattern; in that case, we choose some font that fits the pattern.
5408 The return value shows which font we chose. */
5410 Lisp_Object
5411 x_new_font (f, fontname)
5412 struct frame *f;
5413 register char *fontname;
5415 struct font_info *fontp
5416 = FS_LOAD_FONT (f, 0, fontname, -1);
5418 if (!fontp)
5419 return Qnil;
5421 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5422 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5423 FRAME_FONTSET (f) = -1;
5425 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5426 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5427 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5429 compute_fringe_widths (f, 1);
5431 /* Compute the scroll bar width in character columns. */
5432 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5434 int wid = FRAME_COLUMN_WIDTH (f);
5435 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5436 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5438 else
5440 int wid = FRAME_COLUMN_WIDTH (f);
5441 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5444 /* Now make the frame display the given font. */
5445 if (FRAME_MAC_WINDOW (f) != 0)
5447 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5448 FRAME_FONT (f));
5449 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5450 FRAME_FONT (f));
5451 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5452 FRAME_FONT (f));
5454 /* Don't change the size of a tip frame; there's no point in
5455 doing it because it's done in Fx_show_tip, and it leads to
5456 problems because the tip frame has no widget. */
5457 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5458 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5461 return build_string (fontp->full_name);
5464 /* Give frame F the fontset named FONTSETNAME as its default font, and
5465 return the full name of that fontset. FONTSETNAME may be a wildcard
5466 pattern; in that case, we choose some fontset that fits the pattern.
5467 The return value shows which fontset we chose. */
5469 Lisp_Object
5470 x_new_fontset (f, fontsetname)
5471 struct frame *f;
5472 char *fontsetname;
5474 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5475 Lisp_Object result;
5477 if (fontset < 0)
5478 return Qnil;
5480 if (FRAME_FONTSET (f) == fontset)
5481 /* This fontset is already set in frame F. There's nothing more
5482 to do. */
5483 return fontset_name (fontset);
5485 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5487 if (!STRINGP (result))
5488 /* Can't load ASCII font. */
5489 return Qnil;
5491 /* Since x_new_font doesn't update any fontset information, do it now. */
5492 FRAME_FONTSET (f) = fontset;
5494 return build_string (fontsetname);
5498 /***********************************************************************
5499 TODO: W32 Input Methods
5500 ***********************************************************************/
5501 /* Listing missing functions from xterm.c helps diff stay in step.
5503 xim_destroy_callback (xim, client_data, call_data)
5504 xim_open_dpy (dpyinfo, resource_name)
5505 struct xim_inst_t
5506 xim_instantiate_callback (display, client_data, call_data)
5507 xim_initialize (dpyinfo, resource_name)
5508 xim_close_dpy (dpyinfo)
5513 void
5514 mac_handle_origin_change (f)
5515 struct frame *f;
5517 x_real_positions (f, &f->left_pos, &f->top_pos);
5520 void
5521 mac_handle_size_change (f, pixelwidth, pixelheight)
5522 struct frame *f;
5523 int pixelwidth, pixelheight;
5525 int cols, rows;
5527 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
5528 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
5530 if (cols != FRAME_COLS (f)
5531 || rows != FRAME_LINES (f)
5532 || pixelwidth != FRAME_PIXEL_WIDTH (f)
5533 || pixelheight != FRAME_PIXEL_HEIGHT (f))
5535 /* We pass 1 for DELAY since we can't run Lisp code inside of
5536 a BLOCK_INPUT. */
5537 change_frame_size (f, rows, cols, 0, 1, 0);
5538 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5539 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5541 /* If cursor was outside the new size, mark it as off. */
5542 mark_window_cursors_off (XWINDOW (f->root_window));
5544 /* Clear out any recollection of where the mouse highlighting
5545 was, since it might be in a place that's outside the new
5546 frame size. Actually checking whether it is outside is a
5547 pain in the neck, so don't try--just let the highlighting be
5548 done afresh with new size. */
5549 cancel_mouse_face (f);
5551 #if TARGET_API_MAC_CARBON
5552 mac_reposition_hourglass (f);
5553 #endif
5558 /* Calculate the absolute position in frame F
5559 from its current recorded position values and gravity. */
5561 void
5562 x_calc_absolute_position (f)
5563 struct frame *f;
5565 int flags = f->size_hint_flags;
5566 Rect inner, outer;
5568 /* We have nothing to do if the current position
5569 is already for the top-left corner. */
5570 if (! ((flags & XNegative) || (flags & YNegative)))
5571 return;
5573 /* Find the offsets of the outside upper-left corner of
5574 the inner window, with respect to the outer window. */
5575 BLOCK_INPUT;
5576 mac_get_window_bounds (f, &inner, &outer);
5577 UNBLOCK_INPUT;
5579 /* Treat negative positions as relative to the leftmost bottommost
5580 position that fits on the screen. */
5581 if (flags & XNegative)
5582 f->left_pos += (FRAME_MAC_DISPLAY_INFO (f)->width
5583 - (outer.right - outer.left));
5585 if (flags & YNegative)
5586 f->top_pos += (FRAME_MAC_DISPLAY_INFO (f)->height
5587 - (outer.bottom - outer.top));
5589 /* The left_pos and top_pos
5590 are now relative to the top and left screen edges,
5591 so the flags should correspond. */
5592 f->size_hint_flags &= ~ (XNegative | YNegative);
5595 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5596 to really change the position, and 0 when calling from
5597 x_make_frame_visible (in that case, XOFF and YOFF are the current
5598 position values). It is -1 when calling from x_set_frame_parameters,
5599 which means, do adjust for borders but don't change the gravity. */
5601 void
5602 x_set_offset (f, xoff, yoff, change_gravity)
5603 struct frame *f;
5604 register int xoff, yoff;
5605 int change_gravity;
5607 if (change_gravity > 0)
5609 f->top_pos = yoff;
5610 f->left_pos = xoff;
5611 f->size_hint_flags &= ~ (XNegative | YNegative);
5612 if (xoff < 0)
5613 f->size_hint_flags |= XNegative;
5614 if (yoff < 0)
5615 f->size_hint_flags |= YNegative;
5616 f->win_gravity = NorthWestGravity;
5618 x_calc_absolute_position (f);
5620 BLOCK_INPUT;
5621 x_wm_set_size_hint (f, (long) 0, 0);
5623 #if TARGET_API_MAC_CARBON
5624 mac_move_window_structure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5625 /* If the title bar is completely outside the screen, adjust the
5626 position. */
5627 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5628 kWindowConstrainMoveRegardlessOfFit
5629 | kWindowConstrainAllowPartial, NULL, NULL);
5630 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
5631 mac_handle_origin_change (f);
5632 #else
5634 Rect inner, outer, screen_rect, dummy;
5635 RgnHandle region = NewRgn ();
5637 mac_get_window_bounds (f, &inner, &outer);
5638 f->x_pixels_diff = inner.left - outer.left;
5639 f->y_pixels_diff = inner.top - outer.top;
5640 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5641 f->top_pos + f->y_pixels_diff, false);
5643 /* If the title bar is completely outside the screen, adjust the
5644 position. The variable `outer' holds the title bar rectangle.
5645 The variable `inner' holds slightly smaller one than `outer',
5646 so that the calculation of overlapping may not become too
5647 strict. */
5648 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5649 outer = (*region)->rgnBBox;
5650 DisposeRgn (region);
5651 inner = outer;
5652 InsetRect (&inner, 8, 8);
5653 screen_rect = qd.screenBits.bounds;
5654 screen_rect.top += GetMBarHeight ();
5656 if (!SectRect (&inner, &screen_rect, &dummy))
5658 if (inner.right <= screen_rect.left)
5659 f->left_pos = screen_rect.left;
5660 else if (inner.left >= screen_rect.right)
5661 f->left_pos = screen_rect.right - (outer.right - outer.left);
5663 if (inner.bottom <= screen_rect.top)
5664 f->top_pos = screen_rect.top;
5665 else if (inner.top >= screen_rect.bottom)
5666 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5668 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5669 f->top_pos + f->y_pixels_diff, false);
5672 #endif
5674 UNBLOCK_INPUT;
5677 /* Call this to change the size of frame F's x-window.
5678 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5679 for this size change and subsequent size changes.
5680 Otherwise we leave the window gravity unchanged. */
5682 void
5683 x_set_window_size (f, change_gravity, cols, rows)
5684 struct frame *f;
5685 int change_gravity;
5686 int cols, rows;
5688 int pixelwidth, pixelheight;
5690 BLOCK_INPUT;
5692 check_frame_size (f, &rows, &cols);
5693 f->scroll_bar_actual_width
5694 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5696 compute_fringe_widths (f, 0);
5698 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5699 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5701 f->win_gravity = NorthWestGravity;
5702 x_wm_set_size_hint (f, (long) 0, 0);
5704 mac_size_window (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5706 #if TARGET_API_MAC_CARBON
5707 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
5708 #endif
5709 mac_handle_size_change (f, pixelwidth, pixelheight);
5711 if (f->output_data.mac->internal_border_width
5712 != FRAME_INTERNAL_BORDER_WIDTH (f))
5714 mac_clear_window (f);
5715 f->output_data.mac->internal_border_width
5716 = FRAME_INTERNAL_BORDER_WIDTH (f);
5719 SET_FRAME_GARBAGED (f);
5721 UNBLOCK_INPUT;
5724 /* Mouse warping. */
5726 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5728 void
5729 x_set_mouse_position (f, x, y)
5730 struct frame *f;
5731 int x, y;
5733 int pix_x, pix_y;
5735 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5736 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5738 if (pix_x < 0) pix_x = 0;
5739 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5741 if (pix_y < 0) pix_y = 0;
5742 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5744 x_set_mouse_pixel_position (f, pix_x, pix_y);
5747 void
5748 x_set_mouse_pixel_position (f, pix_x, pix_y)
5749 struct frame *f;
5750 int pix_x, pix_y;
5752 #ifdef MAC_OSX
5753 BLOCK_INPUT;
5754 mac_convert_frame_point_to_global (f, &pix_x, &pix_y);
5755 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
5756 UNBLOCK_INPUT;
5757 #else
5758 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
5759 BLOCK_INPUT;
5761 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5762 0, 0, 0, 0, pix_x, pix_y);
5763 UNBLOCK_INPUT;
5764 #endif
5765 #endif
5768 /* focus shifting, raising and lowering. */
5770 void
5771 x_focus_on_frame (f)
5772 struct frame *f;
5774 #if 0 /* This proves to be unpleasant. */
5775 x_raise_frame (f);
5776 #endif
5777 #if 0
5778 /* I don't think that the ICCCM allows programs to do things like this
5779 without the interaction of the window manager. Whatever you end up
5780 doing with this code, do it to x_unfocus_frame too. */
5781 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5782 RevertToPointerRoot, CurrentTime);
5783 #endif /* ! 0 */
5786 void
5787 x_unfocus_frame (f)
5788 struct frame *f;
5792 /* Raise frame F. */
5794 void
5795 x_raise_frame (f)
5796 struct frame *f;
5798 if (f->async_visible)
5800 BLOCK_INPUT;
5801 mac_bring_window_to_front (FRAME_MAC_WINDOW (f));
5802 UNBLOCK_INPUT;
5806 /* Lower frame F. */
5808 void
5809 x_lower_frame (f)
5810 struct frame *f;
5812 if (f->async_visible)
5814 BLOCK_INPUT;
5815 mac_send_window_behind (FRAME_MAC_WINDOW (f), NULL);
5816 UNBLOCK_INPUT;
5820 static void
5821 XTframe_raise_lower (f, raise_flag)
5822 FRAME_PTR f;
5823 int raise_flag;
5825 if (raise_flag)
5826 x_raise_frame (f);
5827 else
5828 x_lower_frame (f);
5831 /* Change of visibility. */
5833 void
5834 mac_handle_visibility_change (f)
5835 struct frame *f;
5837 Window wp = FRAME_MAC_WINDOW (f);
5838 int visible = 0, iconified = 0;
5839 struct input_event buf;
5841 if (mac_is_window_visible (wp))
5843 if (mac_is_window_collapsed (wp))
5844 iconified = 1;
5845 else
5846 visible = 1;
5849 if (!f->async_visible && visible)
5851 if (f->iconified)
5853 /* wait_reading_process_output will notice this and update
5854 the frame's display structures. If we were made
5855 invisible, we should not set garbaged, because that stops
5856 redrawing on Update events. */
5857 SET_FRAME_GARBAGED (f);
5859 EVENT_INIT (buf);
5860 buf.kind = DEICONIFY_EVENT;
5861 XSETFRAME (buf.frame_or_window, f);
5862 buf.arg = Qnil;
5863 kbd_buffer_store_event (&buf);
5865 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
5866 /* Force a redisplay sooner or later to update the
5867 frame titles in case this is the second frame. */
5868 record_asynch_buffer_change ();
5870 else if (f->async_visible && !visible)
5871 if (iconified)
5873 EVENT_INIT (buf);
5874 buf.kind = ICONIFY_EVENT;
5875 XSETFRAME (buf.frame_or_window, f);
5876 buf.arg = Qnil;
5877 kbd_buffer_store_event (&buf);
5880 f->async_visible = visible;
5881 f->async_iconified = iconified;
5884 /* This tries to wait until the frame is really visible.
5885 However, if the window manager asks the user where to position
5886 the frame, this will return before the user finishes doing that.
5887 The frame will not actually be visible at that time,
5888 but it will become visible later when the window manager
5889 finishes with it. */
5891 void
5892 x_make_frame_visible (f)
5893 struct frame *f;
5895 BLOCK_INPUT;
5897 if (! FRAME_VISIBLE_P (f))
5899 /* We test FRAME_GARBAGED_P here to make sure we don't
5900 call x_set_offset a second time
5901 if we get to x_make_frame_visible a second time
5902 before the window gets really visible. */
5903 if (! FRAME_ICONIFIED_P (f)
5904 && ! f->output_data.mac->asked_for_visible)
5905 x_set_offset (f, f->left_pos, f->top_pos, 0);
5907 f->output_data.mac->asked_for_visible = 1;
5909 mac_collapse_window (FRAME_MAC_WINDOW (f), false);
5910 mac_show_window (FRAME_MAC_WINDOW (f));
5913 XFlush (FRAME_MAC_DISPLAY (f));
5915 /* Synchronize to ensure Emacs knows the frame is visible
5916 before we do anything else. We do this loop with input not blocked
5917 so that incoming events are handled. */
5919 Lisp_Object frame;
5920 int count;
5922 /* This must come after we set COUNT. */
5923 UNBLOCK_INPUT;
5925 XSETFRAME (frame, f);
5927 /* Wait until the frame is visible. Process X events until a
5928 MapNotify event has been seen, or until we think we won't get a
5929 MapNotify at all.. */
5930 for (count = input_signal_count + 10;
5931 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5933 /* Force processing of queued events. */
5934 x_sync (f);
5936 /* Machines that do polling rather than SIGIO have been
5937 observed to go into a busy-wait here. So we'll fake an
5938 alarm signal to let the handler know that there's something
5939 to be read. We used to raise a real alarm, but it seems
5940 that the handler isn't always enabled here. This is
5941 probably a bug. */
5942 if (input_polling_used ())
5944 /* It could be confusing if a real alarm arrives while
5945 processing the fake one. Turn it off and let the
5946 handler reset it. */
5947 extern void poll_for_input_1 P_ ((void));
5948 int old_poll_suppress_count = poll_suppress_count;
5949 poll_suppress_count = 1;
5950 poll_for_input_1 ();
5951 poll_suppress_count = old_poll_suppress_count;
5954 /* See if a MapNotify event has been processed. */
5955 FRAME_SAMPLE_VISIBILITY (f);
5960 /* Change from mapped state to withdrawn state. */
5962 /* Make the frame visible (mapped and not iconified). */
5964 void
5965 x_make_frame_invisible (f)
5966 struct frame *f;
5968 /* A deactivate event does not occur when the last visible frame is
5969 made invisible. So if we clear the highlight here, it will not
5970 be rehighlighted when it is made visible. */
5971 #if 0
5972 /* Don't keep the highlight on an invisible frame. */
5973 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5974 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5975 #endif
5977 BLOCK_INPUT;
5979 #if !TARGET_API_MAC_CARBON
5980 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5981 that the current position of the window is user-specified, rather than
5982 program-specified, so that when the window is mapped again, it will be
5983 placed at the same location, without forcing the user to position it
5984 by hand again (they have already done that once for this window.) */
5985 x_wm_set_size_hint (f, (long) 0, 1);
5986 #endif
5988 mac_hide_window (FRAME_MAC_WINDOW (f));
5990 UNBLOCK_INPUT;
5992 #if !TARGET_API_MAC_CARBON
5993 mac_handle_visibility_change (f);
5994 #endif
5997 /* Change window state from mapped to iconified. */
5999 void
6000 x_iconify_frame (f)
6001 struct frame *f;
6003 OSStatus err;
6005 /* A deactivate event does not occur when the last visible frame is
6006 iconified. So if we clear the highlight here, it will not be
6007 rehighlighted when it is deiconified. */
6008 #if 0
6009 /* Don't keep the highlight on an invisible frame. */
6010 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6011 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6012 #endif
6014 if (f->async_iconified)
6015 return;
6017 BLOCK_INPUT;
6019 FRAME_SAMPLE_VISIBILITY (f);
6021 if (! FRAME_VISIBLE_P (f))
6022 mac_show_window (FRAME_MAC_WINDOW (f));
6024 err = mac_collapse_window (FRAME_MAC_WINDOW (f), true);
6026 UNBLOCK_INPUT;
6028 if (err != noErr)
6029 error ("Can't notify window manager of iconification");
6031 #if !TARGET_API_MAC_CARBON
6032 mac_handle_visibility_change (f);
6033 #endif
6037 /* Free X resources of frame F. */
6039 void
6040 x_free_frame_resources (f)
6041 struct frame *f;
6043 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6044 Window wp = FRAME_MAC_WINDOW (f);
6046 BLOCK_INPUT;
6048 /* AppKit version of mac_dispose_frame_window, which is implemented
6049 as -[NSWindow close], will change the focus to the next window
6050 during its call. So, unlike other platforms, we clean up the
6051 focus-related variables before calling mac_dispose_frame_window. */
6052 if (f == dpyinfo->x_focus_frame)
6054 dpyinfo->x_focus_frame = 0;
6055 #if USE_MAC_FONT_PANEL
6056 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6057 #endif
6059 if (f == dpyinfo->x_focus_event_frame)
6060 dpyinfo->x_focus_event_frame = 0;
6061 if (f == dpyinfo->x_highlight_frame)
6062 dpyinfo->x_highlight_frame = 0;
6064 if (f == dpyinfo->mouse_face_mouse_frame)
6066 dpyinfo->mouse_face_beg_row
6067 = dpyinfo->mouse_face_beg_col = -1;
6068 dpyinfo->mouse_face_end_row
6069 = dpyinfo->mouse_face_end_col = -1;
6070 dpyinfo->mouse_face_window = Qnil;
6071 dpyinfo->mouse_face_deferred_gc = 0;
6072 dpyinfo->mouse_face_mouse_frame = 0;
6075 mac_dispose_frame_window (f);
6076 if (wp == tip_window)
6077 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6078 closed' event. So we reset tip_window here. */
6079 tip_window = NULL;
6081 free_frame_menubar (f);
6083 if (FRAME_FACE_CACHE (f))
6084 free_frame_faces (f);
6086 x_free_gcs (f);
6088 if (FRAME_SIZE_HINTS (f))
6089 xfree (FRAME_SIZE_HINTS (f));
6091 xfree (f->output_data.mac);
6092 f->output_data.mac = NULL;
6094 UNBLOCK_INPUT;
6098 /* Destroy the X window of frame F. */
6100 void
6101 x_destroy_window (f)
6102 struct frame *f;
6104 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6106 x_free_frame_resources (f);
6108 dpyinfo->reference_count--;
6112 /* Setting window manager hints. */
6114 /* Set the normal size hints for the window manager, for frame F.
6115 FLAGS is the flags word to use--or 0 meaning preserve the flags
6116 that the window now has.
6117 If USER_POSITION is nonzero, we set the USPosition
6118 flag (this is useful when FLAGS is 0). */
6119 void
6120 x_wm_set_size_hint (f, flags, user_position)
6121 struct frame *f;
6122 long flags;
6123 int user_position;
6125 int base_width, base_height, width_inc, height_inc;
6126 int min_rows = 0, min_cols = 0;
6127 XSizeHints *size_hints;
6129 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6130 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6131 width_inc = FRAME_COLUMN_WIDTH (f);
6132 height_inc = FRAME_LINE_HEIGHT (f);
6134 check_frame_size (f, &min_rows, &min_cols);
6136 size_hints = FRAME_SIZE_HINTS (f);
6137 if (size_hints == NULL)
6139 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6140 bzero (size_hints, sizeof (XSizeHints));
6143 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6144 size_hints->width_inc = width_inc;
6145 size_hints->height_inc = height_inc;
6146 size_hints->min_width = base_width + min_cols * width_inc;
6147 size_hints->min_height = base_height + min_rows * height_inc;
6148 size_hints->base_width = base_width;
6149 size_hints->base_height = base_height;
6151 if (flags)
6152 size_hints->flags = flags;
6153 else if (user_position)
6155 size_hints->flags &= ~ PPosition;
6156 size_hints->flags |= USPosition;
6160 #if 0 /* MAC_TODO: hide application instead of iconify? */
6161 /* Used for IconicState or NormalState */
6163 void
6164 x_wm_set_window_state (f, state)
6165 struct frame *f;
6166 int state;
6168 #ifdef USE_X_TOOLKIT
6169 Arg al[1];
6171 XtSetArg (al[0], XtNinitialState, state);
6172 XtSetValues (f->output_data.x->widget, al, 1);
6173 #else /* not USE_X_TOOLKIT */
6174 Window window = FRAME_X_WINDOW (f);
6176 f->output_data.x->wm_hints.flags |= StateHint;
6177 f->output_data.x->wm_hints.initial_state = state;
6179 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6180 #endif /* not USE_X_TOOLKIT */
6183 void
6184 x_wm_set_icon_pixmap (f, pixmap_id)
6185 struct frame *f;
6186 int pixmap_id;
6188 Pixmap icon_pixmap;
6190 #ifndef USE_X_TOOLKIT
6191 Window window = FRAME_X_WINDOW (f);
6192 #endif
6194 if (pixmap_id > 0)
6196 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6197 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6199 else
6201 /* It seems there is no way to turn off use of an icon pixmap.
6202 The following line does it, only if no icon has yet been created,
6203 for some window managers. But with mwm it crashes.
6204 Some people say it should clear the IconPixmapHint bit in this case,
6205 but that doesn't work, and the X consortium said it isn't the
6206 right thing at all. Since there is no way to win,
6207 best to explicitly give up. */
6208 #if 0
6209 f->output_data.x->wm_hints.icon_pixmap = None;
6210 #else
6211 return;
6212 #endif
6215 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6218 Arg al[1];
6219 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6220 XtSetValues (f->output_data.x->widget, al, 1);
6223 #else /* not USE_X_TOOLKIT */
6225 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6226 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6228 #endif /* not USE_X_TOOLKIT */
6231 #endif /* MAC_TODO */
6233 void
6234 x_wm_set_icon_position (f, icon_x, icon_y)
6235 struct frame *f;
6236 int icon_x, icon_y;
6238 #if 0 /* MAC_TODO: no icons on Mac */
6239 #ifdef USE_X_TOOLKIT
6240 Window window = XtWindow (f->output_data.x->widget);
6241 #else
6242 Window window = FRAME_X_WINDOW (f);
6243 #endif
6245 f->output_data.x->wm_hints.flags |= IconPositionHint;
6246 f->output_data.x->wm_hints.icon_x = icon_x;
6247 f->output_data.x->wm_hints.icon_y = icon_y;
6249 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6250 #endif /* MAC_TODO */
6254 /***********************************************************************
6255 XLFD Pattern Match
6256 ***********************************************************************/
6258 /* An XLFD pattern is divided into blocks delimited by '*'. This
6259 structure holds information for each block. */
6260 struct xlfdpat_block
6262 /* Length of the pattern string in this block. Non-zero except for
6263 the first and the last blocks. */
6264 int len;
6266 /* Pattern string except the last character in this block. The last
6267 character is replaced with NUL in order to use it as a
6268 sentinel. */
6269 unsigned char *pattern;
6271 /* Last character of the pattern string. Must not be '?'. */
6272 unsigned char last_char;
6274 /* One of the tables for the Boyer-Moore string search. It
6275 specifies the number of positions to proceed for each character
6276 with which the match fails. */
6277 int skip[256];
6279 /* The skip value for the last character in the above `skip' is
6280 assigned to `infinity' in order to simplify a loop condition.
6281 The original value is saved here. */
6282 int last_char_skip;
6285 struct xlfdpat
6287 /* Normalized pattern string. "Normalized" means that capital
6288 letters are lowered, blocks are not empty except the first and
6289 the last ones, and trailing '?'s in a block that is not the last
6290 one are moved to the next one. The last character in each block
6291 is replaced with NUL. */
6292 unsigned char *buf;
6294 /* Number of characters except '*'s and trailing '?'s in the
6295 normalized pattern string. */
6296 int nchars;
6298 /* Number of trailing '?'s in the normalized pattern string. */
6299 int trailing_anychars;
6301 /* Number of blocks and information for each block. The latter is
6302 NULL if the pattern is exact (no '*' or '?' in it). */
6303 int nblocks;
6304 struct xlfdpat_block *blocks;
6307 static void
6308 xlfdpat_destroy (pat)
6309 struct xlfdpat *pat;
6311 if (pat)
6313 if (pat->buf)
6315 if (pat->blocks)
6316 xfree (pat->blocks);
6317 xfree (pat->buf);
6319 xfree (pat);
6323 static struct xlfdpat *
6324 xlfdpat_create (pattern)
6325 const char *pattern;
6327 struct xlfdpat *pat;
6328 int nblocks, i, skip;
6329 unsigned char last_char, *p, *q, *anychar_head;
6330 const unsigned char *ptr;
6331 struct xlfdpat_block *blk;
6333 pat = xmalloc (sizeof (struct xlfdpat));
6334 pat->buf = xmalloc (strlen (pattern) + 1);
6336 /* Normalize the pattern string and store it to `pat->buf'. */
6337 nblocks = 0;
6338 anychar_head = NULL;
6339 q = pat->buf;
6340 last_char = '\0';
6341 for (ptr = pattern; *ptr; ptr++)
6343 unsigned char c = *ptr;
6345 if (c == '*')
6346 if (last_char == '*')
6347 /* ...a** -> ...a* */
6348 continue;
6349 else
6351 if (last_char == '?')
6353 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6354 /* ...*??* -> ...*?? */
6355 continue;
6356 else
6357 /* ...a??* -> ...a*?? */
6359 *anychar_head++ = '*';
6360 c = '?';
6363 nblocks++;
6365 else if (c == '?')
6367 if (last_char != '?')
6368 anychar_head = q;
6370 else
6371 /* On Mac OS X 10.3, tolower also converts non-ASCII
6372 characters for some locales. */
6373 if (isascii (c))
6374 c = tolower (c);
6376 *q++ = last_char = c;
6378 *q = '\0';
6379 nblocks++;
6380 pat->nblocks = nblocks;
6381 if (last_char != '?')
6382 pat->trailing_anychars = 0;
6383 else
6385 pat->trailing_anychars = q - anychar_head;
6386 q = anychar_head;
6388 pat->nchars = q - pat->buf - (nblocks - 1);
6390 if (anychar_head == NULL && nblocks == 1)
6392 /* The pattern is exact. */
6393 pat->blocks = NULL;
6394 return pat;
6397 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6399 /* Divide the normalized pattern into blocks. */
6400 p = pat->buf;
6401 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6403 blk->pattern = p;
6404 while (*p != '*')
6405 p++;
6406 blk->len = p - blk->pattern;
6407 p++;
6409 blk->pattern = p;
6410 blk->len = q - blk->pattern;
6412 /* Setup a table for the Boyer-Moore string search. */
6413 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6414 if (blk->len != 0)
6416 blk->last_char = blk->pattern[blk->len - 1];
6417 blk->pattern[blk->len - 1] = '\0';
6419 for (skip = 1; skip < blk->len; skip++)
6420 if (blk->pattern[blk->len - skip - 1] == '?')
6421 break;
6423 for (i = 0; i < 256; i++)
6424 blk->skip[i] = skip;
6426 p = blk->pattern + (blk->len - skip);
6427 while (--skip > 0)
6428 blk->skip[*p++] = skip;
6430 blk->last_char_skip = blk->skip[blk->last_char];
6433 return pat;
6436 static INLINE int
6437 xlfdpat_exact_p (pat)
6438 struct xlfdpat *pat;
6440 return pat->blocks == NULL;
6443 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6444 that the pattern in *BLK matches with its prefix. Return NULL
6445 there is no such strings. STRING must be lowered in advance. */
6447 static const char *
6448 xlfdpat_block_match_1 (blk, string, start_max)
6449 struct xlfdpat_block *blk;
6450 const unsigned char *string;
6451 int start_max;
6453 int start, infinity;
6454 unsigned char *p;
6455 const unsigned char *s;
6457 xassert (blk->len > 0);
6458 xassert (start_max + blk->len <= strlen (string));
6459 xassert (blk->last_char != '?');
6461 /* See the comments in the function `boyer_moore' (search.c) for the
6462 use of `infinity'. */
6463 infinity = start_max + blk->len + 1;
6464 blk->skip[blk->last_char] = infinity;
6466 start = 0;
6469 /* Check the last character of the pattern. */
6470 s = string + blk->len - 1;
6473 start += blk->skip[*(s + start)];
6475 while (start <= start_max);
6477 if (start < infinity)
6478 /* Couldn't find the last character. */
6479 return NULL;
6481 /* No less than `infinity' means we could find the last
6482 character at `s[start - infinity]'. */
6483 start -= infinity;
6485 /* Check the remaining characters. We prefer making no-'?'
6486 cases faster because the use of '?' is really rare. */
6487 p = blk->pattern;
6488 s = string + start;
6491 while (*p++ == *s++)
6494 while (*(p - 1) == '?');
6496 if (*(p - 1) == '\0')
6497 /* Matched. */
6498 return string + start;
6500 /* Didn't match. */
6501 start += blk->last_char_skip;
6503 while (start <= start_max);
6505 return NULL;
6508 #define xlfdpat_block_match(b, s, m) \
6509 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6510 : xlfdpat_block_match_1 (b, s, m))
6512 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
6513 matches with STRING. STRING must be lowered in advance. */
6515 static int
6516 xlfdpat_match (pat, string)
6517 struct xlfdpat *pat;
6518 const unsigned char *string;
6520 int str_len, nblocks, i, start_max;
6521 struct xlfdpat_block *blk;
6522 const unsigned char *s;
6524 xassert (pat->nblocks > 0);
6526 if (xlfdpat_exact_p (pat))
6527 return strcmp (pat->buf, string) == 0;
6529 /* The number of the characters in the string must not be smaller
6530 than that in the pattern. */
6531 str_len = strlen (string);
6532 if (str_len < pat->nchars + pat->trailing_anychars)
6533 return 0;
6535 /* Chop off the trailing '?'s. */
6536 str_len -= pat->trailing_anychars;
6538 /* The last block. When it is non-empty, it must match at the end
6539 of the string. */
6540 nblocks = pat->nblocks;
6541 blk = pat->blocks + (nblocks - 1);
6542 if (nblocks == 1)
6543 /* The last block is also the first one. */
6544 return (str_len == blk->len
6545 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6546 else if (blk->len != 0)
6547 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6548 return 0;
6550 /* The first block. When it is non-empty, it must match at the
6551 beginning of the string. */
6552 blk = pat->blocks;
6553 if (blk->len != 0)
6555 s = xlfdpat_block_match (blk, string, 0);
6556 if (s == NULL)
6557 return 0;
6558 string = s + blk->len;
6561 /* The rest of the blocks. */
6562 start_max = str_len - pat->nchars;
6563 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6565 s = xlfdpat_block_match (blk, string, start_max);
6566 if (s == NULL)
6567 return 0;
6568 start_max -= s - string;
6569 string = s + blk->len;
6572 return 1;
6576 /***********************************************************************
6577 Fonts
6578 ***********************************************************************/
6580 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6582 struct font_info *
6583 x_get_font_info (f, font_idx)
6584 FRAME_PTR f;
6585 int font_idx;
6587 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6590 /* the global font name table */
6591 static char **font_name_table = NULL;
6592 static int font_name_table_size = 0;
6593 static int font_name_count = 0;
6595 /* Alist linking font family names to Font Manager font family
6596 references (which can also be used as QuickDraw font IDs). We use
6597 an alist because hash tables are not ready when the terminal frame
6598 for Mac OS Classic is created. */
6599 static Lisp_Object fm_font_family_alist;
6600 #if USE_ATSUI
6601 /* Hash table linking font family names to ATSU font IDs. */
6602 static Lisp_Object atsu_font_id_hash;
6603 /* Alist linking Font Manager style to face attributes. */
6604 static Lisp_Object fm_style_face_attributes_alist;
6605 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
6606 #endif
6607 #if USE_MAC_FONT_PANEL
6608 Lisp_Object Qpanel_closed, Qselection;
6609 #endif
6611 /* Alist linking character set strings to Mac text encoding and Emacs
6612 coding system. */
6613 static Lisp_Object Vmac_charset_info_alist;
6615 static Lisp_Object
6616 create_text_encoding_info_alist ()
6618 Lisp_Object result = Qnil, rest;
6620 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6622 Lisp_Object charset_info = XCAR (rest);
6623 Lisp_Object charset, coding_system, text_encoding;
6624 Lisp_Object existing_info;
6626 if (!(CONSP (charset_info)
6627 && (charset = XCAR (charset_info),
6628 STRINGP (charset))
6629 && CONSP (XCDR (charset_info))
6630 && (text_encoding = XCAR (XCDR (charset_info)),
6631 INTEGERP (text_encoding))
6632 && CONSP (XCDR (XCDR (charset_info)))
6633 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
6634 SYMBOLP (coding_system))))
6635 continue;
6637 existing_info = assq_no_quit (text_encoding, result);
6638 if (NILP (existing_info))
6639 result = Fcons (list3 (text_encoding, coding_system, charset),
6640 result);
6641 else
6642 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6643 XSETCDR (XCDR (existing_info),
6644 Fcons (charset, XCDR (XCDR (existing_info))));
6647 return result;
6651 static void
6652 decode_mac_font_name (name, size, coding_system)
6653 char *name;
6654 int size;
6655 Lisp_Object coding_system;
6657 struct coding_system coding;
6658 char *buf, *p;
6660 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6662 for (p = name; *p; p++)
6663 if (!isascii (*p) || iscntrl (*p))
6664 break;
6666 if (*p)
6668 setup_coding_system (coding_system, &coding);
6669 coding.src_multibyte = 0;
6670 coding.dst_multibyte = 1;
6671 coding.mode |= CODING_MODE_LAST_BLOCK;
6672 coding.composing = COMPOSITION_DISABLED;
6673 buf = (char *) alloca (size);
6675 decode_coding (&coding, name, buf, strlen (name), size - 1);
6676 bcopy (buf, name, coding.produced);
6677 name[coding.produced] = '\0';
6681 /* If there's just one occurrence of '-' in the family name, it is
6682 replaced with '_'. (More than one occurrence of '-' means a
6683 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6684 p = strchr (name, '-');
6685 if (p && strchr (p + 1, '-') == NULL)
6686 *p = '_';
6688 for (p = name; *p; p++)
6689 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6690 for some locales. */
6691 if (isascii (*p))
6692 *p = tolower (*p);
6696 static char *
6697 mac_to_x_fontname (name, size, style, charset)
6698 const char *name;
6699 int size;
6700 Style style;
6701 char *charset;
6703 Str31 foundry, cs;
6704 Str255 family;
6705 char xf[256], *result;
6706 unsigned char *p;
6708 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6709 charset = cs;
6710 else
6712 strcpy(foundry, "Apple");
6713 strcpy(family, name);
6716 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6717 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
6718 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
6720 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6721 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6722 for (p = result; *p; p++)
6723 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6724 for some locales. */
6725 if (isascii (*p))
6726 *p = tolower (*p);
6727 return result;
6731 /* Parse fully-specified and instantiated X11 font spec XF, and store
6732 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6733 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6734 caller must allocate at least 256 and 32 bytes respectively. For
6735 ordinary Mac fonts, the value stored to FAMILY should just be their
6736 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6737 intlfonts collection contain their charset designation in their
6738 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6739 types of font names are handled accordingly. */
6741 const int kDefaultFontSize = 12;
6743 static int
6744 parse_x_font_name (xf, family, size, style, charset)
6745 const char *xf;
6746 char *family;
6747 int *size;
6748 Style *style;
6749 char *charset;
6751 Str31 foundry, weight;
6752 int point_size, avgwidth;
6753 char slant[2], *p;
6755 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6756 foundry, family, weight, slant, size,
6757 &point_size, &avgwidth, charset) != 8
6758 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6759 foundry, family, weight, slant, size,
6760 &point_size, &avgwidth, charset) != 8)
6761 return 0;
6763 if (*size == 0)
6765 if (point_size > 0)
6766 *size = point_size / 10;
6767 else if (avgwidth > 0)
6768 *size = avgwidth / 10;
6770 if (*size == 0)
6771 *size = kDefaultFontSize;
6773 *style = normal;
6774 if (strcmp (weight, "bold") == 0)
6775 *style |= bold;
6776 if (*slant == 'i')
6777 *style |= italic;
6779 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
6781 int foundry_len = strlen (foundry), family_len = strlen (family);
6783 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
6785 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6786 but take overlap into account. */
6787 memmove (family + foundry_len + 1, family, family_len);
6788 memcpy (family, foundry, foundry_len);
6789 family[foundry_len] = '-';
6790 family[foundry_len + 1 + family_len] = '-';
6791 strcpy (family + foundry_len + 1 + family_len + 1, charset);
6793 else
6794 return 0;
6797 for (p = family; *p; p++)
6798 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6799 for some locales. */
6800 if (isascii (*p))
6801 *p = tolower (*p);
6803 return 1;
6807 static void
6808 add_font_name_table_entry (char *font_name)
6810 if (font_name_table_size == 0)
6812 font_name_table_size = 256;
6813 font_name_table = (char **)
6814 xmalloc (font_name_table_size * sizeof (char *));
6816 else if (font_name_count + 1 >= font_name_table_size)
6818 font_name_table_size *= 2;
6819 font_name_table = (char **)
6820 xrealloc (font_name_table,
6821 font_name_table_size * sizeof (char *));
6824 font_name_table[font_name_count++] = font_name;
6827 static void
6828 add_mac_font_name (name, size, style, charset)
6829 const char *name;
6830 int size;
6831 Style style;
6832 const char *charset;
6834 if (size > 0)
6835 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
6836 else
6838 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
6839 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
6840 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
6841 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
6842 charset));
6846 #if USE_ATSUI
6847 static FMFontStyle
6848 fm_get_style_from_font (font)
6849 FMFont font;
6851 OSStatus err;
6852 FMFontStyle style = normal;
6853 ByteCount len;
6854 UInt16 mac_style;
6855 FMFontFamily font_family;
6856 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
6858 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
6859 some font (e.g., Optima) even if it is `bold'. */
6860 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
6861 sizeof (mac_style), &mac_style, &len);
6862 if (err == noErr
6863 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
6864 style = EndianU16_BtoN (mac_style);
6865 else
6866 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
6868 return style;
6871 static ATSUFontID
6872 atsu_find_font_from_family_name (family)
6873 const char *family;
6875 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
6876 unsigned hash_code;
6877 int i;
6878 Lisp_Object rest, best;
6879 FMFontStyle min_style, style;
6881 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
6882 &hash_code);
6883 if (i < 0)
6884 return kATSUInvalidFontID;
6886 rest = HASH_VALUE (h, i);
6887 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
6888 return cons_to_long (rest);
6890 rest = Fnreverse (rest);
6891 best = XCAR (rest);
6892 rest = XCDR (rest);
6893 if (!NILP (rest)
6894 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
6897 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
6898 if (style < min_style)
6900 best = XCAR (rest);
6901 if (style == normal)
6902 break;
6903 else
6904 min_style = style;
6906 rest = XCDR (rest);
6908 while (!NILP (rest));
6910 HASH_VALUE (h, i) = best;
6911 return cons_to_long (best);
6914 static Lisp_Object
6915 fm_style_to_face_attributes (fm_style)
6916 FMFontStyle fm_style;
6918 Lisp_Object tem;
6920 fm_style &= (bold | italic);
6921 tem = assq_no_quit (make_number (fm_style),
6922 fm_style_face_attributes_alist);
6923 if (!NILP (tem))
6924 return XCDR (tem);
6926 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
6927 QCslant, fm_style & italic ? Qitalic : Qnormal);
6928 fm_style_face_attributes_alist =
6929 Fcons (Fcons (make_number (fm_style), tem),
6930 fm_style_face_attributes_alist);
6932 return tem;
6935 static Lisp_Object
6936 atsu_find_font_family_name (font_id)
6937 ATSUFontID font_id;
6939 OSStatus err;
6940 ByteCount len;
6941 Lisp_Object family = Qnil;
6943 err = ATSUFindFontName (font_id, kFontFamilyName,
6944 kFontMacintoshPlatform, kFontNoScript,
6945 kFontNoLanguage, 0, NULL, &len, NULL);
6946 if (err == noErr)
6948 family = make_uninit_string (len);
6949 err = ATSUFindFontName (font_id, kFontFamilyName,
6950 kFontMacintoshPlatform, kFontNoScript,
6951 kFontNoLanguage, len, SDATA (family),
6952 NULL, NULL);
6954 if (err == noErr)
6955 decode_mac_font_name (SDATA (family), len + 1, Qnil);
6957 return family;
6960 Lisp_Object
6961 mac_atsu_font_face_attributes (font_id)
6962 ATSUFontID font_id;
6964 Lisp_Object family, style_attrs;
6966 family = atsu_find_font_family_name (font_id);
6967 if (NILP (family))
6968 return Qnil;
6969 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
6970 return Fcons (QCfamily, Fcons (family, style_attrs));
6972 #endif
6974 /* Sets up the table font_name_table to contain the list of all fonts
6975 in the system the first time the table is used so that the Resource
6976 Manager need not be accessed every time this information is
6977 needed. */
6979 static void
6980 init_font_name_table ()
6982 #if TARGET_API_MAC_CARBON
6983 FMFontFamilyIterator ffi;
6984 FMFontFamilyInstanceIterator ffii;
6985 FMFontFamily ff;
6986 Lisp_Object text_encoding_info_alist;
6987 struct gcpro gcpro1;
6989 text_encoding_info_alist = create_text_encoding_info_alist ();
6991 #if USE_ATSUI
6992 #if USE_CG_TEXT_DRAWING
6993 init_cg_text_anti_aliasing_threshold ();
6994 #endif
6995 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6996 text_encoding_info_alist)))
6998 OSStatus err;
6999 struct Lisp_Hash_Table *h;
7000 unsigned hash_code;
7001 ItemCount nfonts, i;
7002 ATSUFontID *font_ids = NULL;
7003 Lisp_Object prev_family = Qnil;
7004 int j;
7006 atsu_font_id_hash =
7007 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
7008 make_float (DEFAULT_REHASH_SIZE),
7009 make_float (DEFAULT_REHASH_THRESHOLD),
7010 Qnil, Qnil, Qnil);
7011 h = XHASH_TABLE (atsu_font_id_hash);
7013 err = ATSUFontCount (&nfonts);
7014 if (err == noErr)
7016 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7017 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7019 if (err == noErr)
7020 for (i = 0; i < nfonts; i++)
7022 Lisp_Object family;
7024 family = atsu_find_font_family_name (font_ids[i]);
7025 if (NILP (family) || SREF (family, 0) == '.')
7026 continue;
7027 if (!NILP (Fequal (prev_family, family)))
7028 family = prev_family;
7029 else
7030 j = hash_lookup (h, family, &hash_code);
7031 if (j < 0)
7033 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
7034 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
7035 Qnil), hash_code);
7037 else if (EQ (prev_family, family))
7038 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
7039 HASH_VALUE (h, j));
7040 prev_family = family;
7042 if (font_ids)
7043 xfree (font_ids);
7045 #endif
7047 /* Create a dummy instance iterator here to avoid creating and
7048 destroying it in the loop. */
7049 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7050 return;
7051 /* Create an iterator to enumerate the font families. */
7052 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7053 != noErr)
7055 FMDisposeFontFamilyInstanceIterator (&ffii);
7056 return;
7059 GCPRO1 (text_encoding_info_alist);
7061 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
7063 Str255 name;
7064 FMFont font;
7065 FMFontStyle style;
7066 FMFontSize size;
7067 TextEncoding encoding;
7068 TextEncodingBase sc;
7069 Lisp_Object text_encoding_info, family;
7071 if (FMGetFontFamilyName (ff, name) != noErr)
7072 continue;
7073 p2cstr (name);
7074 if (*name == '.')
7075 continue;
7077 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
7078 continue;
7079 sc = GetTextEncodingBase (encoding);
7080 text_encoding_info = assq_no_quit (make_number (sc),
7081 text_encoding_info_alist);
7082 if (NILP (text_encoding_info))
7083 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7084 text_encoding_info_alist);
7085 decode_mac_font_name (name, sizeof (name),
7086 XCAR (XCDR (text_encoding_info)));
7087 family = build_string (name);
7088 if (!NILP (Fassoc (family, fm_font_family_alist)))
7089 continue;
7090 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7091 fm_font_family_alist);
7093 /* Point the instance iterator at the current font family. */
7094 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7095 continue;
7097 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7098 == noErr)
7100 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7102 if (size > 0 || style == normal)
7103 for (; !NILP (rest); rest = XCDR (rest))
7104 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7108 UNGCPRO;
7110 /* Dispose of the iterators. */
7111 FMDisposeFontFamilyIterator (&ffi);
7112 FMDisposeFontFamilyInstanceIterator (&ffii);
7113 #else /* !TARGET_API_MAC_CARBON */
7114 GrafPtr port;
7115 SInt16 fontnum, old_fontnum;
7116 int num_mac_fonts = CountResources('FOND');
7117 int i, j;
7118 Handle font_handle, font_handle_2;
7119 short id, scriptcode;
7120 ResType type;
7121 Str255 name;
7122 struct FontAssoc *fat;
7123 struct AsscEntry *assc_entry;
7124 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7125 struct gcpro gcpro1;
7127 GetPort (&port); /* save the current font number used */
7128 old_fontnum = port->txFont;
7130 text_encoding_info_alist = create_text_encoding_info_alist ();
7132 GCPRO1 (text_encoding_info_alist);
7134 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7136 font_handle = GetIndResource ('FOND', i);
7137 if (!font_handle)
7138 continue;
7140 GetResInfo (font_handle, &id, &type, name);
7141 GetFNum (name, &fontnum);
7142 p2cstr (name);
7143 if (fontnum == 0 || *name == '.')
7144 continue;
7146 TextFont (fontnum);
7147 scriptcode = FontToScript (fontnum);
7148 text_encoding_info = assq_no_quit (make_number (scriptcode),
7149 text_encoding_info_alist);
7150 if (NILP (text_encoding_info))
7151 text_encoding_info = assq_no_quit (make_number (smRoman),
7152 text_encoding_info_alist);
7153 decode_mac_font_name (name, sizeof (name),
7154 XCAR (XCDR (text_encoding_info)));
7155 family = build_string (name);
7156 if (!NILP (Fassoc (family, fm_font_family_alist)))
7157 continue;
7158 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7159 fm_font_family_alist);
7162 HLock (font_handle);
7164 if (GetResourceSizeOnDisk (font_handle)
7165 >= sizeof (struct FamRec))
7167 fat = (struct FontAssoc *) (*font_handle
7168 + sizeof (struct FamRec));
7169 assc_entry
7170 = (struct AsscEntry *) (*font_handle
7171 + sizeof (struct FamRec)
7172 + sizeof (struct FontAssoc));
7174 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7176 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7178 for (; !NILP (rest); rest = XCDR (rest))
7179 add_mac_font_name (name, assc_entry->fontSize,
7180 assc_entry->fontStyle,
7181 SDATA (XCAR (rest)));
7185 HUnlock (font_handle);
7186 font_handle_2 = GetNextFOND (font_handle);
7187 ReleaseResource (font_handle);
7188 font_handle = font_handle_2;
7190 while (ResError () == noErr && font_handle);
7193 UNGCPRO;
7195 TextFont (old_fontnum);
7196 #endif /* !TARGET_API_MAC_CARBON */
7200 void
7201 mac_clear_font_name_table ()
7203 int i;
7205 for (i = 0; i < font_name_count; i++)
7206 xfree (font_name_table[i]);
7207 xfree (font_name_table);
7208 font_name_table = NULL;
7209 font_name_table_size = font_name_count = 0;
7210 fm_font_family_alist = Qnil;
7214 enum xlfd_scalable_field_index
7216 XLFD_SCL_PIXEL_SIZE,
7217 XLFD_SCL_POINT_SIZE,
7218 XLFD_SCL_AVGWIDTH,
7219 XLFD_SCL_LAST
7222 static const int xlfd_scalable_fields[] =
7224 6, /* PIXEL_SIZE */
7225 7, /* POINT_SIZE */
7226 11, /* AVGWIDTH */
7230 static Lisp_Object
7231 mac_do_list_fonts (pattern, maxnames)
7232 const char *pattern;
7233 int maxnames;
7235 int i, n_fonts = 0;
7236 Lisp_Object font_list = Qnil;
7237 struct xlfdpat *pat;
7238 char *scaled;
7239 const char *ptr;
7240 int scl_val[XLFD_SCL_LAST], *val;
7241 const int *field;
7242 int exact;
7244 if (font_name_table == NULL) /* Initialize when first used. */
7245 init_font_name_table ();
7247 for (i = 0; i < XLFD_SCL_LAST; i++)
7248 scl_val[i] = -1;
7250 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7251 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7252 fonts are scaled according to the specified size. */
7253 ptr = pattern;
7254 i = 0;
7255 field = xlfd_scalable_fields;
7256 val = scl_val;
7257 if (*ptr == '-')
7260 ptr++;
7261 if (i == *field)
7263 if ('0' <= *ptr && *ptr <= '9')
7265 *val = *ptr++ - '0';
7266 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7267 *val = *val * 10 + *ptr++ - '0';
7268 if (*ptr != '-')
7269 *val = -1;
7271 field++;
7272 val++;
7274 ptr = strchr (ptr, '-');
7275 i++;
7277 while (ptr && i < 14);
7279 if (i == 14 && ptr == NULL)
7281 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7282 scl_val[XLFD_SCL_PIXEL_SIZE] =
7283 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7284 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7285 : -1));
7286 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7287 scl_val[XLFD_SCL_POINT_SIZE] =
7288 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7289 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7290 : -1));
7291 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7292 scl_val[XLFD_SCL_AVGWIDTH] =
7293 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7294 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7295 : -1));
7297 else
7298 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7300 pat = xlfdpat_create (pattern);
7301 if (pat == NULL)
7302 return Qnil;
7304 exact = xlfdpat_exact_p (pat);
7306 for (i = 0; i < font_name_count; i++)
7308 if (xlfdpat_match (pat, font_name_table[i]))
7310 font_list = Fcons (build_string (font_name_table[i]), font_list);
7311 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7312 break;
7314 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7315 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7317 int former_len = ptr - font_name_table[i];
7319 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7320 memcpy (scaled, font_name_table[i], former_len);
7321 sprintf (scaled + former_len,
7322 "-%d-%d-72-72-m-%d-%s",
7323 scl_val[XLFD_SCL_PIXEL_SIZE],
7324 scl_val[XLFD_SCL_POINT_SIZE],
7325 scl_val[XLFD_SCL_AVGWIDTH],
7326 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7328 if (xlfdpat_match (pat, scaled))
7330 font_list = Fcons (build_string (scaled), font_list);
7331 xfree (scaled);
7332 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7333 break;
7335 else
7336 xfree (scaled);
7340 xlfdpat_destroy (pat);
7342 return font_list;
7345 /* Return a list of names of available fonts matching PATTERN on frame F.
7347 Frame F null means we have not yet created any frame on Mac, and
7348 consult the first display in x_display_list. MAXNAMES sets a limit
7349 on how many fonts to match. */
7351 Lisp_Object
7352 x_list_fonts (f, pattern, size, maxnames)
7353 struct frame *f;
7354 Lisp_Object pattern;
7355 int size, maxnames;
7357 Lisp_Object list = Qnil, patterns, tem, key;
7358 struct mac_display_info *dpyinfo
7359 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7361 xassert (size <= 0);
7363 patterns = Fassoc (pattern, Valternate_fontname_alist);
7364 if (NILP (patterns))
7365 patterns = Fcons (pattern, Qnil);
7367 for (; CONSP (patterns); patterns = XCDR (patterns))
7369 pattern = XCAR (patterns);
7371 if (!STRINGP (pattern))
7372 continue;
7374 tem = XCAR (XCDR (dpyinfo->name_list_element));
7375 key = Fcons (pattern, make_number (maxnames));
7377 list = Fassoc (key, tem);
7378 if (!NILP (list))
7380 list = Fcdr_safe (list);
7381 /* We have a cashed list. Don't have to get the list again. */
7382 goto label_cached;
7385 BLOCK_INPUT;
7386 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7387 UNBLOCK_INPUT;
7389 /* MAC_TODO: add code for matching outline fonts here */
7391 /* Now store the result in the cache. */
7392 XSETCAR (XCDR (dpyinfo->name_list_element),
7393 Fcons (Fcons (key, list),
7394 XCAR (XCDR (dpyinfo->name_list_element))));
7396 label_cached:
7397 if (NILP (list)) continue; /* Try the remaining alternatives. */
7400 return list;
7404 #if GLYPH_DEBUG
7406 /* Check that FONT is valid on frame F. It is if it can be found in F's
7407 font table. */
7409 static void
7410 x_check_font (f, font)
7411 struct frame *f;
7412 XFontStruct *font;
7414 int i;
7415 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7417 xassert (font != NULL);
7419 for (i = 0; i < dpyinfo->n_fonts; i++)
7420 if (dpyinfo->font_table[i].name
7421 && font == dpyinfo->font_table[i].font)
7422 break;
7424 xassert (i < dpyinfo->n_fonts);
7427 #endif /* GLYPH_DEBUG != 0 */
7429 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7430 Note: There are (broken) X fonts out there with invalid XFontStruct
7431 min_bounds contents. For example, handa@etl.go.jp reports that
7432 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7433 have font->min_bounds.width == 0. */
7435 static INLINE void
7436 x_font_min_bounds (font, w, h)
7437 MacFontStruct *font;
7438 int *w, *h;
7440 *h = FONT_HEIGHT (font);
7441 *w = font->min_bounds.width;
7445 /* Compute the smallest character width and smallest font height over
7446 all fonts available on frame F. Set the members smallest_char_width
7447 and smallest_font_height in F's x_display_info structure to
7448 the values computed. Value is non-zero if smallest_font_height or
7449 smallest_char_width become smaller than they were before. */
7451 static int
7452 x_compute_min_glyph_bounds (f)
7453 struct frame *f;
7455 int i;
7456 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7457 MacFontStruct *font;
7458 int old_width = dpyinfo->smallest_char_width;
7459 int old_height = dpyinfo->smallest_font_height;
7461 dpyinfo->smallest_font_height = 100000;
7462 dpyinfo->smallest_char_width = 100000;
7464 for (i = 0; i < dpyinfo->n_fonts; ++i)
7465 if (dpyinfo->font_table[i].name)
7467 struct font_info *fontp = dpyinfo->font_table + i;
7468 int w, h;
7470 font = (MacFontStruct *) fontp->font;
7471 xassert (font != (MacFontStruct *) ~0);
7472 x_font_min_bounds (font, &w, &h);
7474 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7475 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7478 xassert (dpyinfo->smallest_char_width > 0
7479 && dpyinfo->smallest_font_height > 0);
7481 return (dpyinfo->n_fonts == 1
7482 || dpyinfo->smallest_char_width < old_width
7483 || dpyinfo->smallest_font_height < old_height);
7487 /* Determine whether given string is a fully-specified XLFD: all 14
7488 fields are present, none is '*'. */
7490 static int
7491 is_fully_specified_xlfd (p)
7492 const char *p;
7494 int i;
7495 char *q;
7497 if (*p != '-')
7498 return 0;
7500 for (i = 0; i < 13; i++)
7502 q = strchr (p + 1, '-');
7503 if (q == NULL)
7504 return 0;
7505 if (q - p == 2 && *(p + 1) == '*')
7506 return 0;
7507 p = q;
7510 if (strchr (p + 1, '-') != NULL)
7511 return 0;
7513 if (*(p + 1) == '*' && *(p + 2) == '\0')
7514 return 0;
7516 return 1;
7520 /* mac_load_query_font creates and returns an internal representation
7521 for a font in a MacFontStruct struct. There is really no concept
7522 corresponding to "loading" a font on the Mac. But we check its
7523 existence and find the font number and all other information for it
7524 and store them in the returned MacFontStruct. */
7526 static MacFontStruct *
7527 mac_load_query_font (f, fontname)
7528 struct frame *f;
7529 char *fontname;
7531 int size;
7532 char *name;
7533 Str255 family;
7534 Str31 charset;
7535 SInt16 fontnum;
7536 #if USE_ATSUI
7537 static ATSUFontID font_id;
7538 ATSUStyle mac_style = NULL;
7539 #endif
7540 Style fontface;
7541 #if TARGET_API_MAC_CARBON
7542 TextEncoding encoding;
7543 int scriptcode;
7544 #else
7545 short scriptcode;
7546 #endif
7547 MacFontStruct *font;
7548 XCharStruct *space_bounds = NULL, *pcm;
7550 if (is_fully_specified_xlfd (fontname))
7551 name = fontname;
7552 else
7554 Lisp_Object matched_fonts;
7556 matched_fonts = mac_do_list_fonts (fontname, 1);
7557 if (NILP (matched_fonts))
7558 return NULL;
7559 name = SDATA (XCAR (matched_fonts));
7562 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7563 return NULL;
7565 #if USE_ATSUI
7566 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7568 OSStatus err;
7569 static const ATSUAttributeTag tags[] =
7570 {kATSUFontTag, kATSUSizeTag,
7571 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7572 static const ByteCount sizes[] =
7573 {sizeof (ATSUFontID), sizeof (Fixed),
7574 sizeof (Boolean), sizeof (Boolean)};
7575 static Fixed size_fixed;
7576 static Boolean bold_p, italic_p;
7577 static const ATSUAttributeValuePtr values[] =
7578 {&font_id, &size_fixed,
7579 &bold_p, &italic_p};
7580 static const ATSUFontFeatureType types[] =
7581 {kAllTypographicFeaturesType, kDiacriticsType};
7582 static const ATSUFontFeatureSelector selectors[] =
7583 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
7584 FMFontStyle style;
7586 font_id = atsu_find_font_from_family_name (family);
7587 if (font_id == kATSUInvalidFontID)
7588 return NULL;
7589 size_fixed = Long2Fix (size);
7590 bold_p = (fontface & bold) != 0;
7591 italic_p = (fontface & italic) != 0;
7592 err = ATSUCreateStyle (&mac_style);
7593 if (err != noErr)
7594 return NULL;
7595 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7596 types, selectors);
7597 if (err != noErr)
7598 return NULL;
7599 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7600 tags, sizes, values);
7601 if (err != noErr)
7602 return NULL;
7603 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
7604 if (err != noErr)
7605 fontnum = -1;
7606 scriptcode = kTextEncodingMacUnicode;
7608 else
7609 #endif
7611 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7613 if (NILP (tmp))
7614 return NULL;
7615 fontnum = XINT (XCDR (tmp));
7616 #if TARGET_API_MAC_CARBON
7617 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7618 return NULL;
7619 scriptcode = GetTextEncodingBase (encoding);
7620 #else
7621 scriptcode = FontToScript (fontnum);
7622 #endif
7625 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7627 font->mac_fontnum = fontnum;
7628 font->mac_fontsize = size;
7629 font->mac_fontface = fontface;
7630 font->mac_scriptcode = scriptcode;
7631 #if USE_ATSUI
7632 font->mac_style = mac_style;
7633 #if USE_CG_TEXT_DRAWING
7634 font->cg_font = NULL;
7635 font->cg_glyphs = NULL;
7636 #endif
7637 #endif
7639 /* Apple Japanese (SJIS) font is listed as both
7640 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7641 (Roman script) in init_font_name_table (). The latter should be
7642 treated as a one-byte font. */
7643 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7644 font->mac_scriptcode = smRoman;
7646 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
7648 #if USE_ATSUI
7649 if (font->mac_style)
7651 OSStatus err;
7652 UniChar c;
7654 font->min_byte1 = 0;
7655 font->max_byte1 = 0xff;
7656 font->min_char_or_byte2 = 0;
7657 font->max_char_or_byte2 = 0xff;
7659 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
7660 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
7661 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
7662 pcm_init (font->bounds.rows[0], 0x100);
7664 #if USE_CG_TEXT_DRAWING
7665 if (fontnum != -1)
7667 FMFontStyle style;
7668 ATSFontRef ats_font;
7670 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
7671 &font_id, &style);
7672 /* Use CG text drawing if italic/bold is not synthesized. */
7673 if (err == noErr && style == fontface)
7675 ats_font = FMGetATSFontRefFromFont (font_id);
7676 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7680 if (font->cg_font)
7682 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7683 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7685 #endif
7686 space_bounds = font->bounds.rows[0] + 0x20;
7687 err = mac_query_char_extents (font->mac_style, 0x20,
7688 &font->ascent, &font->descent,
7689 space_bounds,
7690 #if USE_CG_TEXT_DRAWING
7691 (font->cg_glyphs ? font->cg_glyphs + 0x20
7692 : NULL)
7693 #else
7694 NULL
7695 #endif
7697 if (err != noErr
7698 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
7700 mac_unload_font (&one_mac_display_info, font);
7701 return NULL;
7704 pcm = font->bounds.rows[0];
7705 for (c = 0x21; c <= 0xff; c++)
7707 if (c == 0xad)
7708 /* Soft hyphen is not supported in ATSUI. */
7709 continue;
7710 else if (c == 0x7f)
7712 #if USE_CG_TEXT_DRAWING
7713 if (font->cg_glyphs)
7715 c = 0x9f;
7716 pcm = NULL;
7717 continue;
7719 #endif
7720 break;
7723 mac_query_char_extents (font->mac_style, c, NULL, NULL,
7724 pcm ? pcm + c : NULL,
7725 #if USE_CG_TEXT_DRAWING
7726 (font->cg_glyphs ? font->cg_glyphs + c
7727 : NULL)
7728 #else
7729 NULL
7730 #endif
7733 #if USE_CG_TEXT_DRAWING
7734 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
7736 /* Don't use CG text drawing if font substitution occurs in
7737 ASCII or Latin-1 characters. */
7738 CGFontRelease (font->cg_font);
7739 font->cg_font = NULL;
7740 xfree (font->cg_glyphs);
7741 font->cg_glyphs = NULL;
7742 if (pcm == NULL)
7743 break;
7745 #endif
7748 else
7749 #endif
7751 OSStatus err;
7752 FontInfo the_fontinfo;
7753 int is_two_byte_font;
7755 mac_begin_clip (f, NULL);
7757 TextFont (fontnum);
7758 TextSize (size);
7759 TextFace (fontface);
7761 GetFontInfo (&the_fontinfo);
7763 font->ascent = the_fontinfo.ascent;
7764 font->descent = the_fontinfo.descent;
7766 is_two_byte_font = (font->mac_scriptcode == smJapanese
7767 || font->mac_scriptcode == smTradChinese
7768 || font->mac_scriptcode == smSimpChinese
7769 || font->mac_scriptcode == smKorean);
7771 if (is_two_byte_font)
7773 int char_width;
7775 font->min_byte1 = 0xa1;
7776 font->max_byte1 = 0xfe;
7777 font->min_char_or_byte2 = 0xa1;
7778 font->max_char_or_byte2 = 0xfe;
7780 /* Use the width of an "ideographic space" of that font
7781 because the_fontinfo.widMax returns the wrong width for
7782 some fonts. */
7783 switch (font->mac_scriptcode)
7785 case smJapanese:
7786 font->min_byte1 = 0x81;
7787 font->max_byte1 = 0xfc;
7788 font->min_char_or_byte2 = 0x40;
7789 font->max_char_or_byte2 = 0xfc;
7790 char_width = StringWidth("\p\x81\x40");
7791 break;
7792 case smTradChinese:
7793 font->min_char_or_byte2 = 0x40;
7794 char_width = StringWidth("\p\xa1\x40");
7795 break;
7796 case smSimpChinese:
7797 char_width = StringWidth("\p\xa1\xa1");
7798 break;
7799 case smKorean:
7800 char_width = StringWidth("\p\xa1\xa1");
7801 break;
7804 font->bounds.per_char = NULL;
7806 if (fontface & italic)
7807 font->max_bounds.rbearing = char_width + 1;
7808 else
7809 font->max_bounds.rbearing = char_width;
7810 font->max_bounds.lbearing = 0;
7811 font->max_bounds.width = char_width;
7812 font->max_bounds.ascent = the_fontinfo.ascent;
7813 font->max_bounds.descent = the_fontinfo.descent;
7815 font->min_bounds = font->max_bounds;
7817 else
7819 int c;
7821 font->min_byte1 = font->max_byte1 = 0;
7822 font->min_char_or_byte2 = 0x20;
7823 font->max_char_or_byte2 = 0xff;
7825 font->bounds.per_char =
7826 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7827 bzero (font->bounds.per_char,
7828 sizeof (XCharStruct) * (0xff - 0x20 + 1));
7830 space_bounds = font->bounds.per_char;
7831 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
7832 &font->descent, space_bounds, NULL);
7833 if (err != noErr || space_bounds->width <= 0)
7835 mac_unload_font (&one_mac_display_info, font);
7836 return NULL;
7839 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
7840 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
7843 mac_end_clip (f, NULL);
7846 if (space_bounds)
7848 int c;
7850 font->min_bounds = font->max_bounds = *space_bounds;
7851 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
7852 if (pcm->width > 0)
7854 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
7855 pcm->lbearing);
7856 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
7857 pcm->rbearing);
7858 font->min_bounds.width = min (font->min_bounds.width,
7859 pcm->width);
7860 font->min_bounds.ascent = min (font->min_bounds.ascent,
7861 pcm->ascent);
7862 font->min_bounds.descent = min (font->min_bounds.descent,
7863 pcm->descent);
7865 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
7866 pcm->lbearing);
7867 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
7868 pcm->rbearing);
7869 font->max_bounds.width = max (font->max_bounds.width,
7870 pcm->width);
7871 font->max_bounds.ascent = max (font->max_bounds.ascent,
7872 pcm->ascent);
7873 font->max_bounds.descent = max (font->max_bounds.descent,
7874 pcm->descent);
7876 if (
7877 #if USE_ATSUI
7878 font->mac_style == NULL &&
7879 #endif
7880 font->max_bounds.width == font->min_bounds.width
7881 && font->min_bounds.lbearing >= 0
7882 && font->max_bounds.rbearing <= font->max_bounds.width)
7884 /* Fixed width and no overhangs. */
7885 xfree (font->bounds.per_char);
7886 font->bounds.per_char = NULL;
7890 #if !defined (MAC_OS8) || USE_ATSUI
7891 /* AppKit and WebKit do some adjustment to the heights of Courier,
7892 Helvetica, and Times. This only works on the environments where
7893 srcCopy text transfer mode is never used. */
7894 if (
7895 #ifdef MAC_OS8 /* implies USE_ATSUI */
7896 font->mac_style &&
7897 #endif
7898 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
7899 || strcmp (family, "times") == 0))
7900 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
7901 #endif
7903 return font;
7907 void
7908 mac_unload_font (dpyinfo, font)
7909 struct mac_display_info *dpyinfo;
7910 XFontStruct *font;
7912 xfree (font->full_name);
7913 #if USE_ATSUI
7914 if (font->mac_style)
7916 int i;
7918 for (i = font->min_byte1; i <= font->max_byte1; i++)
7919 if (font->bounds.rows[i])
7920 xfree (font->bounds.rows[i]);
7921 xfree (font->bounds.rows);
7922 ATSUDisposeStyle (font->mac_style);
7924 else
7925 #endif
7926 if (font->bounds.per_char)
7927 xfree (font->bounds.per_char);
7928 #if USE_CG_TEXT_DRAWING
7929 if (font->cg_font)
7930 CGFontRelease (font->cg_font);
7931 if (font->cg_glyphs)
7932 xfree (font->cg_glyphs);
7933 #endif
7934 xfree (font);
7938 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7939 pointer to the structure font_info while allocating it dynamically.
7940 If SIZE is 0, load any size of font.
7941 If loading is failed, return NULL. */
7943 struct font_info *
7944 x_load_font (f, fontname, size)
7945 struct frame *f;
7946 register char *fontname;
7947 int size;
7949 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7950 Lisp_Object font_names;
7952 /* Get a list of all the fonts that match this name. Once we
7953 have a list of matching fonts, we compare them against the fonts
7954 we already have by comparing names. */
7955 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7957 if (!NILP (font_names))
7959 Lisp_Object tail;
7960 int i;
7962 for (i = 0; i < dpyinfo->n_fonts; i++)
7963 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7964 if (dpyinfo->font_table[i].name
7965 && (!strcmp (dpyinfo->font_table[i].name,
7966 SDATA (XCAR (tail)))
7967 || !strcmp (dpyinfo->font_table[i].full_name,
7968 SDATA (XCAR (tail)))))
7969 return (dpyinfo->font_table + i);
7971 else
7972 return NULL;
7974 /* Load the font and add it to the table. */
7976 struct MacFontStruct *font;
7977 struct font_info *fontp;
7978 int i;
7980 fontname = (char *) SDATA (XCAR (font_names));
7982 BLOCK_INPUT;
7983 font = mac_load_query_font (f, fontname);
7984 UNBLOCK_INPUT;
7985 if (!font)
7986 return NULL;
7988 /* Find a free slot in the font table. */
7989 for (i = 0; i < dpyinfo->n_fonts; ++i)
7990 if (dpyinfo->font_table[i].name == NULL)
7991 break;
7993 /* If no free slot found, maybe enlarge the font table. */
7994 if (i == dpyinfo->n_fonts
7995 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7997 int sz;
7998 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7999 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
8000 dpyinfo->font_table
8001 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
8004 fontp = dpyinfo->font_table + i;
8005 if (i == dpyinfo->n_fonts)
8006 ++dpyinfo->n_fonts;
8008 /* Now fill in the slots of *FONTP. */
8009 BLOCK_INPUT;
8010 bzero (fontp, sizeof (*fontp));
8011 fontp->font = font;
8012 fontp->font_idx = i;
8013 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8014 bcopy (fontname, fontp->name, strlen (fontname) + 1);
8016 if (font->min_bounds.width == font->max_bounds.width)
8018 /* Fixed width font. */
8019 fontp->average_width = fontp->space_width = font->min_bounds.width;
8021 else
8023 XChar2b char2b;
8024 XCharStruct *pcm;
8026 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8027 pcm = mac_per_char_metric (font, &char2b, 0);
8028 if (pcm)
8029 fontp->space_width = pcm->width;
8030 else
8031 fontp->space_width = FONT_WIDTH (font);
8033 if (pcm)
8035 int width = pcm->width;
8036 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8037 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8038 width += pcm->width;
8039 fontp->average_width = width / 95;
8041 else
8042 fontp->average_width = FONT_WIDTH (font);
8045 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8046 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
8048 fontp->size = font->max_bounds.width;
8049 fontp->height = FONT_HEIGHT (font);
8051 /* For some font, ascent and descent in max_bounds field is
8052 larger than the above value. */
8053 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8054 if (max_height > fontp->height)
8055 fontp->height = max_height;
8058 /* The slot `encoding' specifies how to map a character
8059 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8060 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8061 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8062 2:0xA020..0xFF7F). For the moment, we don't know which charset
8063 uses this font. So, we set information in fontp->encoding[1]
8064 which is never used by any charset. If mapping can't be
8065 decided, set FONT_ENCODING_NOT_DECIDED. */
8066 if (font->mac_scriptcode == smJapanese)
8067 fontp->encoding[1] = 4;
8068 else
8070 fontp->encoding[1]
8071 = (font->max_byte1 == 0
8072 /* 1-byte font */
8073 ? (font->min_char_or_byte2 < 0x80
8074 ? (font->max_char_or_byte2 < 0x80
8075 ? 0 /* 0x20..0x7F */
8076 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8077 : 1) /* 0xA0..0xFF */
8078 /* 2-byte font */
8079 : (font->min_byte1 < 0x80
8080 ? (font->max_byte1 < 0x80
8081 ? (font->min_char_or_byte2 < 0x80
8082 ? (font->max_char_or_byte2 < 0x80
8083 ? 0 /* 0x2020..0x7F7F */
8084 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8085 : 3) /* 0x20A0..0x7FFF */
8086 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8087 : (font->min_char_or_byte2 < 0x80
8088 ? (font->max_char_or_byte2 < 0x80
8089 ? 2 /* 0xA020..0xFF7F */
8090 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8091 : 1))); /* 0xA0A0..0xFFFF */
8094 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8095 fontp->baseline_offset
8096 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8097 ? (long) value : 0);
8098 fontp->relative_compose
8099 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8100 ? (long) value : 0);
8101 fontp->default_ascent
8102 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8103 ? (long) value : 0);
8104 #else
8105 fontp->baseline_offset = 0;
8106 fontp->relative_compose = 0;
8107 fontp->default_ascent = 0;
8108 #endif
8110 /* Set global flag fonts_changed_p to non-zero if the font loaded
8111 has a character with a smaller width than any other character
8112 before, or if the font loaded has a smaller height than any
8113 other font loaded before. If this happens, it will make a
8114 glyph matrix reallocation necessary. */
8115 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8116 UNBLOCK_INPUT;
8117 return fontp;
8122 /* Return a pointer to struct font_info of a font named FONTNAME for
8123 frame F. If no such font is loaded, return NULL. */
8125 struct font_info *
8126 x_query_font (f, fontname)
8127 struct frame *f;
8128 register char *fontname;
8130 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8131 int i;
8133 for (i = 0; i < dpyinfo->n_fonts; i++)
8134 if (dpyinfo->font_table[i].name
8135 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8136 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8137 return (dpyinfo->font_table + i);
8138 return NULL;
8142 /* Find a CCL program for a font specified by FONTP, and set the member
8143 `encoder' of the structure. */
8145 void
8146 x_find_ccl_program (fontp)
8147 struct font_info *fontp;
8149 Lisp_Object list, elt;
8151 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8153 elt = XCAR (list);
8154 if (CONSP (elt)
8155 && STRINGP (XCAR (elt))
8156 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8157 >= 0))
8158 break;
8160 if (! NILP (list))
8162 struct ccl_program *ccl
8163 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8165 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8166 xfree (ccl);
8167 else
8168 fontp->font_encoder = ccl;
8173 /* The Mac Event loop code */
8175 #if !TARGET_API_MAC_CARBON
8176 #include <Events.h>
8177 #include <Quickdraw.h>
8178 #include <Balloons.h>
8179 #include <Devices.h>
8180 #include <Fonts.h>
8181 #include <Gestalt.h>
8182 #include <Menus.h>
8183 #include <Processes.h>
8184 #include <Sound.h>
8185 #include <ToolUtils.h>
8186 #include <TextUtils.h>
8187 #include <Dialogs.h>
8188 #include <Script.h>
8189 #include <Types.h>
8190 #include <Resources.h>
8192 #if __MWERKS__
8193 #include <unix.h>
8194 #endif
8195 #endif /* ! TARGET_API_MAC_CARBON */
8197 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8198 Lisp_Object Qreverse;
8201 /* Modifier associated with the control key, or nil to ignore. */
8202 Lisp_Object Vmac_control_modifier;
8204 /* Modifier associated with the option key, or nil to ignore. */
8205 Lisp_Object Vmac_option_modifier;
8207 /* Modifier associated with the command key, or nil to ignore. */
8208 Lisp_Object Vmac_command_modifier;
8210 /* Modifier associated with the function key, or nil to ignore. */
8211 Lisp_Object Vmac_function_modifier;
8213 /* True if the option and command modifiers should be used to emulate
8214 a three button mouse */
8215 Lisp_Object Vmac_emulate_three_button_mouse;
8217 #if TARGET_API_MAC_CARBON
8218 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8219 mouse-2, instead of mouse-3. */
8220 int mac_wheel_button_is_mouse_2;
8222 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8223 for processing before Emacs sees it. */
8224 int mac_pass_command_to_system;
8226 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8227 for processing before Emacs sees it. */
8228 int mac_pass_control_to_system;
8229 #endif
8231 /* Whether or not the screen configuration has changed. */
8232 int mac_screen_config_changed = 0;
8234 /* Apple Events */
8235 #if TARGET_API_MAC_CARBON
8236 Lisp_Object Qhi_command;
8237 #ifdef MAC_OSX
8238 Lisp_Object Qtoolbar_switch_mode;
8239 #endif
8240 #if USE_MAC_TSM
8241 Lisp_Object Qtext_input;
8242 Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8243 Lisp_Object Vmac_ts_active_input_overlay, Vmac_ts_active_input_buf;
8244 static Lisp_Object Vmac_ts_script_language_on_focus;
8245 static Lisp_Object saved_ts_script_language_on_focus;
8246 static ScriptLanguageRecord saved_ts_language;
8247 static Component saved_ts_component;
8248 #endif
8249 #ifdef MAC_OSX
8250 Lisp_Object Qservice, Qpaste, Qperform;
8251 Lisp_Object Qmouse_drag_overlay;
8252 #endif
8253 #endif /* TARGET_API_MAC_CARBON */
8254 extern Lisp_Object Qundefined;
8255 extern int XTread_socket P_ ((int, int, struct input_event *));
8256 extern void init_apple_event_handler P_ ((void));
8257 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8258 Lisp_Object *, Lisp_Object *,
8259 Lisp_Object *));
8260 extern OSErr init_coercion_handler P_ ((void));
8262 /* Table for translating Mac keycode to X keysym values. Contributed
8263 by Sudhir Shenoy.
8264 Mapping for special keys is now identical to that in Apple X11
8265 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8266 on the right of the Cmd key on laptops, and fn + `enter' (->
8267 <linefeed>). */
8268 const unsigned char keycode_to_xkeysym_table[] = {
8269 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8270 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8271 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8273 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8274 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8275 /*0x38*/ 0, 0, 0, 0,
8276 /*0x3C*/ 0, 0, 0, 0,
8278 /*0x40*/ 0xce /*f17*/, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8279 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8280 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8281 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0xcf /*f18*/,
8283 /*0x50*/ 0xd0 /*f19*/, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8284 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8285 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8286 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8288 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8289 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8290 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8291 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8293 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8294 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8295 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8296 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8299 #ifdef MAC_OSX
8300 /* Table for translating Mac keycode with the laptop `fn' key to that
8301 without it. Destination symbols in comments are keys on US
8302 keyboard, and they may not be the same on other types of keyboards.
8303 If the destination is identical to the source, it doesn't map `fn'
8304 key to a modifier. */
8305 static const unsigned char fn_keycode_to_keycode_table[] = {
8306 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8307 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8308 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8310 /*0x30*/ 0, 0, 0, 0,
8311 /*0x34*/ 0, 0, 0, 0,
8312 /*0x38*/ 0, 0, 0, 0,
8313 /*0x3C*/ 0, 0, 0, 0,
8315 /*0x40*/ 0x40 /*f17 = f17*/, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8316 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8317 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8318 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0x4f /*f18 = f18*/,
8320 /*0x50*/ 0x50 /*f19 = f19*/, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8321 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8322 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8323 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8325 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8326 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8327 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
8328 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8330 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
8331 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8332 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
8333 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
8335 #endif /* MAC_OSX */
8338 #if TARGET_API_MAC_CARBON
8339 mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
8340 #else
8341 mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
8342 #endif
8344 unsigned int result = 0;
8345 if ((mods | unmapped_mods) & shiftKey)
8346 result |= shift_modifier;
8348 /* Deactivated to simplify configuration:
8349 if Vmac_option_modifier is non-NIL, we fully process the Option
8350 key. Otherwise, we only process it if an additional Ctrl or Command
8351 is pressed. That way the system may convert the character to a
8352 composed one.
8353 if ((mods & optionKey) &&
8354 (( !NILP(Vmac_option_modifier) ||
8355 ((mods & cmdKey) || (mods & controlKey))))) */
8357 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
8358 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8359 if (INTEGERP(val))
8360 result |= XUINT(val);
8362 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8363 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8364 if (INTEGERP(val))
8365 result |= XUINT(val);
8367 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8368 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8369 if (INTEGERP(val))
8370 result |= XUINT(val);
8373 #ifdef MAC_OSX
8374 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8375 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8376 if (INTEGERP(val))
8377 result |= XUINT(val);
8379 #endif
8381 return result;
8384 UInt32
8385 mac_mapped_modifiers (modifiers, key_code)
8386 UInt32 modifiers, key_code;
8388 UInt32 mapped_modifiers_all =
8389 (NILP (Vmac_control_modifier) ? 0 : controlKey)
8390 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
8391 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
8393 #ifdef MAC_OSX
8394 mapped_modifiers_all |=
8395 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
8397 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
8398 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
8399 no longer means laptop's `fn' key is down for the following keys:
8400 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
8401 Down, the arrow keys, and Clear. We ignore the corresponding bit
8402 if that key can be entered without the `fn' key on laptops. */
8403 if (modifiers & kEventKeyModifierFnMask
8404 && key_code <= 0x7f
8405 && fn_keycode_to_keycode_table[key_code] == key_code)
8406 modifiers &= ~kEventKeyModifierFnMask;
8407 #endif
8409 return mapped_modifiers_all & modifiers;
8413 mac_get_emulated_btn ( UInt32 modifiers )
8415 int result = 0;
8416 if (!NILP (Vmac_emulate_three_button_mouse)) {
8417 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
8418 if (modifiers & cmdKey)
8419 result = cmdIs3 ? 2 : 1;
8420 else if (modifiers & optionKey)
8421 result = cmdIs3 ? 1 : 2;
8423 return result;
8426 #ifdef MAC_OSX
8427 void
8428 mac_get_selected_range (w, range)
8429 struct window *w;
8430 CFRange *range;
8432 Lisp_Object overlay = find_symbol_value (Qmouse_drag_overlay);
8433 struct buffer *b = XBUFFER (w->buffer);
8434 int begv = BUF_BEGV (b), zv = BUF_ZV (b);
8435 int start, end;
8437 if (OVERLAYP (overlay)
8438 && EQ (Foverlay_buffer (overlay), w->buffer)
8439 && (start = XINT (Foverlay_start (overlay)),
8440 end = XINT (Foverlay_end (overlay)),
8441 start != end))
8443 else
8445 if (w == XWINDOW (selected_window) && b == current_buffer)
8446 start = PT;
8447 else
8448 start = marker_position (w->pointm);
8450 if (NILP (Vtransient_mark_mode) || NILP (b->mark_active))
8451 end = start;
8452 else
8454 int mark_pos = marker_position (b->mark);
8456 if (start <= mark_pos)
8457 end = mark_pos;
8458 else
8460 end = start;
8461 start = mark_pos;
8466 if (start != end)
8468 if (start < begv)
8469 start = begv;
8470 else if (start > zv)
8471 start = zv;
8473 if (end < begv)
8474 end = begv;
8475 else if (end > zv)
8476 end = zv;
8479 range->location = start - begv;
8480 range->length = end - start;
8483 /* Store the text of the buffer BUF from START to END as Unicode
8484 characters in CHARACTERS. Return non-zero if successful. */
8487 mac_store_buffer_text_to_unicode_chars (buf, start, end, characters)
8488 struct buffer *buf;
8489 int start, end;
8490 UniChar *characters;
8492 int start_byte, end_byte, char_count, byte_count;
8493 struct coding_system coding;
8494 unsigned char *dst = (unsigned char *) characters;
8496 start_byte = buf_charpos_to_bytepos (buf, start);
8497 end_byte = buf_charpos_to_bytepos (buf, end);
8498 char_count = end - start;
8499 byte_count = end_byte - start_byte;
8501 if (setup_coding_system (
8502 #ifdef WORDS_BIG_ENDIAN
8503 intern ("utf-16be")
8504 #else
8505 intern ("utf-16le")
8506 #endif
8507 , &coding) < 0)
8508 return 0;
8510 coding.src_multibyte = !NILP (buf->enable_multibyte_characters);
8511 coding.dst_multibyte = 0;
8512 coding.mode |= CODING_MODE_LAST_BLOCK;
8513 coding.composing = COMPOSITION_DISABLED;
8515 if (BUF_GPT_BYTE (buf) <= start_byte || end_byte <= BUF_GPT_BYTE (buf))
8516 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8517 byte_count, char_count * sizeof (UniChar));
8518 else
8520 int first_byte_count = BUF_GPT_BYTE (buf) - start_byte;
8522 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8523 first_byte_count, char_count * sizeof (UniChar));
8524 if (coding.result == CODING_FINISH_NORMAL)
8525 encode_coding (&coding,
8526 BUF_BYTE_ADDRESS (buf, start_byte + first_byte_count),
8527 dst + coding.produced,
8528 byte_count - first_byte_count,
8529 char_count * sizeof (UniChar) - coding.produced);
8532 if (coding.result != CODING_FINISH_NORMAL)
8533 return 0;
8535 return 1;
8538 void
8539 mac_ax_selected_text_range (f, range)
8540 struct frame *f;
8541 CFRange *range;
8543 mac_get_selected_range (XWINDOW (f->selected_window), range);
8546 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8547 unsigned int
8548 mac_ax_number_of_characters (f)
8549 struct frame *f;
8551 struct buffer *b = XBUFFER (XWINDOW (f->selected_window)->buffer);
8553 return BUF_ZV (b) - BUF_BEGV (b);
8555 #endif
8556 #endif
8558 #if USE_MAC_TSM
8559 OSStatus
8560 mac_restore_keyboard_input_source ()
8562 OSStatus err = noErr;
8563 ScriptLanguageRecord slrec, *slptr = NULL;
8565 if (EQ (Vmac_ts_script_language_on_focus, Qt)
8566 && EQ (saved_ts_script_language_on_focus, Qt))
8567 slptr = &saved_ts_language;
8568 else if (CONSP (Vmac_ts_script_language_on_focus)
8569 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8570 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
8571 && CONSP (saved_ts_script_language_on_focus)
8572 && EQ (XCAR (saved_ts_script_language_on_focus),
8573 XCAR (Vmac_ts_script_language_on_focus))
8574 && EQ (XCDR (saved_ts_script_language_on_focus),
8575 XCDR (Vmac_ts_script_language_on_focus)))
8577 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8578 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8579 slptr = &slrec;
8582 if (slptr)
8584 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8585 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
8586 kKeyboardInputMethodClass);
8587 #else
8588 err = SetDefaultInputMethod (saved_ts_component, slptr);
8589 #endif
8590 if (err == noErr)
8591 err = SetTextServiceLanguage (slptr);
8593 /* Seems to be needed on Mac OS X 10.2. */
8594 if (err == noErr)
8595 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
8598 return err;
8601 void
8602 mac_save_keyboard_input_source ()
8604 OSStatus err;
8605 ScriptLanguageRecord slrec, *slptr = NULL;
8607 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
8609 if (EQ (Vmac_ts_script_language_on_focus, Qt))
8611 err = GetTextServiceLanguage (&saved_ts_language);
8612 if (err == noErr)
8613 slptr = &saved_ts_language;
8615 else if (CONSP (Vmac_ts_script_language_on_focus)
8616 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8617 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
8619 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8620 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8621 slptr = &slrec;
8624 if (slptr)
8626 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8627 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
8628 kKeyboardInputMethodClass);
8629 #else
8630 GetDefaultInputMethod (&saved_ts_component, slptr);
8631 #endif
8634 #endif
8636 #if TARGET_API_MAC_CARBON
8637 /***** Code to handle C-g testing *****/
8638 extern int quit_char;
8639 extern int make_ctrl_char P_ ((int));
8642 mac_quit_char_key_p (modifiers, key_code)
8643 UInt32 modifiers, key_code;
8645 UInt32 char_code, mapped_modifiers;
8646 unsigned long some_state = 0;
8647 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8648 int c, emacs_modifiers;
8650 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
8651 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8652 key_code |= (modifiers & ~mapped_modifiers);
8653 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
8654 if (char_code & ~0xff)
8655 return 0;
8657 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8658 if (emacs_modifiers & ctrl_modifier)
8659 c = make_ctrl_char (char_code);
8661 c |= (emacs_modifiers
8662 & (meta_modifier | alt_modifier
8663 | hyper_modifier | super_modifier));
8665 return c == quit_char;
8667 #endif
8669 static void
8670 mac_set_unicode_keystroke_event (code, buf)
8671 UniChar code;
8672 struct input_event *buf;
8674 int charset_id, c1, c2;
8676 if (code < 0x80)
8678 buf->kind = ASCII_KEYSTROKE_EVENT;
8679 buf->code = code;
8681 else if (code < 0x100)
8683 if (code < 0xA0)
8684 charset_id = CHARSET_8_BIT_CONTROL;
8685 else
8686 charset_id = charset_latin_iso8859_1;
8687 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8688 buf->code = MAKE_CHAR (charset_id, code, 0);
8690 else
8692 if (code < 0x2500)
8693 charset_id = charset_mule_unicode_0100_24ff,
8694 code -= 0x100;
8695 else if (code < 0x33FF)
8696 charset_id = charset_mule_unicode_2500_33ff,
8697 code -= 0x2500;
8698 else if (code >= 0xE000)
8699 charset_id = charset_mule_unicode_e000_ffff,
8700 code -= 0xE000;
8701 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
8702 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8703 buf->code = MAKE_CHAR (charset_id, c1, c2);
8707 void
8708 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
8709 EventKind action;
8710 unsigned char char_code;
8711 UInt32 key_code, modifiers;
8712 unsigned long timestamp;
8713 struct input_event *buf;
8715 static SInt16 last_key_script = -1;
8716 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
8717 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8719 #ifdef MAC_OSX
8720 if (mapped_modifiers & kEventKeyModifierFnMask
8721 && key_code <= 0x7f
8722 && fn_keycode_to_keycode_table[key_code])
8723 key_code = fn_keycode_to_keycode_table[key_code];
8724 #endif
8726 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
8728 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
8729 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
8731 else if (mapped_modifiers)
8733 /* translate the keycode back to determine the original key */
8734 #ifdef MAC_OSX
8735 UCKeyboardLayout *uchr_ptr = NULL;
8736 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8737 OSStatus err;
8738 KeyboardLayoutRef layout;
8740 err = KLGetCurrentKeyboardLayout (&layout);
8741 if (err == noErr)
8742 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
8743 (const void **) &uchr_ptr);
8744 #else
8745 static SInt16 last_key_layout_id = 0;
8746 static Handle uchr_handle = (Handle)-1;
8747 SInt16 current_key_layout_id =
8748 GetScriptVariable (current_key_script, smScriptKeys);
8750 if (uchr_handle == (Handle)-1
8751 || last_key_layout_id != current_key_layout_id)
8753 uchr_handle = GetResource ('uchr', current_key_layout_id);
8754 last_key_layout_id = current_key_layout_id;
8756 if (uchr_handle)
8757 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
8758 #endif
8760 if (uchr_ptr)
8762 OSStatus status;
8763 UInt16 key_action = action - keyDown;
8764 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
8765 UInt32 keyboard_type = LMGetKbdType ();
8766 SInt32 dead_key_state = 0;
8767 UniChar code;
8768 UniCharCount actual_length;
8770 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
8771 modifier_key_state, keyboard_type,
8772 kUCKeyTranslateNoDeadKeysMask,
8773 &dead_key_state,
8774 1, &actual_length, &code);
8775 if (status == noErr && actual_length == 1)
8776 mac_set_unicode_keystroke_event (code, buf);
8778 #endif /* MAC_OSX */
8780 if (buf->kind == NO_EVENT)
8782 /* This code comes from Keyboard Resource, Appendix C of IM
8783 - Text. This is necessary since shift is ignored in KCHR
8784 table translation when option or command is pressed. It
8785 also does not translate correctly control-shift chars
8786 like C-% so mask off shift here also. */
8787 /* Mask off modifier keys that are mapped to some Emacs
8788 modifiers. */
8789 int new_modifiers = modifiers & ~mapped_modifiers;
8790 /* set high byte of keycode to modifier high byte*/
8791 int new_key_code = key_code | new_modifiers;
8792 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8793 unsigned long some_state = 0;
8794 UInt32 new_char_code;
8796 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
8797 if (new_char_code == 0)
8798 /* Seems like a dead key. Append up-stroke. */
8799 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
8800 &some_state);
8801 if (new_char_code)
8803 buf->kind = ASCII_KEYSTROKE_EVENT;
8804 buf->code = new_char_code & 0xff;
8809 if (buf->kind == NO_EVENT)
8811 buf->kind = ASCII_KEYSTROKE_EVENT;
8812 buf->code = char_code;
8815 buf->modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8816 buf->modifiers |= (extra_keyboard_modifiers
8817 & (meta_modifier | alt_modifier
8818 | hyper_modifier | super_modifier));
8820 #if TARGET_API_MAC_CARBON
8821 if (buf->kind == ASCII_KEYSTROKE_EVENT
8822 && buf->code >= 0x80 && buf->modifiers)
8824 OSStatus err;
8825 TextEncoding encoding = kTextEncodingMacRoman;
8826 TextToUnicodeInfo ttu_info;
8828 UpgradeScriptInfoToTextEncoding (current_key_script,
8829 kTextLanguageDontCare,
8830 kTextRegionDontCare,
8831 NULL, &encoding);
8832 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
8833 if (err == noErr)
8835 UniChar code;
8836 Str255 pstr;
8837 ByteCount unicode_len;
8839 pstr[0] = 1;
8840 pstr[1] = buf->code;
8841 err = ConvertFromPStringToUnicode (ttu_info, pstr,
8842 sizeof (UniChar),
8843 &unicode_len, &code);
8844 if (err == noErr && unicode_len == sizeof (UniChar))
8845 mac_set_unicode_keystroke_event (code, buf);
8846 DisposeTextToUnicodeInfo (&ttu_info);
8849 #endif
8851 if (buf->kind == ASCII_KEYSTROKE_EVENT
8852 && buf->code >= 0x80
8853 && last_key_script != current_key_script)
8855 struct input_event event;
8857 EVENT_INIT (event);
8858 event.kind = LANGUAGE_CHANGE_EVENT;
8859 event.arg = Qnil;
8860 event.code = current_key_script;
8861 event.timestamp = timestamp;
8862 kbd_buffer_store_event (&event);
8863 last_key_script = current_key_script;
8867 void
8868 mac_store_apple_event (class, id, desc)
8869 Lisp_Object class, id;
8870 const AEDesc *desc;
8872 struct input_event buf;
8874 EVENT_INIT (buf);
8876 buf.kind = MAC_APPLE_EVENT;
8877 buf.x = class;
8878 buf.y = id;
8879 XSETFRAME (buf.frame_or_window,
8880 mac_focus_frame (&one_mac_display_info));
8881 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
8882 is safe to use them during read_socket_hook. */
8883 buf.arg = mac_aedesc_to_lisp (desc);
8884 kbd_buffer_store_event (&buf);
8887 #if TARGET_API_MAC_CARBON
8888 OSStatus
8889 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
8890 event, num_params, names, types)
8891 AEEventClass class;
8892 AEEventID id;
8893 Lisp_Object class_key, id_key;
8894 EventRef event;
8895 UInt32 num_params;
8896 const EventParamName *names;
8897 const EventParamType *types;
8899 OSStatus err = eventNotHandledErr;
8900 Lisp_Object binding;
8902 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
8903 if (!NILP (binding) && !EQ (binding, Qundefined))
8905 if (INTEGERP (binding))
8906 err = XINT (binding);
8907 else
8909 struct input_event buf;
8911 EVENT_INIT (buf);
8913 buf.kind = MAC_APPLE_EVENT;
8914 buf.x = class_key;
8915 buf.y = id_key;
8916 XSETFRAME (buf.frame_or_window,
8917 mac_focus_frame (&one_mac_display_info));
8918 /* Now that Lisp object allocations are protected by
8919 BLOCK_INPUT, it is safe to use them during
8920 read_socket_hook. */
8921 buf.arg = Fcons (build_string ("aevt"),
8922 mac_event_parameters_to_lisp (event, num_params,
8923 names, types));
8924 kbd_buffer_store_event (&buf);
8925 mac_wakeup_from_rne ();
8926 err = noErr;
8930 return err;
8932 #endif /* TARGET_API_MAC_CARBON */
8934 static pascal void
8935 mac_handle_dm_notification (event)
8936 AppleEvent *event;
8938 mac_screen_config_changed = 1;
8941 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8942 static void
8943 mac_handle_cg_display_reconfig (display, flags, user_info)
8944 CGDirectDisplayID display;
8945 CGDisplayChangeSummaryFlags flags;
8946 void *user_info;
8948 mac_screen_config_changed = 1;
8950 #endif
8952 static OSErr
8953 init_dm_notification_handler ()
8955 OSErr err = noErr;
8957 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8958 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8959 if (CGDisplayRegisterReconfigurationCallback != NULL)
8960 #endif
8962 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
8963 NULL);
8965 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8966 else /* CGDisplayRegisterReconfigurationCallback == NULL */
8967 #endif
8968 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
8969 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8971 static DMNotificationUPP handle_dm_notificationUPP = NULL;
8972 ProcessSerialNumber psn;
8974 if (handle_dm_notificationUPP == NULL)
8975 handle_dm_notificationUPP =
8976 NewDMNotificationUPP (mac_handle_dm_notification);
8978 err = GetCurrentProcess (&psn);
8979 if (err == noErr)
8980 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
8982 #endif
8984 return err;
8987 void
8988 mac_get_screen_info (dpyinfo)
8989 struct mac_display_info *dpyinfo;
8991 #ifdef MAC_OSX
8992 /* HasDepth returns true if it is possible to have a 32 bit display,
8993 but this may not be what is actually used. Mac OSX can do better. */
8994 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
8995 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
8997 CGDisplayErr err;
8998 CGDisplayCount ndisps;
8999 CGDirectDisplayID *displays;
9001 err = CGGetActiveDisplayList (0, NULL, &ndisps);
9002 if (err == noErr)
9004 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
9005 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
9007 if (err == noErr)
9009 CGRect bounds = CGRectZero;
9011 while (ndisps-- > 0)
9012 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
9013 dpyinfo->height = CGRectGetHeight (bounds);
9014 dpyinfo->width = CGRectGetWidth (bounds);
9016 else
9018 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
9019 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
9022 #else /* !MAC_OSX */
9024 GDHandle gdh = GetMainDevice ();
9025 Rect rect = (**gdh).gdRect;
9027 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
9028 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9029 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
9030 break;
9032 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
9033 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
9034 UnionRect (&rect, &(**gdh).gdRect, &rect);
9036 dpyinfo->height = rect.bottom - rect.top;
9037 dpyinfo->width = rect.right - rect.left;
9039 #endif /* !MAC_OSX */
9043 /***********************************************************************
9044 Initialization (Mac OS Classic)
9045 ***********************************************************************/
9047 #ifdef MAC_OS8
9048 extern void init_emacs_passwd_dir ();
9049 extern int emacs_main (int, char **, char **);
9051 extern void initialize_applescript();
9052 extern void terminate_applescript();
9054 static void
9055 do_get_menus (void)
9057 Handle menubar_handle;
9058 MenuRef menu;
9060 menubar_handle = GetNewMBar (128);
9061 if(menubar_handle == NULL)
9062 abort ();
9063 SetMenuBar (menubar_handle);
9064 DrawMenuBar ();
9066 #if !TARGET_API_MAC_CARBON
9067 menu = GetMenuRef (M_APPLE);
9068 if (menu != NULL)
9069 AppendResMenu (menu, 'DRVR');
9070 else
9071 abort ();
9072 #endif
9075 static void
9076 do_init_managers (void)
9078 #if !TARGET_API_MAC_CARBON
9079 InitGraf (&qd.thePort);
9080 InitFonts ();
9081 FlushEvents (everyEvent, 0);
9082 InitWindows ();
9083 InitMenus ();
9084 TEInit ();
9085 InitDialogs (NULL);
9086 #endif /* !TARGET_API_MAC_CARBON */
9087 InitCursor ();
9089 #if !TARGET_API_MAC_CARBON
9090 /* set up some extra stack space for use by emacs */
9091 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
9093 /* MaxApplZone must be called for AppleScript to execute more
9094 complicated scripts */
9095 MaxApplZone ();
9096 MoreMasters ();
9097 #endif /* !TARGET_API_MAC_CARBON */
9100 static void
9101 do_check_ram_size (void)
9103 SInt32 physical_ram_size, logical_ram_size;
9105 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9106 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9107 || physical_ram_size > (1 << VALBITS)
9108 || logical_ram_size > (1 << VALBITS))
9110 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9111 exit (1);
9115 #if __profile__
9116 void
9117 profiler_exit_proc ()
9119 ProfilerDump ("\pEmacs.prof");
9120 ProfilerTerm ();
9122 #endif
9124 /* These few functions implement Emacs as a normal Mac application
9125 (almost): set up the heap and the Toolbox, handle necessary system
9126 events plus a few simple menu events. They also set up Emacs's
9127 access to functions defined in the rest of this file. Emacs uses
9128 function hooks to perform all its terminal I/O. A complete list of
9129 these functions appear in termhooks.h. For what they do, read the
9130 comments there and see also w32term.c and xterm.c. What's
9131 noticeably missing here is the event loop, which is normally
9132 present in most Mac application. After performing the necessary
9133 Mac initializations, main passes off control to emacs_main
9134 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9135 (defined further below) to read input. This is where
9136 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9138 #undef main
9140 main (void)
9142 #if __profile__ /* is the profiler on? */
9143 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
9144 exit(1);
9145 #endif
9147 #if __MWERKS__
9148 /* set creator and type for files created by MSL */
9149 _fcreator = MAC_EMACS_CREATOR_CODE;
9150 _ftype = 'TEXT';
9151 #endif
9153 do_init_managers ();
9155 do_get_menus ();
9157 #ifndef USE_LSB_TAG
9158 do_check_ram_size ();
9159 #endif
9161 init_emacs_passwd_dir ();
9163 init_environ ();
9165 init_coercion_handler ();
9167 initialize_applescript ();
9169 init_apple_event_handler ();
9171 init_dm_notification_handler ();
9174 char **argv;
9175 int argc = 0;
9177 /* set up argv array from STR# resource */
9178 get_string_list (&argv, ARGV_STRING_LIST_ID);
9179 while (argv[argc])
9180 argc++;
9182 /* free up AppleScript resources on exit */
9183 atexit (terminate_applescript);
9185 #if __profile__ /* is the profiler on? */
9186 atexit (profiler_exit_proc);
9187 #endif
9189 /* 3rd param "envp" never used in emacs_main */
9190 (void) emacs_main (argc, argv, 0);
9193 /* Never reached - real exit in Fkill_emacs */
9194 return 0;
9197 /* Need to override CodeWarrior's input function so no conversion is
9198 done on newlines Otherwise compiled functions in .elc files will be
9199 read incorrectly. Defined in ...:MSL C:MSL
9200 Common:Source:buffer_io.c. */
9201 #ifdef __MWERKS__
9202 void
9203 __convert_to_newlines (unsigned char * p, size_t * n)
9205 #pragma unused(p,n)
9208 void
9209 __convert_from_newlines (unsigned char * p, size_t * n)
9211 #pragma unused(p,n)
9213 #endif
9215 void
9216 make_mac_terminal_frame (struct frame *f)
9218 Lisp_Object frame;
9219 Rect r;
9221 XSETFRAME (frame, f);
9223 f->output_method = output_mac;
9224 f->output_data.mac = (struct mac_output *)
9225 xmalloc (sizeof (struct mac_output));
9226 bzero (f->output_data.mac, sizeof (struct mac_output));
9228 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9230 FRAME_COLS (f) = 96;
9231 FRAME_LINES (f) = 4;
9233 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9234 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9236 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9238 f->output_data.mac->cursor_pixel = 0;
9239 f->output_data.mac->border_pixel = 0x00ff00;
9240 f->output_data.mac->mouse_pixel = 0xff00ff;
9241 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9243 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9244 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9245 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9246 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9247 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9248 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9250 FRAME_FONTSET (f) = -1;
9251 f->output_data.mac->explicit_parent = 0;
9252 f->left_pos = 8;
9253 f->top_pos = 32;
9254 f->border_width = 0;
9256 f->internal_border_width = 0;
9258 f->auto_raise = 1;
9259 f->auto_lower = 1;
9261 f->new_text_cols = 0;
9262 f->new_text_lines = 0;
9264 SetRect (&r, f->left_pos, f->top_pos,
9265 f->left_pos + FRAME_PIXEL_WIDTH (f),
9266 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9268 BLOCK_INPUT;
9270 if (!(FRAME_MAC_WINDOW (f) =
9271 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9272 (WindowRef) -1, 1, (long) f->output_data.mac)))
9273 abort ();
9274 /* so that update events can find this mac_output struct */
9275 f->output_data.mac->mFP = f; /* point back to emacs frame */
9277 UNBLOCK_INPUT;
9279 x_make_gc (f);
9281 /* Need to be initialized for unshow_buffer in window.c. */
9282 selected_window = f->selected_window;
9284 Fmodify_frame_parameters (frame,
9285 Fcons (Fcons (Qfont,
9286 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9287 Fmodify_frame_parameters (frame,
9288 Fcons (Fcons (Qforeground_color,
9289 build_string ("black")), Qnil));
9290 Fmodify_frame_parameters (frame,
9291 Fcons (Fcons (Qbackground_color,
9292 build_string ("white")), Qnil));
9294 #endif /* MAC_OS8 */
9297 /***********************************************************************
9298 Initialization
9299 ***********************************************************************/
9301 static int mac_initialized = 0;
9303 static XrmDatabase
9304 mac_make_rdb (xrm_option)
9305 const char *xrm_option;
9307 XrmDatabase database;
9309 database = xrm_get_preference_database (NULL);
9310 if (xrm_option)
9311 xrm_merge_string_database (database, xrm_option);
9313 return database;
9316 struct mac_display_info *
9317 mac_term_init (display_name, xrm_option, resource_name)
9318 Lisp_Object display_name;
9319 char *xrm_option;
9320 char *resource_name;
9322 struct mac_display_info *dpyinfo;
9324 BLOCK_INPUT;
9326 if (!mac_initialized)
9328 mac_initialize ();
9329 mac_initialized = 1;
9332 if (x_display_list)
9333 error ("Sorry, this version can only handle one display");
9335 dpyinfo = &one_mac_display_info;
9336 bzero (dpyinfo, sizeof (*dpyinfo));
9338 #ifdef MAC_OSX
9339 dpyinfo->mac_id_name
9340 = (char *) xmalloc (SCHARS (Vinvocation_name)
9341 + SCHARS (Vsystem_name)
9342 + 2);
9343 sprintf (dpyinfo->mac_id_name, "%s@%s",
9344 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9345 #else
9346 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9347 strcpy (dpyinfo->mac_id_name, "Mac Display");
9348 #endif
9350 dpyinfo->reference_count = 0;
9351 dpyinfo->resx = 72.0;
9352 dpyinfo->resy = 72.0;
9354 mac_get_screen_info (dpyinfo);
9356 dpyinfo->grabbed = 0;
9357 dpyinfo->root_window = NULL;
9358 dpyinfo->image_cache = make_image_cache ();
9360 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9361 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9362 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9363 dpyinfo->mouse_face_window = Qnil;
9364 dpyinfo->mouse_face_overlay = Qnil;
9365 dpyinfo->mouse_face_hidden = 0;
9367 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9369 /* Put this display on the chain. */
9370 dpyinfo->next = x_display_list;
9371 x_display_list = dpyinfo;
9373 /* Put it on x_display_name_list. */
9374 x_display_name_list = Fcons (Fcons (display_name,
9375 Fcons (Qnil, dpyinfo->xrdb)),
9376 x_display_name_list);
9377 dpyinfo->name_list_element = XCAR (x_display_name_list);
9379 UNBLOCK_INPUT;
9381 return dpyinfo;
9384 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9386 void
9387 x_delete_display (dpyinfo)
9388 struct mac_display_info *dpyinfo;
9390 int i;
9392 /* Discard this display from x_display_name_list and x_display_list.
9393 We can't use Fdelq because that can quit. */
9394 if (! NILP (x_display_name_list)
9395 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9396 x_display_name_list = XCDR (x_display_name_list);
9397 else
9399 Lisp_Object tail;
9401 tail = x_display_name_list;
9402 while (CONSP (tail) && CONSP (XCDR (tail)))
9404 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9406 XSETCDR (tail, XCDR (XCDR (tail)));
9407 break;
9409 tail = XCDR (tail);
9413 if (x_display_list == dpyinfo)
9414 x_display_list = dpyinfo->next;
9415 else
9417 struct x_display_info *tail;
9419 for (tail = x_display_list; tail; tail = tail->next)
9420 if (tail->next == dpyinfo)
9421 tail->next = tail->next->next;
9424 /* Free the font names in the font table. */
9425 for (i = 0; i < dpyinfo->n_fonts; i++)
9426 if (dpyinfo->font_table[i].name)
9428 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9429 xfree (dpyinfo->font_table[i].full_name);
9430 xfree (dpyinfo->font_table[i].name);
9433 if (dpyinfo->font_table)
9435 if (dpyinfo->font_table->font_encoder)
9436 xfree (dpyinfo->font_table->font_encoder);
9437 xfree (dpyinfo->font_table);
9439 if (dpyinfo->mac_id_name)
9440 xfree (dpyinfo->mac_id_name);
9442 if (x_display_list == 0)
9444 mac_clear_font_name_table ();
9445 bzero (dpyinfo, sizeof (*dpyinfo));
9450 /* Set up use of X before we make the first connection. */
9452 extern frame_parm_handler mac_frame_parm_handlers[];
9454 static struct redisplay_interface x_redisplay_interface =
9456 mac_frame_parm_handlers,
9457 x_produce_glyphs,
9458 x_write_glyphs,
9459 x_insert_glyphs,
9460 x_clear_end_of_line,
9461 x_scroll_run,
9462 x_after_update_window_line,
9463 x_update_window_begin,
9464 x_update_window_end,
9465 x_cursor_to,
9466 x_flush,
9467 #if USE_CG_DRAWING
9468 mac_flush_display_optional,
9469 #else
9470 0, /* flush_display_optional */
9471 #endif
9472 x_clear_window_mouse_face,
9473 x_get_glyph_overhangs,
9474 x_fix_overlapping_area,
9475 x_draw_fringe_bitmap,
9476 #if USE_CG_DRAWING
9477 mac_define_fringe_bitmap,
9478 mac_destroy_fringe_bitmap,
9479 #else
9480 0, /* define_fringe_bitmap */
9481 0, /* destroy_fringe_bitmap */
9482 #endif
9483 mac_per_char_metric,
9484 mac_encode_char,
9485 mac_compute_glyph_string_overhangs,
9486 x_draw_glyph_string,
9487 mac_define_frame_cursor,
9488 mac_clear_frame_area,
9489 mac_draw_window_cursor,
9490 mac_draw_vertical_window_border,
9491 mac_shift_glyphs_for_insert
9494 void
9495 mac_initialize ()
9497 rif = &x_redisplay_interface;
9499 clear_frame_hook = x_clear_frame;
9500 ins_del_lines_hook = x_ins_del_lines;
9501 delete_glyphs_hook = x_delete_glyphs;
9502 ring_bell_hook = XTring_bell;
9503 reset_terminal_modes_hook = XTreset_terminal_modes;
9504 set_terminal_modes_hook = XTset_terminal_modes;
9505 update_begin_hook = x_update_begin;
9506 update_end_hook = x_update_end;
9507 set_terminal_window_hook = XTset_terminal_window;
9508 read_socket_hook = XTread_socket;
9509 frame_up_to_date_hook = XTframe_up_to_date;
9510 mouse_position_hook = XTmouse_position;
9511 frame_rehighlight_hook = XTframe_rehighlight;
9512 frame_raise_lower_hook = XTframe_raise_lower;
9514 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9515 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9516 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9517 judge_scroll_bars_hook = XTjudge_scroll_bars;
9519 scroll_region_ok = 1; /* we'll scroll partial frames */
9520 char_ins_del_ok = 1;
9521 line_ins_del_ok = 1; /* we'll just blt 'em */
9522 fast_clear_end_of_line = 1; /* X does this well */
9523 memory_below_frame = 0; /* we don't remember what scrolls
9524 off the bottom */
9525 baud_rate = 19200;
9527 last_tool_bar_item = -1;
9529 /* Try to use interrupt input; if we can't, then start polling. */
9530 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9532 BLOCK_INPUT;
9534 #if TARGET_API_MAC_CARBON
9535 #ifdef MAC_OSX
9536 init_coercion_handler ();
9538 init_dm_notification_handler ();
9539 #endif
9541 install_application_handler ();
9543 mac_toolbox_initialize ();
9545 #ifdef MAC_OSX
9546 if (!inhibit_window_system)
9548 static const ProcessSerialNumber psn = {0, kCurrentProcess};
9550 SetFrontProcess (&psn);
9552 #endif
9553 #endif
9555 #if USE_CG_DRAWING
9556 init_cg_color ();
9558 mac_init_fringe ();
9559 #endif
9561 UNBLOCK_INPUT;
9565 void
9566 syms_of_macterm ()
9568 #if 0
9569 staticpro (&x_error_message_string);
9570 x_error_message_string = Qnil;
9571 #endif
9573 Qcontrol = intern ("control"); staticpro (&Qcontrol);
9574 Qmeta = intern ("meta"); staticpro (&Qmeta);
9575 Qalt = intern ("alt"); staticpro (&Qalt);
9576 Qhyper = intern ("hyper"); staticpro (&Qhyper);
9577 Qsuper = intern ("super"); staticpro (&Qsuper);
9578 Qmodifier_value = intern ("modifier-value");
9579 staticpro (&Qmodifier_value);
9581 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
9582 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
9583 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9584 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9585 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9587 #if TARGET_API_MAC_CARBON
9588 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
9589 #ifdef MAC_OSX
9590 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
9591 staticpro (&Qtoolbar_switch_mode);
9592 #if USE_MAC_FONT_PANEL
9593 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
9594 Qselection = intern ("selection"); staticpro (&Qselection);
9595 #endif
9597 Qservice = intern ("service"); staticpro (&Qservice);
9598 Qpaste = intern ("paste"); staticpro (&Qpaste);
9599 Qperform = intern ("perform"); staticpro (&Qperform);
9601 Qmouse_drag_overlay = intern ("mouse-drag-overlay");
9602 staticpro (&Qmouse_drag_overlay);
9603 #endif
9604 #if USE_MAC_TSM
9605 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
9606 Qupdate_active_input_area = intern ("update-active-input-area");
9607 staticpro (&Qupdate_active_input_area);
9608 Qunicode_for_key_event = intern ("unicode-for-key-event");
9609 staticpro (&Qunicode_for_key_event);
9610 #endif
9611 #endif
9613 #ifdef MAC_OSX
9614 Fprovide (intern ("mac-carbon"), Qnil);
9615 #endif
9617 staticpro (&Qreverse);
9618 Qreverse = intern ("reverse");
9620 staticpro (&x_display_name_list);
9621 x_display_name_list = Qnil;
9623 staticpro (&last_mouse_scroll_bar);
9624 last_mouse_scroll_bar = Qnil;
9626 staticpro (&fm_font_family_alist);
9627 fm_font_family_alist = Qnil;
9629 #if USE_ATSUI
9630 staticpro (&atsu_font_id_hash);
9631 atsu_font_id_hash = Qnil;
9633 staticpro (&fm_style_face_attributes_alist);
9634 fm_style_face_attributes_alist = Qnil;
9635 #endif
9637 #if USE_MAC_TSM
9638 staticpro (&saved_ts_script_language_on_focus);
9639 saved_ts_script_language_on_focus = Qnil;
9640 #endif
9642 /* We don't yet support this, but defining this here avoids whining
9643 from cus-start.el and other places, like "M-x set-variable". */
9644 DEFVAR_BOOL ("x-use-underline-position-properties",
9645 &x_use_underline_position_properties,
9646 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9647 A value of nil means ignore them. If you encounter fonts with bogus
9648 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9649 to 4.1, set this to nil.
9651 NOTE: Not supported on Mac yet. */);
9652 x_use_underline_position_properties = 0;
9654 DEFVAR_BOOL ("x-underline-at-descent-line",
9655 &x_underline_at_descent_line,
9656 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
9657 A value of nil means to draw the underline according to the value of the
9658 variable `x-use-underline-position-properties', which is usually at the
9659 baseline level. The default value is nil. */);
9660 x_underline_at_descent_line = 0;
9662 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9663 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9664 #ifdef USE_TOOLKIT_SCROLL_BARS
9665 Vx_toolkit_scroll_bars = Qt;
9666 #else
9667 Vx_toolkit_scroll_bars = Qnil;
9668 #endif
9670 staticpro (&last_mouse_motion_frame);
9671 last_mouse_motion_frame = Qnil;
9673 /* Variables to configure modifier key assignment. */
9675 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
9676 doc: /* *Modifier key assumed when the Mac control key is pressed.
9677 The value can be `control', `meta', `alt', `hyper', or `super' for the
9678 respective modifier. The default is `control'. */);
9679 Vmac_control_modifier = Qcontrol;
9681 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9682 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
9683 The value can be `control', `meta', `alt', `hyper', or `super' for the
9684 respective modifier. If the value is nil then the key will act as the
9685 normal Mac control modifier, and the option key can be used to compose
9686 characters depending on the chosen Mac keyboard setting. */);
9687 Vmac_option_modifier = Qnil;
9689 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
9690 doc: /* *Modifier key assumed when the Mac command key is pressed.
9691 The value can be `control', `meta', `alt', `hyper', or `super' for the
9692 respective modifier. The default is `meta'. */);
9693 Vmac_command_modifier = Qmeta;
9695 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
9696 doc: /* *Modifier key assumed when the Mac function key is pressed.
9697 The value can be `control', `meta', `alt', `hyper', or `super' for the
9698 respective modifier. Note that remapping the function key may lead to
9699 unexpected results for some keys on non-US/GB keyboards. */);
9700 Vmac_function_modifier = Qnil;
9702 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9703 &Vmac_emulate_three_button_mouse,
9704 doc: /* *Specify a way of three button mouse emulation.
9705 The value can be nil, t, or the symbol `reverse'.
9706 A value of nil means that no emulation should be done and the modifiers
9707 should be placed on the mouse-1 event.
9708 t means that when the option-key is held down while pressing the mouse
9709 button, the click will register as mouse-2 and while the command-key
9710 is held down, the click will register as mouse-3.
9711 The symbol `reverse' means that the option-key will register for
9712 mouse-3 and the command-key will register for mouse-2. */);
9713 Vmac_emulate_three_button_mouse = Qnil;
9715 #if TARGET_API_MAC_CARBON
9716 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
9717 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
9718 Otherwise, the right click will be treated as mouse-2 and the wheel
9719 button will be mouse-3. */);
9720 mac_wheel_button_is_mouse_2 = 1;
9722 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
9723 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
9724 mac_pass_command_to_system = 1;
9726 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
9727 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
9728 mac_pass_control_to_system = 1;
9730 #endif
9732 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
9733 doc: /* *If non-nil, allow anti-aliasing.
9734 The text will be rendered using Core Graphics text rendering which
9735 may anti-alias the text. */);
9736 #if USE_CG_DRAWING
9737 mac_use_core_graphics = 1;
9738 #else
9739 mac_use_core_graphics = 0;
9740 #endif
9742 /* Register an entry for `mac-roman' so that it can be used when
9743 creating the terminal frame on Mac OS 9 before loading
9744 term/mac-win.elc. */
9745 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
9746 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
9747 Each entry should be of the form:
9749 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
9751 where CHARSET-NAME is a string used in font names to identify the
9752 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
9753 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
9754 Vmac_charset_info_alist =
9755 Fcons (list3 (build_string ("mac-roman"),
9756 make_number (smRoman), Qnil), Qnil);
9758 #if USE_MAC_TSM
9759 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
9760 doc: /* Overlay used to display Mac TSM active input area. */);
9761 Vmac_ts_active_input_overlay = Qnil;
9763 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf,
9764 doc: /* Byte sequence of the current Mac TSM active input area. */);
9765 /* `empty_string' is not ready yet on Mac OS Classic. */
9766 Vmac_ts_active_input_buf = build_string ("");
9768 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
9769 doc: /* *How to change Mac TSM script/language when a frame gets focus.
9770 If the value is t, the input script and language are restored to those
9771 used in the last focus frame. If the value is a pair of integers, the
9772 input script and language codes, which are defined in the Script
9773 Manager, are set to its car and cdr parts, respectively. Otherwise,
9774 Emacs doesn't set them and thus follows the system default behavior. */);
9775 Vmac_ts_script_language_on_focus = Qnil;
9776 #endif
9779 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9780 (do not change this comment) */