(mac_draw_rectangle) [USE_CG_DRAWING]: Fix rectangle calculation.
[emacs.git] / src / macterm.c
blobd0012e1116f0e816a29e01e5d0a6d85699e69aea
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
479 CGContextRef context;
481 context = mac_begin_cg_clip (f, gc);
482 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
483 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
484 mac_end_cg_clip (f);
485 #else
486 Rect r;
488 mac_begin_clip (f, gc);
489 RGBBackColor (GC_BACK_COLOR (gc));
490 SetRect (&r, x, y, x + width, y + height);
491 EraseRect (&r);
492 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
493 mac_end_clip (f, gc);
494 #endif
498 /* Mac version of XClearArea. */
500 void
501 mac_clear_area (f, x, y, width, height)
502 struct frame *f;
503 int x, y;
504 unsigned int width, height;
506 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
509 /* Mac version of XClearWindow. */
511 static void
512 mac_clear_window (f)
513 struct frame *f;
515 #if USE_CG_DRAWING
516 CGContextRef context;
517 GC gc = FRAME_NORMAL_GC (f);
519 context = mac_begin_cg_clip (f, NULL);
520 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
521 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
522 FRAME_PIXEL_HEIGHT (f)));
523 mac_end_cg_clip (f);
524 #else /* !USE_CG_DRAWING */
525 mac_begin_clip (f, NULL);
526 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
527 #if TARGET_API_MAC_CARBON
529 Rect r;
531 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
532 EraseRect (&r);
534 #else /* not TARGET_API_MAC_CARBON */
535 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
536 #endif /* not TARGET_API_MAC_CARBON */
537 mac_end_clip (f, NULL);
538 #endif
542 /* Mac replacement for XCopyArea. */
544 #if USE_CG_DRAWING
545 static void
546 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
547 dest_x, dest_y, overlay_p)
548 CGImageRef image;
549 struct frame *f;
550 GC gc;
551 int src_x, src_y;
552 unsigned int width, height;
553 int dest_x, dest_y, overlay_p;
555 CGContextRef context;
556 CGRect dest_rect, bounds;
558 context = mac_begin_cg_clip (f, gc);
559 dest_rect = mac_rect_make (f, dest_x, dest_y, width, height);
560 bounds = mac_rect_make (f, dest_x - src_x, dest_y - src_y,
561 CGImageGetWidth (image), CGImageGetHeight (image));
562 if (!overlay_p)
564 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
565 CGContextFillRect (context, dest_rect);
567 CGContextClipToRect (context, dest_rect);
568 CGContextTranslateCTM (context,
569 CGRectGetMinX (bounds), CGRectGetMaxY (bounds));
570 CGContextScaleCTM (context, 1, -1);
571 if (CGImageIsMask (image))
572 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
573 bounds.origin = CGPointZero;
574 CGContextDrawImage (context, bounds, image);
575 mac_end_cg_clip (f);
578 #else /* !USE_CG_DRAWING */
580 static void
581 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
582 struct frame *f;
583 GC gc;
584 int x, y, width, height;
585 unsigned short *bits;
586 int overlay_p;
588 BitMap bitmap;
589 Rect r;
591 bitmap.rowBytes = sizeof(unsigned short);
592 bitmap.baseAddr = (char *)bits;
593 SetRect (&(bitmap.bounds), 0, 0, width, height);
595 mac_begin_clip (f, gc);
596 RGBForeColor (GC_FORE_COLOR (gc));
597 RGBBackColor (GC_BACK_COLOR (gc));
598 SetRect (&r, x, y, x + width, y + height);
599 #if TARGET_API_MAC_CARBON
601 CGrafPtr port;
603 GetPort (&port);
604 LockPortBits (port);
605 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
606 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
607 UnlockPortBits (port);
609 #else /* not TARGET_API_MAC_CARBON */
610 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
611 overlay_p ? srcOr : srcCopy, 0);
612 #endif /* not TARGET_API_MAC_CARBON */
613 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
614 mac_end_clip (f, gc);
616 #endif /* !USE_CG_DRAWING */
619 /* Mac replacement for XCreateBitmapFromBitmapData. */
621 static void
622 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
623 BitMap *bitmap;
624 char *bits;
625 int w, h;
627 static const unsigned char swap_nibble[16]
628 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
629 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
630 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
631 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
632 int i, j, w1;
633 char *p;
635 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
636 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
637 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
638 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
639 for (i = 0; i < h; i++)
641 p = bitmap->baseAddr + i * bitmap->rowBytes;
642 for (j = 0; j < w1; j++)
644 /* Bitswap XBM bytes to match how Mac does things. */
645 unsigned char c = *bits++;
646 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
647 | (swap_nibble[(c>>4) & 0xf]));
651 SetRect (&(bitmap->bounds), 0, 0, w, h);
655 static void
656 mac_free_bitmap (bitmap)
657 BitMap *bitmap;
659 xfree (bitmap->baseAddr);
663 Pixmap
664 XCreatePixmap (display, w, width, height, depth)
665 Display *display;
666 Window w;
667 unsigned int width, height;
668 unsigned int depth;
670 #if USE_MAC_IMAGE_IO
671 XImagePtr ximg;
673 ximg = xmalloc (sizeof (*ximg));
674 ximg->width = width;
675 ximg->height = height;
676 ximg->bits_per_pixel = depth == 1 ? 8 : 32;
677 ximg->bytes_per_line = width * (ximg->bits_per_pixel / 8);
678 ximg->data = xmalloc (ximg->bytes_per_line * height);
679 return ximg;
680 #else
681 Pixmap pixmap;
682 Rect r;
683 QDErr err;
685 #ifdef MAC_OS8
686 SetPortWindowPort (w);
687 #endif
688 SetRect (&r, 0, 0, width, height);
689 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
690 if (depth == 1)
691 #endif
692 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
693 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
694 else
695 /* CreateCGImageFromPixMaps requires ARGB format. */
696 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
697 #endif
698 if (err != noErr)
699 return NULL;
700 return pixmap;
701 #endif
705 Pixmap
706 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
707 Display *display;
708 Window w;
709 char *data;
710 unsigned int width, height;
711 unsigned long fg, bg;
712 unsigned int depth;
714 Pixmap pixmap;
715 BitMap bitmap;
716 #if USE_MAC_IMAGE_IO
717 CGDataProviderRef provider;
718 CGImageRef image_mask;
719 CGContextRef context;
721 pixmap = XCreatePixmap (display, w, width, height, depth);
722 if (pixmap == NULL)
723 return NULL;
725 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
726 provider = CGDataProviderCreateWithData (NULL, bitmap.baseAddr,
727 bitmap.rowBytes * height, NULL);
728 image_mask = CGImageMaskCreate (width, height, 1, 1, bitmap.rowBytes,
729 provider, NULL, 0);
730 CGDataProviderRelease (provider);
732 context = CGBitmapContextCreate (pixmap->data, width, height, 8,
733 pixmap->bytes_per_line,
734 mac_cg_color_space_rgb,
735 kCGImageAlphaNoneSkipFirst
736 | kCGBitmapByteOrder32Host);
738 CG_SET_FILL_COLOR (context, fg);
739 CGContextFillRect (context, CGRectMake (0, 0, width, height));
740 CG_SET_FILL_COLOR (context, bg);
741 CGContextDrawImage (context, CGRectMake (0, 0, width, height), image_mask);
742 CGContextRelease (context);
743 CGImageRelease (image_mask);
744 #else
745 CGrafPtr old_port;
746 GDHandle old_gdh;
747 static GC gc = NULL;
749 if (gc == NULL)
750 gc = XCreateGC (display, w, 0, NULL);
752 pixmap = XCreatePixmap (display, w, width, height, depth);
753 if (pixmap == NULL)
754 return NULL;
756 GetGWorld (&old_port, &old_gdh);
757 SetGWorld (pixmap, NULL);
758 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
759 XSetForeground (display, gc, fg);
760 XSetBackground (display, gc, bg);
761 RGBForeColor (GC_FORE_COLOR (gc));
762 RGBBackColor (GC_BACK_COLOR (gc));
763 LockPixels (GetGWorldPixMap (pixmap));
764 #if TARGET_API_MAC_CARBON
765 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
766 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
767 #else /* not TARGET_API_MAC_CARBON */
768 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
769 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
770 #endif /* not TARGET_API_MAC_CARBON */
771 UnlockPixels (GetGWorldPixMap (pixmap));
772 SetGWorld (old_port, old_gdh);
773 #endif
774 mac_free_bitmap (&bitmap);
776 return pixmap;
780 void
781 XFreePixmap (display, pixmap)
782 Display *display;
783 Pixmap pixmap;
785 #if USE_MAC_IMAGE_IO
786 if (pixmap)
788 if (pixmap->data)
789 xfree (pixmap->data);
790 xfree (pixmap);
792 #else
793 DisposeGWorld (pixmap);
794 #endif
798 /* Mac replacement for XFillRectangle. */
800 static void
801 mac_fill_rectangle (f, gc, x, y, width, height)
802 struct frame *f;
803 GC gc;
804 int x, y;
805 unsigned int width, height;
807 #if USE_CG_DRAWING
808 CGContextRef context;
810 context = mac_begin_cg_clip (f, gc);
811 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
812 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
813 mac_end_cg_clip (f);
814 #else
815 Rect r;
817 mac_begin_clip (f, gc);
818 RGBForeColor (GC_FORE_COLOR (gc));
819 SetRect (&r, x, y, x + width, y + height);
820 PaintRect (&r); /* using foreground color of gc */
821 mac_end_clip (f, gc);
822 #endif
826 /* Mac replacement for XDrawRectangle: dest is a window. */
828 static void
829 mac_draw_rectangle (f, gc, x, y, width, height)
830 struct frame *f;
831 GC gc;
832 int x, y;
833 unsigned int width, height;
835 #if USE_CG_DRAWING
836 CGContextRef context;
837 CGRect rect;
839 context = mac_begin_cg_clip (f, gc);
840 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc);
841 rect = mac_rect_make (f, x, y, width + 1, height + 1);
842 CGContextStrokeRect (context, CGRectInset (rect, 0.5f, 0.5f));
843 mac_end_cg_clip (f);
844 #else
845 Rect r;
847 mac_begin_clip (f, gc);
848 RGBForeColor (GC_FORE_COLOR (gc));
849 SetRect (&r, x, y, x + width + 1, y + height + 1);
850 FrameRect (&r); /* using foreground color of gc */
851 mac_end_clip (f, gc);
852 #endif
856 static void
857 mac_invert_rectangle (f, x, y, width, height)
858 struct frame *f;
859 int x, y;
860 unsigned int width, height;
862 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
863 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
864 if (CGContextSetBlendMode != NULL)
865 #endif
867 CGContextRef context;
869 context = mac_begin_cg_clip (f, NULL);
870 CGContextSetRGBFillColor (context, 1.0f, 1.0f, 1.0f, 1.0f);
871 CGContextSetBlendMode (context, kCGBlendModeDifference);
872 CGContextFillRect (context, mac_rect_make (f, x, y, width, height));
873 mac_end_cg_clip (f);
875 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 && MAC_OS_X_VERSION_MIN_REQUIRED >= 1020
876 else /* CGContextSetBlendMode == NULL */
877 #endif
878 #endif /* USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */
879 #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)
881 Rect r;
883 mac_begin_clip (f, NULL);
884 SetRect (&r, x, y, x + width, y + height);
885 InvertRect (&r);
886 mac_end_clip (f, NULL);
888 #endif
892 #if USE_ATSUI
893 static OSStatus
894 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
895 ConstUniCharArrayPtr text;
896 UniCharCount text_length;
897 ATSUStyle style;
898 ATSUTextLayout *text_layout;
900 OSStatus err;
901 static ATSUTextLayout saved_text_layout = NULL;
903 if (saved_text_layout == NULL)
905 static const UniCharCount lengths[] = {kATSUToTextEnd};
906 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
907 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
908 static ATSLineLayoutOptions line_layout =
909 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
910 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
911 | kATSLineUseQDRendering
912 #else
913 kATSLineIsDisplayOnly | kATSLineFractDisable
914 #endif
916 static const ATSUAttributeValuePtr values[] = {&line_layout};
918 err = ATSUCreateTextLayoutWithTextPtr (text,
919 kATSUFromTextBeginning,
920 kATSUToTextEnd,
921 text_length,
922 1, lengths, &style,
923 &saved_text_layout);
924 if (err == noErr)
925 err = ATSUSetLayoutControls (saved_text_layout,
926 sizeof (tags) / sizeof (tags[0]),
927 tags, sizes, values);
928 if (err == noErr)
929 err = ATSUSetTransientFontMatching (saved_text_layout, true);
931 else
933 err = ATSUSetRunStyle (saved_text_layout, style,
934 kATSUFromTextBeginning, kATSUToTextEnd);
935 if (err == noErr)
936 err = ATSUSetTextPointerLocation (saved_text_layout, text,
937 kATSUFromTextBeginning,
938 kATSUToTextEnd,
939 text_length);
942 if (err == noErr)
943 *text_layout = saved_text_layout;
944 return err;
948 static void
949 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
950 overstrike_p, bytes_per_char)
951 struct frame *f;
952 GC gc;
953 int x, y;
954 char *buf;
955 int nchars, bg_width, overstrike_p, bytes_per_char;
957 OSStatus err;
958 ATSUTextLayout text_layout;
960 xassert (bytes_per_char == 2);
962 #ifndef WORDS_BIG_ENDIAN
964 int i;
965 UniChar *text = (UniChar *)buf;
967 for (i = 0; i < nchars; i++)
968 text[i] = EndianU16_BtoN (text[i]);
970 #endif
971 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
972 nchars,
973 GC_FONT (gc)->mac_style,
974 &text_layout);
975 if (err != noErr)
976 return;
977 #ifdef MAC_OSX
978 if (!mac_use_core_graphics)
980 #endif
981 mac_begin_clip (f, gc);
982 RGBForeColor (GC_FORE_COLOR (gc));
983 if (bg_width)
985 Rect r;
987 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
988 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
989 RGBBackColor (GC_BACK_COLOR (gc));
990 EraseRect (&r);
991 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
993 MoveTo (x, y);
994 ATSUDrawText (text_layout,
995 kATSUFromTextBeginning, kATSUToTextEnd,
996 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
997 if (overstrike_p)
999 MoveTo (x + 1, y);
1000 ATSUDrawText (text_layout,
1001 kATSUFromTextBeginning, kATSUToTextEnd,
1002 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
1004 mac_end_clip (f, gc);
1005 #ifdef MAC_OSX
1007 else
1009 static CGContextRef context;
1010 static const ATSUAttributeTag tags[] = {kATSUCGContextTag};
1011 static const ByteCount sizes[] = {sizeof (CGContextRef)};
1012 static const ATSUAttributeValuePtr values[] = {&context};
1014 #if USE_CG_DRAWING
1015 context = mac_begin_cg_clip (f, gc);
1016 #else
1017 CGrafPtr port;
1019 GetPort (&port);
1020 QDBeginCGContext (port, &context);
1021 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
1022 if (gc->n_clip_rects || bg_width)
1024 CGContextScaleCTM (context, 1, -1);
1025 if (gc->n_clip_rects)
1026 CGContextClipToRects (context, gc->clip_rects,
1027 gc->n_clip_rects);
1028 #endif
1029 if (bg_width)
1031 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1032 CGContextFillRect (context,
1033 mac_rect_make (f,
1034 x, y - FONT_BASE (GC_FONT (gc)),
1035 bg_width,
1036 FONT_HEIGHT (GC_FONT (gc))));
1038 CGContextScaleCTM (context, 1, -1);
1039 #if !USE_CG_DRAWING
1041 #endif
1042 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1043 err = ATSUSetLayoutControls (text_layout,
1044 sizeof (tags) / sizeof (tags[0]),
1045 tags, sizes, values);
1046 if (err == noErr)
1048 ATSUDrawText (text_layout,
1049 kATSUFromTextBeginning, kATSUToTextEnd,
1050 Long2Fix (x), Long2Fix (-y));
1051 if (overstrike_p)
1052 ATSUDrawText (text_layout,
1053 kATSUFromTextBeginning, kATSUToTextEnd,
1054 Long2Fix (x + 1), Long2Fix (-y));
1056 #if USE_CG_DRAWING
1057 mac_end_cg_clip (f);
1058 context = NULL;
1059 #else
1060 CGContextSynchronize (context);
1061 QDEndCGContext (port, &context);
1062 #endif
1063 #if 0
1064 /* This doesn't work on Mac OS X 10.1. */
1065 ATSUClearLayoutControls (text_layout,
1066 sizeof (tags) / sizeof (tags[0]), tags);
1067 #else
1068 ATSUSetLayoutControls (text_layout,
1069 sizeof (tags) / sizeof (tags[0]),
1070 tags, sizes, values);
1071 #endif
1073 #endif /* MAC_OSX */
1075 #endif /* USE_ATSUI */
1078 static void
1079 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1080 overstrike_p, bytes_per_char)
1081 struct frame *f;
1082 GC gc;
1083 int x, y;
1084 char *buf;
1085 int nchars, bg_width, overstrike_p, bytes_per_char;
1087 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1088 UInt32 savedFlags;
1089 #endif
1091 mac_begin_clip (f, gc);
1092 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1093 if (mac_use_core_graphics)
1094 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1095 #endif
1096 RGBForeColor (GC_FORE_COLOR (gc));
1097 #ifdef MAC_OS8
1098 if (bg_width)
1100 RGBBackColor (GC_BACK_COLOR (gc));
1101 TextMode (srcCopy);
1103 else
1104 TextMode (srcOr);
1105 #else
1106 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1107 because:
1108 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1109 into an offscreen graphics world first. So performance gain
1110 cannot be expected.)
1111 - It lowers rendering quality.
1112 - Some fonts leave garbage on cursor movement. */
1113 if (bg_width)
1115 Rect r;
1117 RGBBackColor (GC_BACK_COLOR (gc));
1118 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1119 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1120 EraseRect (&r);
1122 TextMode (srcOr);
1123 #endif
1124 TextFont (GC_FONT (gc)->mac_fontnum);
1125 TextSize (GC_FONT (gc)->mac_fontsize);
1126 TextFace (GC_FONT (gc)->mac_fontface);
1127 MoveTo (x, y);
1128 DrawText (buf, 0, nchars * bytes_per_char);
1129 if (overstrike_p)
1131 TextMode (srcOr);
1132 MoveTo (x + 1, y);
1133 DrawText (buf, 0, nchars * bytes_per_char);
1135 if (bg_width)
1136 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1137 mac_end_clip (f, gc);
1139 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1140 if (mac_use_core_graphics)
1141 SwapQDTextFlags(savedFlags);
1142 #endif
1146 static INLINE void
1147 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1148 overstrike_p, bytes_per_char)
1149 struct frame *f;
1150 GC gc;
1151 int x, y;
1152 char *buf;
1153 int nchars, bg_width, overstrike_p, bytes_per_char;
1155 #if USE_ATSUI
1156 if (GC_FONT (gc)->mac_style)
1157 mac_draw_image_string_atsui (f, gc, x, y, buf, nchars, bg_width,
1158 overstrike_p, bytes_per_char);
1159 else
1160 #endif /* USE_ATSUI */
1161 mac_draw_image_string_qd (f, gc, x, y, buf, nchars, bg_width,
1162 overstrike_p, bytes_per_char);
1166 /* Mac replacement for XDrawImageString. */
1168 static void
1169 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1170 struct frame *f;
1171 GC gc;
1172 int x, y;
1173 char *buf;
1174 int nchars, bg_width, overstrike_p;
1176 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width,
1177 overstrike_p, 1);
1181 /* Mac replacement for XDrawImageString16. */
1183 static void
1184 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1185 struct frame *f;
1186 GC gc;
1187 int x, y;
1188 XChar2b *buf;
1189 int nchars, bg_width, overstrike_p;
1191 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width,
1192 overstrike_p, 2);
1196 /* Mac replacement for XQueryTextExtents, but takes a character. If
1197 STYLE is NULL, measurement is done by QuickDraw Text routines for
1198 the font of the current graphics port. If CG_GLYPH is not NULL,
1199 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1201 static OSStatus
1202 mac_query_char_extents (style, c,
1203 font_ascent_return, font_descent_return,
1204 overall_return, cg_glyph)
1205 #if USE_ATSUI
1206 ATSUStyle style;
1207 #else
1208 void *style;
1209 #endif
1210 int c;
1211 int *font_ascent_return, *font_descent_return;
1212 XCharStruct *overall_return;
1213 #if USE_CG_TEXT_DRAWING
1214 CGGlyph *cg_glyph;
1215 #else
1216 void *cg_glyph;
1217 #endif
1219 OSStatus err = noErr;
1220 int width;
1221 Rect char_bounds;
1223 #if USE_ATSUI
1224 if (style)
1226 ATSUTextLayout text_layout;
1227 UniChar ch = c;
1229 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1230 if (err == noErr
1231 && (font_ascent_return || font_descent_return || overall_return))
1233 ATSTrapezoid glyph_bounds;
1235 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1236 kATSUFromTextBeginning, kATSUToTextEnd,
1237 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1238 kATSUseFractionalOrigins,
1239 #else
1240 kATSUseDeviceOrigins,
1241 #endif
1242 1, &glyph_bounds, NULL);
1243 if (err == noErr)
1245 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1246 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1248 width = Fix2Long (glyph_bounds.upperRight.x
1249 - glyph_bounds.upperLeft.x);
1250 if (font_ascent_return)
1251 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1252 if (font_descent_return)
1253 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1256 if (err == noErr && overall_return)
1258 err = ATSUMeasureTextImage (text_layout,
1259 kATSUFromTextBeginning, kATSUToTextEnd,
1260 0, 0, &char_bounds);
1261 if (err == noErr)
1262 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1263 #if USE_CG_TEXT_DRAWING
1264 if (err == noErr && cg_glyph)
1266 OSStatus err1;
1267 ATSUGlyphInfoArray glyph_info_array;
1268 ByteCount count = sizeof (ATSUGlyphInfoArray);
1270 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1271 kATSUToTextEnd, NULL, NULL, NULL);
1272 if (err1 == noErr)
1273 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1274 kATSUToTextEnd, &count,
1275 &glyph_info_array);
1276 if (err1 == noErr
1277 /* Make sure that we don't have to make layout
1278 adjustments. */
1279 && glyph_info_array.glyphs[0].deltaY == 0.0f
1280 && glyph_info_array.glyphs[0].idealX == 0.0f
1281 && glyph_info_array.glyphs[0].screenX == 0)
1283 xassert (glyph_info_array.glyphs[0].glyphID);
1284 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1286 else
1287 *cg_glyph = 0;
1289 #endif
1292 else
1293 #endif
1295 if (font_ascent_return || font_descent_return)
1297 FontInfo font_info;
1299 GetFontInfo (&font_info);
1300 if (font_ascent_return)
1301 *font_ascent_return = font_info.ascent;
1302 if (font_descent_return)
1303 *font_descent_return = font_info.descent;
1305 if (overall_return)
1307 char ch = c;
1309 width = CharWidth (ch);
1310 QDTextBounds (1, &ch, &char_bounds);
1311 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1315 return err;
1319 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1321 static int
1322 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1323 XFontStruct *font_struct;
1324 XChar2b *string;
1325 int nchars;
1326 XCharStruct *overall_return;
1328 int i;
1329 short width = 0, lbearing = 0, rbearing = 0;
1330 XCharStruct *pcm;
1332 for (i = 0; i < nchars; i++)
1334 pcm = mac_per_char_metric (font_struct, string, 0);
1335 if (pcm == NULL)
1336 width += FONT_WIDTH (font_struct);
1337 else
1339 lbearing = min (lbearing, width + pcm->lbearing);
1340 rbearing = max (rbearing, width + pcm->rbearing);
1341 width += pcm->width;
1343 string++;
1346 overall_return->lbearing = lbearing;
1347 overall_return->rbearing = rbearing;
1348 overall_return->width = width;
1350 /* What's the meaning of the return value of XTextExtents16? */
1354 #if USE_CG_TEXT_DRAWING
1355 static int cg_text_anti_aliasing_threshold = 8;
1357 static void
1358 init_cg_text_anti_aliasing_threshold ()
1360 int threshold;
1361 Boolean valid_p;
1363 threshold =
1364 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1365 kCFPreferencesCurrentApplication,
1366 &valid_p);
1367 if (valid_p)
1368 cg_text_anti_aliasing_threshold = threshold;
1371 static int
1372 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p)
1373 struct frame *f;
1374 GC gc;
1375 int x, y;
1376 XChar2b *buf;
1377 int nchars, bg_width, overstrike_p;
1379 CGFloat gx, gy;
1380 int i;
1381 CGContextRef context;
1382 CGGlyph *glyphs;
1383 CGSize *advances;
1385 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1386 return 0;
1388 gx = x;
1389 gy = -y;
1390 glyphs = (CGGlyph *)buf;
1391 advances = alloca (sizeof (CGSize) * nchars);
1392 if (advances == NULL)
1393 return 0;
1394 for (i = 0; i < nchars; i++)
1396 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1398 advances[i].width = pcm->width;
1399 advances[i].height = 0;
1400 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1401 buf++;
1404 #if USE_CG_DRAWING
1405 context = mac_begin_cg_clip (f, gc);
1406 #else
1407 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1408 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
1409 if (gc->n_clip_rects || bg_width)
1411 CGContextScaleCTM (context, 1, -1);
1412 if (gc->n_clip_rects)
1413 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1414 #endif
1415 if (bg_width)
1417 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc);
1418 CGContextFillRect
1419 (context,
1420 mac_rect_make (f, gx, y - FONT_BASE (GC_FONT (gc)),
1421 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1423 CGContextScaleCTM (context, 1, -1);
1424 #if !USE_CG_DRAWING
1426 #endif
1427 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc);
1428 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1429 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1430 CGContextSetTextMatrix (context, CGAffineTransformIdentity);
1431 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1432 CGContextSetShouldAntialias (context, false);
1433 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1434 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1435 if (CGContextShowGlyphsWithAdvances != NULL)
1436 #endif
1438 CGContextSetTextPosition (context, gx, gy);
1439 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1440 if (overstrike_p)
1442 CGContextSetTextPosition (context, gx + 1.0f, gy);
1443 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1446 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1447 else /* CGContextShowGlyphsWithAdvances == NULL */
1448 #endif
1449 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
1450 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1452 for (i = 0; i < nchars; i++)
1454 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1455 if (overstrike_p)
1456 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1);
1457 gx += advances[i].width;
1460 #endif
1461 #if USE_CG_DRAWING
1462 mac_end_cg_clip (f);
1463 #else
1464 CGContextSynchronize (context);
1465 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
1466 #endif
1468 return 1;
1470 #endif
1473 #if !USE_CG_DRAWING
1474 /* Mac replacement for XCopyArea: dest must be window. */
1476 static void
1477 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1478 Pixmap src;
1479 struct frame *f;
1480 GC gc;
1481 int src_x, src_y;
1482 unsigned int width, height;
1483 int dest_x, dest_y;
1485 Rect src_r, dest_r;
1487 mac_begin_clip (f, gc);
1489 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1490 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1492 ForeColor (blackColor);
1493 BackColor (whiteColor);
1495 LockPixels (GetGWorldPixMap (src));
1496 #if TARGET_API_MAC_CARBON
1498 CGrafPtr port;
1500 GetPort (&port);
1501 LockPortBits (port);
1502 CopyBits (GetPortBitMapForCopyBits (src),
1503 GetPortBitMapForCopyBits (port),
1504 &src_r, &dest_r, srcCopy, 0);
1505 UnlockPortBits (port);
1507 #else /* not TARGET_API_MAC_CARBON */
1508 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1509 &src_r, &dest_r, srcCopy, 0);
1510 #endif /* not TARGET_API_MAC_CARBON */
1511 UnlockPixels (GetGWorldPixMap (src));
1513 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1515 mac_end_clip (f, gc);
1519 static void
1520 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1521 width, height, dest_x, dest_y)
1522 Pixmap src, mask;
1523 struct frame *f;
1524 GC gc;
1525 int src_x, src_y;
1526 unsigned int width, height;
1527 int dest_x, dest_y;
1529 Rect src_r, dest_r;
1531 mac_begin_clip (f, gc);
1533 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1534 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1536 ForeColor (blackColor);
1537 BackColor (whiteColor);
1539 LockPixels (GetGWorldPixMap (src));
1540 LockPixels (GetGWorldPixMap (mask));
1541 #if TARGET_API_MAC_CARBON
1543 CGrafPtr port;
1545 GetPort (&port);
1546 LockPortBits (port);
1547 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1548 GetPortBitMapForCopyBits (port),
1549 &src_r, &src_r, &dest_r);
1550 UnlockPortBits (port);
1552 #else /* not TARGET_API_MAC_CARBON */
1553 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1554 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1555 #endif /* not TARGET_API_MAC_CARBON */
1556 UnlockPixels (GetGWorldPixMap (mask));
1557 UnlockPixels (GetGWorldPixMap (src));
1559 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1561 mac_end_clip (f, gc);
1563 #endif /* !USE_CG_DRAWING */
1566 /* Mac replacement for XCopyArea: used only for scrolling. */
1568 #if TARGET_API_MAC_CARBON
1569 /* Defined in mactoolbox.c. */
1570 extern void mac_scroll_area P_ ((struct frame *, GC, int, int,
1571 unsigned int, unsigned int, int, int));
1572 #else /* not TARGET_API_MAC_CARBON */
1573 static void
1574 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1575 struct frame *f;
1576 GC gc;
1577 int src_x, src_y;
1578 unsigned int width, height;
1579 int dest_x, dest_y;
1581 Rect src_r, dest_r;
1582 WindowRef w = FRAME_MAC_WINDOW (f);
1584 mac_begin_clip (f, gc);
1586 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1587 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1589 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1590 color mapping in CopyBits. Otherwise, it will be slow. */
1591 ForeColor (blackColor);
1592 BackColor (whiteColor);
1593 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1595 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1597 mac_end_clip (f, gc);
1599 #endif /* not TARGET_API_MAC_CARBON */
1602 /* Mac replacement for XChangeGC. */
1604 static void
1605 XChangeGC (display, gc, mask, xgcv)
1606 Display *display;
1607 GC gc;
1608 unsigned long mask;
1609 XGCValues *xgcv;
1611 if (mask & GCForeground)
1612 XSetForeground (display, gc, xgcv->foreground);
1613 if (mask & GCBackground)
1614 XSetBackground (display, gc, xgcv->background);
1615 if (mask & GCFont)
1616 XSetFont (display, gc, xgcv->font);
1620 /* Mac replacement for XCreateGC. */
1623 XCreateGC (display, d, mask, xgcv)
1624 Display *display;
1625 void *d;
1626 unsigned long mask;
1627 XGCValues *xgcv;
1629 GC gc = xmalloc (sizeof (*gc));
1631 bzero (gc, sizeof (*gc));
1632 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1633 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1634 if (CGColorGetTypeID != NULL)
1635 #endif
1637 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black;
1638 CGColorRetain (gc->cg_fore_color);
1639 CGColorRetain (gc->cg_back_color);
1641 #endif
1642 XChangeGC (display, gc, mask, xgcv);
1644 return gc;
1648 /* Used in xfaces.c. */
1650 void
1651 XFreeGC (display, gc)
1652 Display *display;
1653 GC gc;
1655 if (gc->clip_region)
1656 DisposeRgn (gc->clip_region);
1657 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1658 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1659 if (CGColorGetTypeID != NULL)
1660 #endif
1662 CGColorRelease (gc->cg_fore_color);
1663 CGColorRelease (gc->cg_back_color);
1665 #endif
1666 xfree (gc);
1670 /* Mac replacement for XGetGCValues. */
1672 static void
1673 XGetGCValues (display, gc, mask, xgcv)
1674 Display *display;
1675 GC gc;
1676 unsigned long mask;
1677 XGCValues *xgcv;
1679 if (mask & GCForeground)
1680 xgcv->foreground = gc->xgcv.foreground;
1681 if (mask & GCBackground)
1682 xgcv->background = gc->xgcv.background;
1683 if (mask & GCFont)
1684 xgcv->font = gc->xgcv.font;
1688 /* Mac replacement for XSetForeground. */
1690 void
1691 XSetForeground (display, gc, color)
1692 Display *display;
1693 GC gc;
1694 unsigned long color;
1696 if (gc->xgcv.foreground != color)
1698 gc->xgcv.foreground = color;
1699 gc->fore_color.red = RED16_FROM_ULONG (color);
1700 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1701 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1702 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1703 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1704 if (CGColorGetTypeID != NULL)
1705 #endif
1707 CGColorRelease (gc->cg_fore_color);
1708 if (color == 0)
1710 gc->cg_fore_color = mac_cg_color_black;
1711 CGColorRetain (gc->cg_fore_color);
1713 else
1715 CGFloat rgba[4];
1717 rgba[0] = gc->fore_color.red / 65535.0f;
1718 rgba[1] = gc->fore_color.green / 65535.0f;
1719 rgba[2] = gc->fore_color.blue / 65535.0f;
1720 rgba[3] = 1.0f;
1721 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1724 #endif
1729 /* Mac replacement for XSetBackground. */
1731 void
1732 XSetBackground (display, gc, color)
1733 Display *display;
1734 GC gc;
1735 unsigned long color;
1737 if (gc->xgcv.background != color)
1739 gc->xgcv.background = color;
1740 gc->back_color.red = RED16_FROM_ULONG (color);
1741 gc->back_color.green = GREEN16_FROM_ULONG (color);
1742 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1743 #if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1744 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
1745 if (CGColorGetTypeID != NULL)
1746 #endif
1748 CGColorRelease (gc->cg_back_color);
1749 if (color == 0)
1751 gc->cg_back_color = mac_cg_color_black;
1752 CGColorRetain (gc->cg_back_color);
1754 else
1756 CGFloat rgba[4];
1758 rgba[0] = gc->back_color.red / 65535.0f;
1759 rgba[1] = gc->back_color.green / 65535.0f;
1760 rgba[2] = gc->back_color.blue / 65535.0f;
1761 rgba[3] = 1.0f;
1762 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba);
1765 #endif
1770 /* Mac replacement for XSetFont. */
1772 static void
1773 XSetFont (display, gc, font)
1774 Display *display;
1775 GC gc;
1776 XFontStruct *font;
1778 gc->xgcv.font = font;
1782 /* Mac replacement for XSetClipRectangles. */
1784 static void
1785 mac_set_clip_rectangles (f, gc, rectangles, n)
1786 struct frame *f;
1787 GC gc;
1788 Rect *rectangles;
1789 int n;
1791 int i;
1793 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1795 gc->n_clip_rects = n;
1796 if (n > 0)
1798 if (gc->clip_region == NULL)
1799 gc->clip_region = NewRgn ();
1800 RectRgn (gc->clip_region, rectangles);
1801 if (n > 1)
1803 RgnHandle region = NewRgn ();
1805 for (i = 1; i < n; i++)
1807 RectRgn (region, rectangles + i);
1808 UnionRgn (gc->clip_region, region, gc->clip_region);
1810 DisposeRgn (region);
1813 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1814 for (i = 0; i < n; i++)
1816 Rect *rect = rectangles + i;
1818 gc->clip_rects[i] = mac_rect_make (f, rect->left, rect->top,
1819 rect->right - rect->left,
1820 rect->bottom - rect->top);
1822 #endif
1826 /* Mac replacement for XSetClipMask. */
1828 static INLINE void
1829 mac_reset_clip_rectangles (f, gc)
1830 struct frame *f;
1831 GC gc;
1833 gc->n_clip_rects = 0;
1836 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1837 Calls to XFlush should be unnecessary because the X output buffer
1838 is flushed automatically as needed by calls to XPending,
1839 XNextEvent, or XWindowEvent according to the XFlush man page.
1840 XTread_socket calls XPending. Removing XFlush improves
1841 performance. */
1843 #define XFlush(DISPLAY) (void) 0
1846 /***********************************************************************
1847 Starting and ending an update
1848 ***********************************************************************/
1850 /* Start an update of frame F. This function is installed as a hook
1851 for update_begin, i.e. it is called when update_begin is called.
1852 This function is called prior to calls to x_update_window_begin for
1853 each window being updated. */
1855 static void
1856 x_update_begin (f)
1857 struct frame *f;
1859 BLOCK_INPUT;
1860 mac_update_begin (f);
1861 UNBLOCK_INPUT;
1865 /* Start update of window W. Set the global variable updated_window
1866 to the window being updated and set output_cursor to the cursor
1867 position of W. */
1869 static void
1870 x_update_window_begin (w)
1871 struct window *w;
1873 struct frame *f = XFRAME (WINDOW_FRAME (w));
1874 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1876 updated_window = w;
1877 set_output_cursor (&w->cursor);
1879 BLOCK_INPUT;
1881 if (f == display_info->mouse_face_mouse_frame)
1883 /* Don't do highlighting for mouse motion during the update. */
1884 display_info->mouse_face_defer = 1;
1886 /* If F needs to be redrawn, simply forget about any prior mouse
1887 highlighting. */
1888 if (FRAME_GARBAGED_P (f))
1889 display_info->mouse_face_window = Qnil;
1891 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1892 their mouse_face_p flag set, which means that they are always
1893 unequal to rows in a desired matrix which never have that
1894 flag set. So, rows containing mouse-face glyphs are never
1895 scrolled, and we don't have to switch the mouse highlight off
1896 here to prevent it from being scrolled. */
1898 /* Can we tell that this update does not affect the window
1899 where the mouse highlight is? If so, no need to turn off.
1900 Likewise, don't do anything if the frame is garbaged;
1901 in that case, the frame's current matrix that we would use
1902 is all wrong, and we will redisplay that line anyway. */
1903 if (!NILP (display_info->mouse_face_window)
1904 && w == XWINDOW (display_info->mouse_face_window))
1906 int i;
1908 for (i = 0; i < w->desired_matrix->nrows; ++i)
1909 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1910 break;
1912 if (i < w->desired_matrix->nrows)
1913 clear_mouse_face (display_info);
1915 #endif /* 0 */
1918 UNBLOCK_INPUT;
1922 /* Draw a vertical window border from (x,y0) to (x,y1) */
1924 static void
1925 mac_draw_vertical_window_border (w, x, y0, y1)
1926 struct window *w;
1927 int x, y0, y1;
1929 struct frame *f = XFRAME (WINDOW_FRAME (w));
1930 struct face *face;
1932 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1933 if (face)
1934 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1935 face->foreground);
1937 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1940 /* End update of window W (which is equal to updated_window).
1942 Draw vertical borders between horizontally adjacent windows, and
1943 display W's cursor if CURSOR_ON_P is non-zero.
1945 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1946 glyphs in mouse-face were overwritten. In that case we have to
1947 make sure that the mouse-highlight is properly redrawn.
1949 W may be a menu bar pseudo-window in case we don't have X toolkit
1950 support. Such windows don't have a cursor, so don't display it
1951 here. */
1953 static void
1954 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1955 struct window *w;
1956 int cursor_on_p, mouse_face_overwritten_p;
1958 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1960 if (!w->pseudo_window_p)
1962 BLOCK_INPUT;
1964 if (cursor_on_p)
1965 display_and_set_cursor (w, 1, output_cursor.hpos,
1966 output_cursor.vpos,
1967 output_cursor.x, output_cursor.y);
1969 if (draw_window_fringes (w, 1))
1970 x_draw_vertical_border (w);
1972 UNBLOCK_INPUT;
1975 /* If a row with mouse-face was overwritten, arrange for
1976 XTframe_up_to_date to redisplay the mouse highlight. */
1977 if (mouse_face_overwritten_p)
1979 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1980 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1981 dpyinfo->mouse_face_window = Qnil;
1984 updated_window = NULL;
1988 /* End update of frame F. This function is installed as a hook in
1989 update_end. */
1991 static void
1992 x_update_end (f)
1993 struct frame *f;
1995 /* Mouse highlight may be displayed again. */
1996 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1998 BLOCK_INPUT;
1999 mac_update_end (f);
2000 XFlush (FRAME_MAC_DISPLAY (f));
2001 UNBLOCK_INPUT;
2005 /* This function is called from various places in xdisp.c whenever a
2006 complete update has been performed. The global variable
2007 updated_window is not available here. */
2009 static void
2010 XTframe_up_to_date (f)
2011 struct frame *f;
2013 if (FRAME_MAC_P (f))
2015 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2017 if (dpyinfo->mouse_face_deferred_gc
2018 || f == dpyinfo->mouse_face_mouse_frame)
2020 BLOCK_INPUT;
2021 if (dpyinfo->mouse_face_mouse_frame)
2022 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
2023 dpyinfo->mouse_face_mouse_x,
2024 dpyinfo->mouse_face_mouse_y);
2025 dpyinfo->mouse_face_deferred_gc = 0;
2026 UNBLOCK_INPUT;
2029 mac_frame_up_to_date (f);
2034 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
2035 arrow bitmaps, or clear the fringes if no bitmaps are required
2036 before DESIRED_ROW is made current. The window being updated is
2037 found in updated_window. This function is called from
2038 update_window_line only if it is known that there are differences
2039 between bitmaps to be drawn between current row and DESIRED_ROW. */
2041 static void
2042 x_after_update_window_line (desired_row)
2043 struct glyph_row *desired_row;
2045 struct window *w = updated_window;
2046 struct frame *f;
2047 int width, height;
2049 xassert (w);
2051 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2052 desired_row->redraw_fringe_bitmaps_p = 1;
2054 /* When a window has disappeared, make sure that no rest of
2055 full-width rows stays visible in the internal border. Could
2056 check here if updated_window is the leftmost/rightmost window,
2057 but I guess it's not worth doing since vertically split windows
2058 are almost never used, internal border is rarely set, and the
2059 overhead is very small. */
2060 if (windows_or_buffers_changed
2061 && desired_row->full_width_p
2062 && (f = XFRAME (w->frame),
2063 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2064 width != 0)
2065 && (height = desired_row->visible_height,
2066 height > 0))
2068 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2070 /* Internal border is drawn below the tool bar. */
2071 if (WINDOWP (f->tool_bar_window)
2072 && w == XWINDOW (f->tool_bar_window))
2073 y -= width;
2075 BLOCK_INPUT;
2076 mac_clear_area (f, 0, y, width, height);
2077 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2078 UNBLOCK_INPUT;
2083 /* Draw the bitmap WHICH in one of the left or right fringes of
2084 window W. ROW is the glyph row for which to display the bitmap; it
2085 determines the vertical position at which the bitmap has to be
2086 drawn. */
2088 static void
2089 x_draw_fringe_bitmap (w, row, p)
2090 struct window *w;
2091 struct glyph_row *row;
2092 struct draw_fringe_bitmap_params *p;
2094 struct frame *f = XFRAME (WINDOW_FRAME (w));
2095 Display *display = FRAME_MAC_DISPLAY (f);
2096 struct face *face = p->face;
2097 int rowY;
2098 int overlay_p = p->overlay_p;
2100 #ifdef MAC_OSX
2101 if (!overlay_p)
2103 int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
2105 #if 0 /* MAC_TODO: stipple */
2106 /* In case the same realized face is used for fringes and
2107 for something displayed in the text (e.g. face `region' on
2108 mono-displays, the fill style may have been changed to
2109 FillSolid in x_draw_glyph_string_background. */
2110 if (face->stipple)
2111 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2112 else
2113 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2114 #endif
2116 /* If the fringe is adjacent to the left (right) scroll bar of a
2117 leftmost (rightmost, respectively) window, then extend its
2118 background to the gap between the fringe and the bar. */
2119 if ((WINDOW_LEFTMOST_P (w)
2120 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
2121 || (WINDOW_RIGHTMOST_P (w)
2122 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
2124 int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
2126 if (sb_width > 0)
2128 int left = WINDOW_SCROLL_BAR_AREA_X (w);
2129 int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
2130 * FRAME_COLUMN_WIDTH (f));
2132 if (bx < 0
2133 && (left + width == p->x
2134 || p->x + p->wd == left))
2136 /* Bitmap fills the fringe and we need background
2137 extension. */
2138 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
2140 bx = p->x;
2141 nx = p->wd;
2142 by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
2143 row->y));
2144 ny = row->visible_height;
2147 if (bx >= 0)
2149 if (left + width == bx)
2151 bx = left + sb_width;
2152 nx += width - sb_width;
2154 else if (bx + nx == left)
2155 nx += width - sb_width;
2160 if (bx >= 0)
2162 mac_erase_rectangle (f, face->gc, bx, by, nx, ny);
2163 /* The fringe background has already been filled. */
2164 overlay_p = 1;
2167 #if 0 /* MAC_TODO: stipple */
2168 if (!face->stipple)
2169 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2170 #endif
2172 #endif /* MAC_OSX */
2174 /* Must clip because of partially visible lines. */
2175 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2176 if (p->y < rowY)
2178 /* Adjust position of "bottom aligned" bitmap on partially
2179 visible last row. */
2180 int oldY = row->y;
2181 int oldVH = row->visible_height;
2182 row->visible_height = p->h;
2183 row->y -= rowY - p->y;
2184 x_clip_to_row (w, row, -1, face->gc);
2185 row->y = oldY;
2186 row->visible_height = oldVH;
2188 else
2189 x_clip_to_row (w, row, -1, face->gc);
2191 #ifndef MAC_OSX
2192 if (p->bx >= 0 && !p->overlay_p)
2194 #if 0 /* MAC_TODO: stipple */
2195 /* In case the same realized face is used for fringes and
2196 for something displayed in the text (e.g. face `region' on
2197 mono-displays, the fill style may have been changed to
2198 FillSolid in x_draw_glyph_string_background. */
2199 if (face->stipple)
2200 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2201 else
2202 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2203 #endif
2205 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2207 #if 0 /* MAC_TODO: stipple */
2208 if (!face->stipple)
2209 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2210 #endif
2212 #endif /* !MAC_OSX */
2214 if (p->which
2215 #if USE_CG_DRAWING
2216 && p->which < max_fringe_bmp
2217 #endif
2220 XGCValues gcv;
2222 XGetGCValues (display, face->gc, GCForeground, &gcv);
2223 XSetForeground (display, face->gc,
2224 (p->cursor_p
2225 ? (p->overlay_p ? face->background
2226 : f->output_data.mac->cursor_pixel)
2227 : face->foreground));
2228 #if USE_CG_DRAWING
2229 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2230 p->wd, p->h, p->x, p->y, overlay_p);
2231 #else
2232 mac_draw_bitmap (f, face->gc, p->x, p->y,
2233 p->wd, p->h, p->bits + p->dh, overlay_p);
2234 #endif
2235 XSetForeground (display, face->gc, gcv.foreground);
2238 mac_reset_clip_rectangles (f, face->gc);
2241 #if USE_CG_DRAWING
2242 static void
2243 mac_define_fringe_bitmap (which, bits, h, wd)
2244 int which;
2245 unsigned short *bits;
2246 int h, wd;
2248 int i;
2249 CGDataProviderRef provider;
2251 if (which >= max_fringe_bmp)
2253 i = max_fringe_bmp;
2254 max_fringe_bmp = which + 20;
2255 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2256 while (i < max_fringe_bmp)
2257 fringe_bmp[i++] = 0;
2260 for (i = 0; i < h; i++)
2261 bits[i] = ~bits[i];
2263 BLOCK_INPUT;
2265 provider = CGDataProviderCreateWithData (NULL, bits,
2266 sizeof (unsigned short) * h, NULL);
2267 if (provider)
2269 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2270 sizeof (unsigned short),
2271 provider, NULL, 0);
2272 CGDataProviderRelease (provider);
2275 UNBLOCK_INPUT;
2278 static void
2279 mac_destroy_fringe_bitmap (which)
2280 int which;
2282 if (which >= max_fringe_bmp)
2283 return;
2285 if (fringe_bmp[which])
2287 BLOCK_INPUT;
2288 CGImageRelease (fringe_bmp[which]);
2289 UNBLOCK_INPUT;
2291 fringe_bmp[which] = 0;
2293 #endif
2296 /* This is called when starting Emacs and when restarting after
2297 suspend. When starting Emacs, no window is mapped. And nothing
2298 must be done to Emacs's own window if it is suspended (though that
2299 rarely happens). */
2301 static void
2302 XTset_terminal_modes ()
2306 /* This is called when exiting or suspending Emacs. Exiting will make
2307 the windows go away, and suspending requires no action. */
2309 static void
2310 XTreset_terminal_modes ()
2316 /***********************************************************************
2317 Display Iterator
2318 ***********************************************************************/
2320 /* Function prototypes of this page. */
2322 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2323 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2326 static void
2327 pcm_init (pcm, count)
2328 XCharStruct *pcm;
2329 int count;
2331 bzero (pcm, sizeof (XCharStruct) * count);
2332 while (--count >= 0)
2334 pcm->descent = PCM_INVALID;
2335 pcm++;
2339 static enum pcm_status
2340 pcm_get_status (pcm)
2341 const XCharStruct *pcm;
2343 int height = pcm->ascent + pcm->descent;
2345 /* Negative height means some special status. */
2346 return height >= 0 ? PCM_VALID : height;
2349 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2350 is not contained in the font. */
2352 static INLINE XCharStruct *
2353 x_per_char_metric (font, char2b)
2354 XFontStruct *font;
2355 XChar2b *char2b;
2357 /* The result metric information. */
2358 XCharStruct *pcm = NULL;
2360 xassert (font && char2b);
2362 #if USE_ATSUI
2363 if (font->mac_style)
2365 XCharStruct **row = font->bounds.rows + char2b->byte1;
2367 if (*row == NULL)
2369 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2370 pcm_init (*row, 0x100);
2372 pcm = *row + char2b->byte2;
2373 if (pcm_get_status (pcm) != PCM_VALID)
2375 BLOCK_INPUT;
2376 mac_query_char_extents (font->mac_style,
2377 (char2b->byte1 << 8) + char2b->byte2,
2378 NULL, NULL, pcm, NULL);
2379 UNBLOCK_INPUT;
2382 else
2384 #endif
2385 if (font->bounds.per_char != NULL)
2387 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2389 /* min_char_or_byte2 specifies the linear character index
2390 corresponding to the first element of the per_char array,
2391 max_char_or_byte2 is the index of the last character. A
2392 character with non-zero CHAR2B->byte1 is not in the font.
2393 A character with byte2 less than min_char_or_byte2 or
2394 greater max_char_or_byte2 is not in the font. */
2395 if (char2b->byte1 == 0
2396 && char2b->byte2 >= font->min_char_or_byte2
2397 && char2b->byte2 <= font->max_char_or_byte2)
2398 pcm = font->bounds.per_char
2399 + (char2b->byte2 - font->min_char_or_byte2);
2401 else
2403 /* If either min_byte1 or max_byte1 are nonzero, both
2404 min_char_or_byte2 and max_char_or_byte2 are less than
2405 256, and the 2-byte character index values corresponding
2406 to the per_char array element N (counting from 0) are:
2408 byte1 = N/D + min_byte1
2409 byte2 = N\D + min_char_or_byte2
2411 where:
2413 D = max_char_or_byte2 - min_char_or_byte2 + 1
2414 / = integer division
2415 \ = integer modulus */
2416 if (char2b->byte1 >= font->min_byte1
2417 && char2b->byte1 <= font->max_byte1
2418 && char2b->byte2 >= font->min_char_or_byte2
2419 && char2b->byte2 <= font->max_char_or_byte2)
2421 pcm = (font->bounds.per_char
2422 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2423 * (char2b->byte1 - font->min_byte1))
2424 + (char2b->byte2 - font->min_char_or_byte2));
2428 else
2430 /* If the per_char pointer is null, all glyphs between the first
2431 and last character indexes inclusive have the same
2432 information, as given by both min_bounds and max_bounds. */
2433 if (char2b->byte2 >= font->min_char_or_byte2
2434 && char2b->byte2 <= font->max_char_or_byte2)
2435 pcm = &font->max_bounds;
2437 #if USE_ATSUI
2439 #endif
2441 return ((pcm == NULL
2442 || (pcm->width == 0
2443 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2444 && (pcm->rbearing - pcm->lbearing) == 0
2445 #endif
2447 ? NULL : pcm);
2450 /* RIF:
2453 static XCharStruct *
2454 mac_per_char_metric (font, char2b, font_type)
2455 XFontStruct *font;
2456 XChar2b *char2b;
2457 int font_type;
2459 return x_per_char_metric (font, char2b);
2462 /* RIF:
2463 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2464 the two-byte form of C. Encoding is returned in *CHAR2B. */
2466 static int
2467 mac_encode_char (c, char2b, font_info, two_byte_p)
2468 int c;
2469 XChar2b *char2b;
2470 struct font_info *font_info;
2471 int *two_byte_p;
2473 int charset = CHAR_CHARSET (c);
2474 XFontStruct *font = font_info->font;
2476 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2477 This may be either a program in a special encoder language or a
2478 fixed encoding. */
2479 if (font_info->font_encoder)
2481 /* It's a program. */
2482 struct ccl_program *ccl = font_info->font_encoder;
2484 check_ccl_update (ccl);
2485 if (CHARSET_DIMENSION (charset) == 1)
2487 ccl->reg[0] = charset;
2488 ccl->reg[1] = char2b->byte2;
2489 ccl->reg[2] = -1;
2491 else
2493 ccl->reg[0] = charset;
2494 ccl->reg[1] = char2b->byte1;
2495 ccl->reg[2] = char2b->byte2;
2498 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2500 /* We assume that MSBs are appropriately set/reset by CCL
2501 program. */
2502 if (font->max_byte1 == 0) /* 1-byte font */
2503 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2504 else
2505 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2507 else if (font_info->encoding[charset])
2509 /* Fixed encoding scheme. See fontset.h for the meaning of the
2510 encoding numbers. */
2511 int enc = font_info->encoding[charset];
2513 if ((enc == 1 || enc == 2)
2514 && CHARSET_DIMENSION (charset) == 2)
2515 char2b->byte1 |= 0x80;
2517 if (enc == 1 || enc == 3)
2518 char2b->byte2 |= 0x80;
2520 if (enc == 4)
2522 int sjis1, sjis2;
2524 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2525 char2b->byte1 = sjis1;
2526 char2b->byte2 = sjis2;
2530 if (two_byte_p)
2531 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2533 return FONT_TYPE_UNKNOWN;
2538 /***********************************************************************
2539 Glyph display
2540 ***********************************************************************/
2544 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2545 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2546 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2547 int));
2548 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2549 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2550 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2551 static void x_draw_glyph_string P_ ((struct glyph_string *));
2552 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2553 static void x_set_cursor_gc P_ ((struct glyph_string *));
2554 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2555 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2556 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2557 unsigned long *, double, int));*/
2558 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2559 double, int, unsigned long));
2560 static void x_setup_relief_colors P_ ((struct glyph_string *));
2561 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2562 static void x_draw_image_relief P_ ((struct glyph_string *));
2563 static void x_draw_image_foreground P_ ((struct glyph_string *));
2564 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2565 int, int, int));
2566 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2567 int, int, int, int, int, int,
2568 Rect *));
2569 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2570 int, int, int, Rect *));
2572 #if GLYPH_DEBUG
2573 static void x_check_font P_ ((struct frame *, XFontStruct *));
2574 #endif
2577 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2578 face. */
2580 static void
2581 x_set_cursor_gc (s)
2582 struct glyph_string *s;
2584 if (s->font == FRAME_FONT (s->f)
2585 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2586 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2587 && !s->cmp)
2588 s->gc = s->f->output_data.mac->cursor_gc;
2589 else
2591 /* Cursor on non-default face: must merge. */
2592 XGCValues xgcv;
2593 unsigned long mask;
2595 xgcv.background = s->f->output_data.mac->cursor_pixel;
2596 xgcv.foreground = s->face->background;
2598 /* If the glyph would be invisible, try a different foreground. */
2599 if (xgcv.foreground == xgcv.background)
2600 xgcv.foreground = s->face->foreground;
2601 if (xgcv.foreground == xgcv.background)
2602 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2603 if (xgcv.foreground == xgcv.background)
2604 xgcv.foreground = s->face->foreground;
2606 /* Make sure the cursor is distinct from text in this face. */
2607 if (xgcv.background == s->face->background
2608 && xgcv.foreground == s->face->foreground)
2610 xgcv.background = s->face->foreground;
2611 xgcv.foreground = s->face->background;
2614 IF_DEBUG (x_check_font (s->f, s->font));
2615 xgcv.font = s->font;
2616 mask = GCForeground | GCBackground | GCFont;
2618 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2619 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2620 mask, &xgcv);
2621 else
2622 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2623 = XCreateGC (s->display, s->window, mask, &xgcv);
2625 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2630 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2632 static void
2633 x_set_mouse_face_gc (s)
2634 struct glyph_string *s;
2636 int face_id;
2637 struct face *face;
2639 /* What face has to be used last for the mouse face? */
2640 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2641 face = FACE_FROM_ID (s->f, face_id);
2642 if (face == NULL)
2643 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2645 if (s->first_glyph->type == CHAR_GLYPH)
2646 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2647 else
2648 face_id = FACE_FOR_CHAR (s->f, face, 0);
2649 s->face = FACE_FROM_ID (s->f, face_id);
2650 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2652 /* If font in this face is same as S->font, use it. */
2653 if (s->font == s->face->font)
2654 s->gc = s->face->gc;
2655 else
2657 /* Otherwise construct scratch_cursor_gc with values from FACE
2658 but font FONT. */
2659 XGCValues xgcv;
2660 unsigned long mask;
2662 xgcv.background = s->face->background;
2663 xgcv.foreground = s->face->foreground;
2664 IF_DEBUG (x_check_font (s->f, s->font));
2665 xgcv.font = s->font;
2666 mask = GCForeground | GCBackground | GCFont;
2668 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2669 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2670 mask, &xgcv);
2671 else
2672 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2673 = XCreateGC (s->display, s->window, mask, &xgcv);
2675 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2678 xassert (s->gc != 0);
2682 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2683 Faces to use in the mode line have already been computed when the
2684 matrix was built, so there isn't much to do, here. */
2686 static INLINE void
2687 x_set_mode_line_face_gc (s)
2688 struct glyph_string *s;
2690 s->gc = s->face->gc;
2694 /* Set S->gc of glyph string S for drawing that glyph string. Set
2695 S->stippled_p to a non-zero value if the face of S has a stipple
2696 pattern. */
2698 static INLINE void
2699 x_set_glyph_string_gc (s)
2700 struct glyph_string *s;
2702 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2704 if (s->hl == DRAW_NORMAL_TEXT)
2706 s->gc = s->face->gc;
2707 s->stippled_p = s->face->stipple != 0;
2709 else if (s->hl == DRAW_INVERSE_VIDEO)
2711 x_set_mode_line_face_gc (s);
2712 s->stippled_p = s->face->stipple != 0;
2714 else if (s->hl == DRAW_CURSOR)
2716 x_set_cursor_gc (s);
2717 s->stippled_p = 0;
2719 else if (s->hl == DRAW_MOUSE_FACE)
2721 x_set_mouse_face_gc (s);
2722 s->stippled_p = s->face->stipple != 0;
2724 else if (s->hl == DRAW_IMAGE_RAISED
2725 || s->hl == DRAW_IMAGE_SUNKEN)
2727 s->gc = s->face->gc;
2728 s->stippled_p = s->face->stipple != 0;
2730 else
2732 s->gc = s->face->gc;
2733 s->stippled_p = s->face->stipple != 0;
2736 /* GC must have been set. */
2737 xassert (s->gc != 0);
2741 /* Set clipping for output of glyph string S. S may be part of a mode
2742 line or menu if we don't have X toolkit support. */
2744 static INLINE void
2745 x_set_glyph_string_clipping (s)
2746 struct glyph_string *s;
2748 Rect rects[MAX_CLIP_RECTS];
2749 int n;
2751 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2752 mac_set_clip_rectangles (s->f, s->gc, rects, n);
2756 /* RIF:
2757 Compute left and right overhang of glyph string S. If S is a glyph
2758 string for a composition, assume overhangs don't exist. */
2760 static void
2761 mac_compute_glyph_string_overhangs (s)
2762 struct glyph_string *s;
2764 if (!(s->cmp == NULL
2765 && s->first_glyph->type == CHAR_GLYPH))
2766 return;
2768 if (!s->two_byte_p
2769 #if USE_ATSUI
2770 || s->font->mac_style
2771 #endif
2774 XCharStruct cs;
2776 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2777 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2778 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2780 else
2782 Rect r;
2783 MacFontStruct *font = s->font;
2785 mac_begin_clip (s->f, NULL);
2787 TextFont (font->mac_fontnum);
2788 TextSize (font->mac_fontsize);
2789 TextFace (font->mac_fontface);
2791 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2793 mac_end_clip (s->f, NULL);
2795 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2796 s->left_overhang = r.left < 0 ? -r.left : 0;
2801 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2803 static INLINE void
2804 x_clear_glyph_string_rect (s, x, y, w, h)
2805 struct glyph_string *s;
2806 int x, y, w, h;
2808 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2812 /* Draw the background of glyph_string S. If S->background_filled_p
2813 is non-zero don't draw it. FORCE_P non-zero means draw the
2814 background even if it wouldn't be drawn normally. This is used
2815 when a string preceding S draws into the background of S, or S
2816 contains the first component of a composition. */
2818 static void
2819 x_draw_glyph_string_background (s, force_p)
2820 struct glyph_string *s;
2821 int force_p;
2823 /* Nothing to do if background has already been drawn or if it
2824 shouldn't be drawn in the first place. */
2825 if (!s->background_filled_p)
2827 int box_line_width = max (s->face->box_line_width, 0);
2829 #if 0 /* MAC_TODO: stipple */
2830 if (s->stippled_p)
2832 /* Fill background with a stipple pattern. */
2833 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2834 XFillRectangle (s->display, s->window, s->gc, s->x,
2835 s->y + box_line_width,
2836 s->background_width,
2837 s->height - 2 * box_line_width);
2838 XSetFillStyle (s->display, s->gc, FillSolid);
2839 s->background_filled_p = 1;
2841 else
2842 #endif
2843 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2844 || s->font_not_found_p
2845 || s->extends_to_end_of_line_p
2846 || force_p)
2848 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2849 s->background_width,
2850 s->height - 2 * box_line_width);
2851 s->background_filled_p = 1;
2857 /* Draw the foreground of glyph string S. */
2859 static void
2860 x_draw_glyph_string_foreground (s)
2861 struct glyph_string *s;
2863 int i, x, bg_width;
2865 /* If first glyph of S has a left box line, start drawing the text
2866 of S to the right of that box line. */
2867 if (s->face->box != FACE_NO_BOX
2868 && s->first_glyph->left_box_line_p)
2869 x = s->x + abs (s->face->box_line_width);
2870 else
2871 x = s->x;
2873 /* Draw characters of S as rectangles if S's font could not be
2874 loaded. */
2875 if (s->font_not_found_p)
2877 for (i = 0; i < s->nchars; ++i)
2879 struct glyph *g = s->first_glyph + i;
2880 mac_draw_rectangle (s->f, s->gc, x, s->y,
2881 g->pixel_width - 1, s->height - 1);
2882 x += g->pixel_width;
2885 else
2887 char *char1b = (char *) s->char2b;
2888 int boff = s->font_info->baseline_offset;
2890 if (s->font_info->vertical_centering)
2891 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2893 /* If we can use 8-bit functions, condense S->char2b. */
2894 if (!s->two_byte_p
2895 #if USE_ATSUI
2896 && GC_FONT (s->gc)->mac_style == NULL
2897 #endif
2899 for (i = 0; i < s->nchars; ++i)
2900 char1b[i] = s->char2b[i].byte2;
2902 /* Draw text with XDrawString if background has already been
2903 filled. Otherwise, use XDrawImageString. (Note that
2904 XDrawImageString is usually faster than XDrawString.) Always
2905 use XDrawImageString when drawing the cursor so that there is
2906 no chance that characters under a box cursor are invisible. */
2907 if (s->for_overlaps
2908 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2909 bg_width = 0; /* Corresponds to XDrawString. */
2910 else
2911 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2913 if (s->two_byte_p
2914 #if USE_ATSUI
2915 || GC_FONT (s->gc)->mac_style
2916 #endif
2918 #if USE_CG_TEXT_DRAWING
2919 if (!s->two_byte_p
2920 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
2921 s->char2b, s->nchars, bg_width,
2922 s->face->overstrike))
2924 else
2925 #endif
2926 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2927 s->char2b, s->nchars, bg_width,
2928 s->face->overstrike);
2929 else
2930 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2931 char1b, s->nchars, bg_width,
2932 s->face->overstrike);
2936 /* Draw the foreground of composite glyph string S. */
2938 static void
2939 x_draw_composite_glyph_string_foreground (s)
2940 struct glyph_string *s;
2942 int i, x;
2944 /* If first glyph of S has a left box line, start drawing the text
2945 of S to the right of that box line. */
2946 if (s->face->box != FACE_NO_BOX
2947 && s->first_glyph->left_box_line_p)
2948 x = s->x + abs (s->face->box_line_width);
2949 else
2950 x = s->x;
2952 /* S is a glyph string for a composition. S->gidx is the index of
2953 the first character drawn for glyphs of this composition.
2954 S->gidx == 0 means we are drawing the very first character of
2955 this composition. */
2957 /* Draw a rectangle for the composition if the font for the very
2958 first character of the composition could not be loaded. */
2959 if (s->font_not_found_p)
2961 if (s->gidx == 0)
2962 mac_draw_rectangle (s->f, s->gc, x, s->y,
2963 s->width - 1, s->height - 1);
2965 else
2967 for (i = 0; i < s->nchars; i++, ++s->gidx)
2968 if (mac_per_char_metric (GC_FONT (s->gc), s->char2b + i, 0) == NULL)
2969 /* This is a nonexistent or zero-width glyph such as a
2970 combining diacritic. Draw a rectangle. */
2971 mac_draw_rectangle (s->f, s->gc,
2972 x + s->cmp->offsets[s->gidx * 2], s->y,
2973 FONT_WIDTH (GC_FONT (s->gc)) - 1, s->height - 1);
2974 else
2975 mac_draw_image_string_16 (s->f, s->gc,
2976 x + s->cmp->offsets[s->gidx * 2],
2977 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2978 s->char2b + i, 1, 0, s->face->overstrike);
2983 #ifdef USE_X_TOOLKIT
2985 static struct frame *x_frame_of_widget P_ ((Widget));
2988 /* Return the frame on which widget WIDGET is used.. Abort if frame
2989 cannot be determined. */
2991 static struct frame *
2992 x_frame_of_widget (widget)
2993 Widget widget;
2995 struct x_display_info *dpyinfo;
2996 Lisp_Object tail;
2997 struct frame *f;
2999 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3001 /* Find the top-level shell of the widget. Note that this function
3002 can be called when the widget is not yet realized, so XtWindow
3003 (widget) == 0. That's the reason we can't simply use
3004 x_any_window_to_frame. */
3005 while (!XtIsTopLevelShell (widget))
3006 widget = XtParent (widget);
3008 /* Look for a frame with that top-level widget. Allocate the color
3009 on that frame to get the right gamma correction value. */
3010 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3011 if (GC_FRAMEP (XCAR (tail))
3012 && (f = XFRAME (XCAR (tail)),
3013 (f->output_data.nothing != 1
3014 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3015 && f->output_data.x->widget == widget)
3016 return f;
3018 abort ();
3022 /* Allocate the color COLOR->pixel on the screen and display of
3023 widget WIDGET in colormap CMAP. If an exact match cannot be
3024 allocated, try the nearest color available. Value is non-zero
3025 if successful. This is called from lwlib. */
3028 x_alloc_nearest_color_for_widget (widget, cmap, color)
3029 Widget widget;
3030 Colormap cmap;
3031 XColor *color;
3033 struct frame *f = x_frame_of_widget (widget);
3034 return x_alloc_nearest_color (f, cmap, color);
3038 #endif /* USE_X_TOOLKIT */
3040 #if 0 /* MAC_TODO */
3042 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3043 CMAP. If an exact match can't be allocated, try the nearest color
3044 available. Value is non-zero if successful. Set *COLOR to the
3045 color allocated. */
3048 x_alloc_nearest_color (f, cmap, color)
3049 struct frame *f;
3050 Colormap cmap;
3051 XColor *color;
3053 Display *display = FRAME_X_DISPLAY (f);
3054 Screen *screen = FRAME_X_SCREEN (f);
3055 int rc;
3057 gamma_correct (f, color);
3058 rc = XAllocColor (display, cmap, color);
3059 if (rc == 0)
3061 /* If we got to this point, the colormap is full, so we're going
3062 to try to get the next closest color. The algorithm used is
3063 a least-squares matching, which is what X uses for closest
3064 color matching with StaticColor visuals. */
3065 int nearest, i;
3066 unsigned long nearest_delta = ~0;
3067 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3068 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3070 for (i = 0; i < ncells; ++i)
3071 cells[i].pixel = i;
3072 XQueryColors (display, cmap, cells, ncells);
3074 for (nearest = i = 0; i < ncells; ++i)
3076 long dred = (color->red >> 8) - (cells[i].red >> 8);
3077 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3078 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3079 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3081 if (delta < nearest_delta)
3083 nearest = i;
3084 nearest_delta = delta;
3088 color->red = cells[nearest].red;
3089 color->green = cells[nearest].green;
3090 color->blue = cells[nearest].blue;
3091 rc = XAllocColor (display, cmap, color);
3094 #ifdef DEBUG_X_COLORS
3095 if (rc)
3096 register_color (color->pixel);
3097 #endif /* DEBUG_X_COLORS */
3099 return rc;
3103 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3104 It's necessary to do this instead of just using PIXEL directly to
3105 get color reference counts right. */
3107 unsigned long
3108 x_copy_color (f, pixel)
3109 struct frame *f;
3110 unsigned long pixel;
3112 XColor color;
3114 color.pixel = pixel;
3115 BLOCK_INPUT;
3116 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3117 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3118 UNBLOCK_INPUT;
3119 #ifdef DEBUG_X_COLORS
3120 register_color (pixel);
3121 #endif
3122 return color.pixel;
3126 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3127 It's necessary to do this instead of just using PIXEL directly to
3128 get color reference counts right. */
3130 unsigned long
3131 x_copy_dpy_color (dpy, cmap, pixel)
3132 Display *dpy;
3133 Colormap cmap;
3134 unsigned long pixel;
3136 XColor color;
3138 color.pixel = pixel;
3139 BLOCK_INPUT;
3140 XQueryColor (dpy, cmap, &color);
3141 XAllocColor (dpy, cmap, &color);
3142 UNBLOCK_INPUT;
3143 #ifdef DEBUG_X_COLORS
3144 register_color (pixel);
3145 #endif
3146 return color.pixel;
3149 #endif /* MAC_TODO */
3152 /* Brightness beyond which a color won't have its highlight brightness
3153 boosted.
3155 Nominally, highlight colors for `3d' faces are calculated by
3156 brightening an object's color by a constant scale factor, but this
3157 doesn't yield good results for dark colors, so for colors who's
3158 brightness is less than this value (on a scale of 0-255) have to
3159 use an additional additive factor.
3161 The value here is set so that the default menu-bar/mode-line color
3162 (grey75) will not have its highlights changed at all. */
3163 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3166 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3167 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3168 If this produces the same color as COLOR, try a color where all RGB
3169 values have DELTA added. Return the allocated color in *COLOR.
3170 DISPLAY is the X display, CMAP is the colormap to operate on.
3171 Value is non-zero if successful. */
3173 static int
3174 mac_alloc_lighter_color (f, color, factor, delta)
3175 struct frame *f;
3176 unsigned long *color;
3177 double factor;
3178 int delta;
3180 unsigned long new;
3181 long bright;
3183 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3184 delta /= 256;
3186 /* Change RGB values by specified FACTOR. Avoid overflow! */
3187 xassert (factor >= 0);
3188 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3189 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3190 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3192 /* Calculate brightness of COLOR. */
3193 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3194 + BLUE_FROM_ULONG (*color)) / 6;
3196 /* We only boost colors that are darker than
3197 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3198 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3199 /* Make an additive adjustment to NEW, because it's dark enough so
3200 that scaling by FACTOR alone isn't enough. */
3202 /* How far below the limit this color is (0 - 1, 1 being darker). */
3203 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3204 /* The additive adjustment. */
3205 int min_delta = delta * dimness * factor / 2;
3207 if (factor < 1)
3208 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3209 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3210 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3211 else
3212 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3213 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3214 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3217 if (new == *color)
3218 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3219 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3220 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3222 /* MAC_TODO: Map to palette and retry with delta if same? */
3223 /* MAC_TODO: Free colors (if using palette)? */
3225 if (new == *color)
3226 return 0;
3228 *color = new;
3230 return 1;
3234 /* Set up the foreground color for drawing relief lines of glyph
3235 string S. RELIEF is a pointer to a struct relief containing the GC
3236 with which lines will be drawn. Use a color that is FACTOR or
3237 DELTA lighter or darker than the relief's background which is found
3238 in S->f->output_data.x->relief_background. If such a color cannot
3239 be allocated, use DEFAULT_PIXEL, instead. */
3241 static void
3242 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3243 struct frame *f;
3244 struct relief *relief;
3245 double factor;
3246 int delta;
3247 unsigned long default_pixel;
3249 XGCValues xgcv;
3250 struct mac_output *di = f->output_data.mac;
3251 unsigned long mask = GCForeground;
3252 unsigned long pixel;
3253 unsigned long background = di->relief_background;
3254 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3256 /* MAC_TODO: Free colors (if using palette)? */
3258 /* Allocate new color. */
3259 xgcv.foreground = default_pixel;
3260 pixel = background;
3261 if (dpyinfo->n_planes != 1
3262 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3264 relief->allocated_p = 1;
3265 xgcv.foreground = relief->pixel = pixel;
3268 if (relief->gc == 0)
3270 #if 0 /* MAC_TODO: stipple */
3271 xgcv.stipple = dpyinfo->gray;
3272 mask |= GCStipple;
3273 #endif
3274 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3276 else
3277 XChangeGC (NULL, relief->gc, mask, &xgcv);
3281 /* Set up colors for the relief lines around glyph string S. */
3283 static void
3284 x_setup_relief_colors (s)
3285 struct glyph_string *s;
3287 struct mac_output *di = s->f->output_data.mac;
3288 unsigned long color;
3290 if (s->face->use_box_color_for_shadows_p)
3291 color = s->face->box_color;
3292 else if (s->first_glyph->type == IMAGE_GLYPH
3293 && s->img->pixmap
3294 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3295 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3296 else
3298 XGCValues xgcv;
3300 /* Get the background color of the face. */
3301 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3302 color = xgcv.background;
3305 if (di->white_relief.gc == 0
3306 || color != di->relief_background)
3308 di->relief_background = color;
3309 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3310 WHITE_PIX_DEFAULT (s->f));
3311 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3312 BLACK_PIX_DEFAULT (s->f));
3317 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3318 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3319 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3320 relief. LEFT_P non-zero means draw a relief on the left side of
3321 the rectangle. RIGHT_P non-zero means draw a relief on the right
3322 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3323 when drawing. */
3325 static void
3326 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3327 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3328 struct frame *f;
3329 int left_x, top_y, right_x, bottom_y, width;
3330 int top_p, bot_p, left_p, right_p, raised_p;
3331 Rect *clip_rect;
3333 int i;
3334 GC gc;
3336 if (raised_p)
3337 gc = f->output_data.mac->white_relief.gc;
3338 else
3339 gc = f->output_data.mac->black_relief.gc;
3340 mac_set_clip_rectangles (f, gc, clip_rect, 1);
3342 /* Top. */
3343 if (top_p)
3344 for (i = 0; i < width; ++i)
3345 mac_draw_line (f, gc,
3346 left_x + i * left_p, top_y + i,
3347 right_x + 1 - i * right_p, top_y + i);
3349 /* Left. */
3350 if (left_p)
3351 for (i = 0; i < width; ++i)
3352 mac_draw_line (f, gc,
3353 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3355 mac_reset_clip_rectangles (f, gc);
3356 if (raised_p)
3357 gc = f->output_data.mac->black_relief.gc;
3358 else
3359 gc = f->output_data.mac->white_relief.gc;
3360 mac_set_clip_rectangles (f, gc, clip_rect, 1);
3362 /* Bottom. */
3363 if (bot_p)
3364 for (i = 0; i < width; ++i)
3365 mac_draw_line (f, gc,
3366 left_x + i * left_p, bottom_y - i,
3367 right_x + 1 - i * right_p, bottom_y - i);
3369 /* Right. */
3370 if (right_p)
3371 for (i = 0; i < width; ++i)
3372 mac_draw_line (f, gc,
3373 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3375 mac_reset_clip_rectangles (f, gc);
3379 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3380 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3381 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3382 left side of the rectangle. RIGHT_P non-zero means draw a line
3383 on the right side of the rectangle. CLIP_RECT is the clipping
3384 rectangle to use when drawing. */
3386 static void
3387 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3388 left_p, right_p, clip_rect)
3389 struct glyph_string *s;
3390 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3391 Rect *clip_rect;
3393 XGCValues xgcv;
3395 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3396 XSetForeground (s->display, s->gc, s->face->box_color);
3397 mac_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
3399 /* Top. */
3400 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3401 right_x - left_x + 1, width);
3403 /* Left. */
3404 if (left_p)
3405 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3406 width, bottom_y - top_y + 1);
3408 /* Bottom. */
3409 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3410 right_x - left_x + 1, width);
3412 /* Right. */
3413 if (right_p)
3414 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3415 top_y, width, bottom_y - top_y + 1);
3417 XSetForeground (s->display, s->gc, xgcv.foreground);
3418 mac_reset_clip_rectangles (s->f, s->gc);
3422 /* Draw a box around glyph string S. */
3424 static void
3425 x_draw_glyph_string_box (s)
3426 struct glyph_string *s;
3428 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3429 int left_p, right_p;
3430 struct glyph *last_glyph;
3431 Rect clip_rect;
3433 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3434 ? WINDOW_RIGHT_EDGE_X (s->w)
3435 : window_box_right (s->w, s->area));
3437 /* The glyph that may have a right box line. */
3438 last_glyph = (s->cmp || s->img
3439 ? s->first_glyph
3440 : s->first_glyph + s->nchars - 1);
3442 width = abs (s->face->box_line_width);
3443 raised_p = s->face->box == FACE_RAISED_BOX;
3444 left_x = s->x;
3445 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3446 ? last_x - 1
3447 : min (last_x, s->x + s->background_width) - 1);
3448 top_y = s->y;
3449 bottom_y = top_y + s->height - 1;
3451 left_p = (s->first_glyph->left_box_line_p
3452 || (s->hl == DRAW_MOUSE_FACE
3453 && (s->prev == NULL
3454 || s->prev->hl != s->hl)));
3455 right_p = (last_glyph->right_box_line_p
3456 || (s->hl == DRAW_MOUSE_FACE
3457 && (s->next == NULL
3458 || s->next->hl != s->hl)));
3460 get_glyph_string_clip_rect (s, &clip_rect);
3462 if (s->face->box == FACE_SIMPLE_BOX)
3463 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3464 left_p, right_p, &clip_rect);
3465 else
3467 x_setup_relief_colors (s);
3468 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3469 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3474 /* Draw foreground of image glyph string S. */
3476 static void
3477 x_draw_image_foreground (s)
3478 struct glyph_string *s;
3480 int x = s->x;
3481 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3483 /* If first glyph of S has a left box line, start drawing it to the
3484 right of that line. */
3485 if (s->face->box != FACE_NO_BOX
3486 && s->first_glyph->left_box_line_p
3487 && s->slice.x == 0)
3488 x += abs (s->face->box_line_width);
3490 /* If there is a margin around the image, adjust x- and y-position
3491 by that margin. */
3492 if (s->slice.x == 0)
3493 x += s->img->hmargin;
3494 if (s->slice.y == 0)
3495 y += s->img->vmargin;
3497 if (s->img->pixmap)
3499 x_set_glyph_string_clipping (s);
3501 #if USE_CG_DRAWING
3502 mac_draw_cg_image (s->img->data.ptr_val,
3503 s->f, s->gc, s->slice.x, s->slice.y,
3504 s->slice.width, s->slice.height, x, y, 1);
3505 #endif
3506 if (s->img->mask)
3507 #if !USE_CG_DRAWING
3508 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3509 s->f, s->gc, s->slice.x, s->slice.y,
3510 s->slice.width, s->slice.height, x, y);
3511 #else
3513 #endif
3514 else
3516 #if !USE_CG_DRAWING
3517 mac_copy_area (s->img->pixmap,
3518 s->f, s->gc, s->slice.x, s->slice.y,
3519 s->slice.width, s->slice.height, x, y);
3520 #endif
3522 /* When the image has a mask, we can expect that at
3523 least part of a mouse highlight or a block cursor will
3524 be visible. If the image doesn't have a mask, make
3525 a block cursor visible by drawing a rectangle around
3526 the image. I believe it's looking better if we do
3527 nothing here for mouse-face. */
3528 if (s->hl == DRAW_CURSOR)
3530 int r = s->img->relief;
3531 if (r < 0) r = -r;
3532 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3533 s->slice.width + r*2 - 1,
3534 s->slice.height + r*2 - 1);
3538 else
3539 /* Draw a rectangle if image could not be loaded. */
3540 mac_draw_rectangle (s->f, s->gc, x, y,
3541 s->slice.width - 1, s->slice.height - 1);
3545 /* Draw a relief around the image glyph string S. */
3547 static void
3548 x_draw_image_relief (s)
3549 struct glyph_string *s;
3551 int x0, y0, x1, y1, thick, raised_p;
3552 Rect r;
3553 int x = s->x;
3554 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3556 /* If first glyph of S has a left box line, start drawing it to the
3557 right of that line. */
3558 if (s->face->box != FACE_NO_BOX
3559 && s->first_glyph->left_box_line_p
3560 && s->slice.x == 0)
3561 x += abs (s->face->box_line_width);
3563 /* If there is a margin around the image, adjust x- and y-position
3564 by that margin. */
3565 if (s->slice.x == 0)
3566 x += s->img->hmargin;
3567 if (s->slice.y == 0)
3568 y += s->img->vmargin;
3570 if (s->hl == DRAW_IMAGE_SUNKEN
3571 || s->hl == DRAW_IMAGE_RAISED)
3573 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3574 raised_p = s->hl == DRAW_IMAGE_RAISED;
3576 else
3578 thick = abs (s->img->relief);
3579 raised_p = s->img->relief > 0;
3582 x0 = x - thick;
3583 y0 = y - thick;
3584 x1 = x + s->slice.width + thick - 1;
3585 y1 = y + s->slice.height + thick - 1;
3587 x_setup_relief_colors (s);
3588 get_glyph_string_clip_rect (s, &r);
3589 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3590 s->slice.y == 0,
3591 s->slice.y + s->slice.height == s->img->height,
3592 s->slice.x == 0,
3593 s->slice.x + s->slice.width == s->img->width,
3594 &r);
3598 /* Draw part of the background of glyph string S. X, Y, W, and H
3599 give the rectangle to draw. */
3601 static void
3602 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3603 struct glyph_string *s;
3604 int x, y, w, h;
3606 #if 0 /* MAC_TODO: stipple */
3607 if (s->stippled_p)
3609 /* Fill background with a stipple pattern. */
3610 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3611 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3612 XSetFillStyle (s->display, s->gc, FillSolid);
3614 else
3615 #endif /* MAC_TODO */
3616 x_clear_glyph_string_rect (s, x, y, w, h);
3620 /* Draw image glyph string S.
3622 s->y
3623 s->x +-------------------------
3624 | s->face->box
3626 | +-------------------------
3627 | | s->img->margin
3629 | | +-------------------
3630 | | | the image
3634 static void
3635 x_draw_image_glyph_string (s)
3636 struct glyph_string *s;
3638 int x, y;
3639 int box_line_hwidth = abs (s->face->box_line_width);
3640 int box_line_vwidth = max (s->face->box_line_width, 0);
3641 int height;
3643 height = s->height - 2 * box_line_vwidth;
3646 /* Fill background with face under the image. Do it only if row is
3647 taller than image or if image has a clip mask to reduce
3648 flickering. */
3649 s->stippled_p = s->face->stipple != 0;
3650 if (height > s->slice.height
3651 || s->img->hmargin
3652 || s->img->vmargin
3653 || s->img->mask
3654 || s->img->pixmap == 0
3655 || s->width != s->background_width)
3657 x = s->x;
3658 if (s->first_glyph->left_box_line_p
3659 && s->slice.x == 0)
3660 x += box_line_hwidth;
3662 y = s->y;
3663 if (s->slice.y == 0)
3664 y += box_line_vwidth;
3666 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3668 s->background_filled_p = 1;
3671 /* Draw the foreground. */
3672 x_draw_image_foreground (s);
3674 /* If we must draw a relief around the image, do it. */
3675 if (s->img->relief
3676 || s->hl == DRAW_IMAGE_RAISED
3677 || s->hl == DRAW_IMAGE_SUNKEN)
3678 x_draw_image_relief (s);
3682 /* Draw stretch glyph string S. */
3684 static void
3685 x_draw_stretch_glyph_string (s)
3686 struct glyph_string *s;
3688 xassert (s->first_glyph->type == STRETCH_GLYPH);
3690 if (s->hl == DRAW_CURSOR
3691 && !x_stretch_cursor_p)
3693 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3694 as wide as the stretch glyph. */
3695 int width, background_width = s->background_width;
3696 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3698 if (x < left_x)
3700 background_width -= left_x - x;
3701 x = left_x;
3703 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3705 /* Draw cursor. */
3706 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3708 /* Clear rest using the GC of the original non-cursor face. */
3709 if (width < background_width)
3711 int y = s->y;
3712 int w = background_width - width, h = s->height;
3713 Rect r;
3714 GC gc;
3716 x += width;
3717 if (s->row->mouse_face_p
3718 && cursor_in_mouse_face_p (s->w))
3720 x_set_mouse_face_gc (s);
3721 gc = s->gc;
3723 else
3724 gc = s->face->gc;
3726 get_glyph_string_clip_rect (s, &r);
3727 mac_set_clip_rectangles (s->f, gc, &r, 1);
3729 #if 0 /* MAC_TODO: stipple */
3730 if (s->face->stipple)
3732 /* Fill background with a stipple pattern. */
3733 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3734 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3735 XSetFillStyle (s->display, gc, FillSolid);
3737 else
3738 #endif /* MAC_TODO */
3739 mac_erase_rectangle (s->f, gc, x, y, w, h);
3742 else if (!s->background_filled_p)
3744 int background_width = s->background_width;
3745 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3747 /* Don't draw into left margin, fringe or scrollbar area
3748 except for header line and mode line. */
3749 if (x < left_x && !s->row->mode_line_p)
3751 background_width -= left_x - x;
3752 x = left_x;
3754 if (background_width > 0)
3755 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3758 s->background_filled_p = 1;
3762 /* Draw glyph string S. */
3764 static void
3765 x_draw_glyph_string (s)
3766 struct glyph_string *s;
3768 int relief_drawn_p = 0;
3770 /* If S draws into the background of its successor that does not
3771 draw a cursor, draw the background of the successor first so that
3772 S can draw into it. This makes S->next use XDrawString instead
3773 of XDrawImageString. */
3774 if (s->next && s->right_overhang && !s->for_overlaps
3775 && s->next->hl != DRAW_CURSOR)
3777 xassert (s->next->img == NULL);
3778 x_set_glyph_string_gc (s->next);
3779 x_set_glyph_string_clipping (s->next);
3780 x_draw_glyph_string_background (s->next, 1);
3783 /* Set up S->gc, set clipping and draw S. */
3784 x_set_glyph_string_gc (s);
3786 /* Draw relief (if any) in advance for char/composition so that the
3787 glyph string can be drawn over it. */
3788 if (!s->for_overlaps
3789 && s->face->box != FACE_NO_BOX
3790 && (s->first_glyph->type == CHAR_GLYPH
3791 || s->first_glyph->type == COMPOSITE_GLYPH))
3794 x_set_glyph_string_clipping (s);
3795 x_draw_glyph_string_background (s, 1);
3796 x_draw_glyph_string_box (s);
3797 x_set_glyph_string_clipping (s);
3798 relief_drawn_p = 1;
3800 else
3801 x_set_glyph_string_clipping (s);
3803 switch (s->first_glyph->type)
3805 case IMAGE_GLYPH:
3806 x_draw_image_glyph_string (s);
3807 break;
3809 case STRETCH_GLYPH:
3810 x_draw_stretch_glyph_string (s);
3811 break;
3813 case CHAR_GLYPH:
3814 if (s->for_overlaps)
3815 s->background_filled_p = 1;
3816 else
3817 x_draw_glyph_string_background (s, 0);
3818 x_draw_glyph_string_foreground (s);
3819 break;
3821 case COMPOSITE_GLYPH:
3822 if (s->for_overlaps || s->gidx > 0)
3823 s->background_filled_p = 1;
3824 else
3825 x_draw_glyph_string_background (s, 1);
3826 x_draw_composite_glyph_string_foreground (s);
3827 break;
3829 default:
3830 abort ();
3833 if (!s->for_overlaps)
3835 /* Draw underline. */
3836 if (s->face->underline_p)
3838 unsigned long tem, h;
3839 int y;
3841 #if 0
3842 /* Get the underline thickness. Default is 1 pixel. */
3843 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3844 #endif
3845 h = 1;
3847 y = s->y + s->height - h;
3848 if (!x_underline_at_descent_line)
3850 /* Get the underline position. This is the recommended
3851 vertical offset in pixels from the baseline to the top of
3852 the underline. This is a signed value according to the
3853 specs, and its default is
3855 ROUND ((maximum descent) / 2), with
3856 ROUND(x) = floor (x + 0.5) */
3858 #if 0
3859 if (x_use_underline_position_properties
3860 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
3861 y = s->ybase + (long) tem;
3862 else
3863 #endif
3864 if (s->face->font)
3865 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
3868 if (s->face->underline_defaulted_p)
3869 mac_fill_rectangle (s->f, s->gc, s->x, y,
3870 s->background_width, h);
3871 else
3873 XGCValues xgcv;
3874 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3875 XSetForeground (s->display, s->gc, s->face->underline_color);
3876 mac_fill_rectangle (s->f, s->gc, s->x, y,
3877 s->background_width, h);
3878 XSetForeground (s->display, s->gc, xgcv.foreground);
3882 /* Draw overline. */
3883 if (s->face->overline_p)
3885 unsigned long dy = 0, h = 1;
3887 if (s->face->overline_color_defaulted_p)
3888 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3889 s->background_width, h);
3890 else
3892 XGCValues xgcv;
3893 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3894 XSetForeground (s->display, s->gc, s->face->overline_color);
3895 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3896 s->background_width, h);
3897 XSetForeground (s->display, s->gc, xgcv.foreground);
3901 /* Draw strike-through. */
3902 if (s->face->strike_through_p)
3904 unsigned long h = 1;
3905 unsigned long dy = (s->height - h) / 2;
3907 if (s->face->strike_through_color_defaulted_p)
3908 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3909 s->width, h);
3910 else
3912 XGCValues xgcv;
3913 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3914 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3915 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3916 s->width, h);
3917 XSetForeground (s->display, s->gc, xgcv.foreground);
3921 /* Draw relief if not yet drawn. */
3922 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3923 x_draw_glyph_string_box (s);
3926 /* Reset clipping. */
3927 mac_reset_clip_rectangles (s->f, s->gc);
3930 /* Shift display to make room for inserted glyphs. */
3932 void
3933 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3934 struct frame *f;
3935 int x, y, width, height, shift_by;
3937 mac_scroll_area (f, f->output_data.mac->normal_gc,
3938 x, y, width, height,
3939 x + shift_by, y);
3942 /* Delete N glyphs at the nominal cursor position. Not implemented
3943 for X frames. */
3945 static void
3946 x_delete_glyphs (n)
3947 register int n;
3949 abort ();
3953 /* Clear entire frame. If updating_frame is non-null, clear that
3954 frame. Otherwise clear the selected frame. */
3956 static void
3957 x_clear_frame ()
3959 struct frame *f;
3961 if (updating_frame)
3962 f = updating_frame;
3963 else
3964 f = SELECTED_FRAME ();
3966 /* Clearing the frame will erase any cursor, so mark them all as no
3967 longer visible. */
3968 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3969 output_cursor.hpos = output_cursor.vpos = 0;
3970 output_cursor.x = -1;
3972 /* We don't set the output cursor here because there will always
3973 follow an explicit cursor_to. */
3974 BLOCK_INPUT;
3975 mac_clear_window (f);
3977 /* We have to clear the scroll bars, too. If we have changed
3978 colors or something like that, then they should be notified. */
3979 x_scroll_bar_clear (f);
3981 XFlush (FRAME_MAC_DISPLAY (f));
3982 UNBLOCK_INPUT;
3987 /* Invert the middle quarter of the frame for .15 sec. */
3989 /* We use the select system call to do the waiting, so we have to make
3990 sure it's available. If it isn't, we just won't do visual bells. */
3992 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3995 /* Subtract the `struct timeval' values X and Y, storing the result in
3996 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3998 static int
3999 timeval_subtract (result, x, y)
4000 struct timeval *result, x, y;
4002 /* Perform the carry for the later subtraction by updating y. This
4003 is safer because on some systems the tv_sec member is unsigned. */
4004 if (x.tv_usec < y.tv_usec)
4006 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4007 y.tv_usec -= 1000000 * nsec;
4008 y.tv_sec += nsec;
4011 if (x.tv_usec - y.tv_usec > 1000000)
4013 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4014 y.tv_usec += 1000000 * nsec;
4015 y.tv_sec -= nsec;
4018 /* Compute the time remaining to wait. tv_usec is certainly
4019 positive. */
4020 result->tv_sec = x.tv_sec - y.tv_sec;
4021 result->tv_usec = x.tv_usec - y.tv_usec;
4023 /* Return indication of whether the result should be considered
4024 negative. */
4025 return x.tv_sec < y.tv_sec;
4028 void
4029 XTflash (f)
4030 struct frame *f;
4032 /* Get the height not including a menu bar widget. */
4033 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
4034 /* Height of each line to flash. */
4035 int flash_height = FRAME_LINE_HEIGHT (f);
4036 /* These will be the left and right margins of the rectangles. */
4037 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4038 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4040 int width;
4042 /* Don't flash the area between a scroll bar and the frame
4043 edge it is next to. */
4044 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4046 case vertical_scroll_bar_left:
4047 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4048 break;
4050 case vertical_scroll_bar_right:
4051 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4052 break;
4054 default:
4055 break;
4058 width = flash_right - flash_left;
4060 BLOCK_INPUT;
4062 /* If window is tall, flash top and bottom line. */
4063 if (height > 3 * FRAME_LINE_HEIGHT (f))
4065 mac_invert_rectangle (f, flash_left,
4066 (FRAME_INTERNAL_BORDER_WIDTH (f)
4067 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4068 width, flash_height);
4069 mac_invert_rectangle (f, flash_left,
4070 (height - flash_height
4071 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4072 width, flash_height);
4074 else
4075 /* If it is short, flash it all. */
4076 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4077 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4079 x_flush (f);
4082 struct timeval wakeup;
4084 EMACS_GET_TIME (wakeup);
4086 /* Compute time to wait until, propagating carry from usecs. */
4087 wakeup.tv_usec += 150000;
4088 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4089 wakeup.tv_usec %= 1000000;
4091 /* Keep waiting until past the time wakeup or any input gets
4092 available. */
4093 while (! detect_input_pending ())
4095 struct timeval current;
4096 struct timeval timeout;
4098 EMACS_GET_TIME (current);
4100 /* Break if result would be negative. */
4101 if (timeval_subtract (&current, wakeup, current))
4102 break;
4104 /* How long `select' should wait. */
4105 timeout.tv_sec = 0;
4106 timeout.tv_usec = 10000;
4108 /* Try to wait that long--but we might wake up sooner. */
4109 select (0, NULL, NULL, NULL, &timeout);
4113 /* If window is tall, flash top and bottom line. */
4114 if (height > 3 * FRAME_LINE_HEIGHT (f))
4116 mac_invert_rectangle (f, flash_left,
4117 (FRAME_INTERNAL_BORDER_WIDTH (f)
4118 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
4119 width, flash_height);
4120 mac_invert_rectangle (f, flash_left,
4121 (height - flash_height
4122 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4123 width, flash_height);
4125 else
4126 /* If it is short, flash it all. */
4127 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4128 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4130 x_flush (f);
4132 UNBLOCK_INPUT;
4135 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
4138 /* Make audible bell. */
4140 void
4141 XTring_bell ()
4143 struct frame *f = SELECTED_FRAME ();
4145 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4146 if (visible_bell)
4147 XTflash (f);
4148 else
4149 #endif
4151 BLOCK_INPUT;
4152 mac_alert_sound_play ();
4153 XFlush (FRAME_MAC_DISPLAY (f));
4154 UNBLOCK_INPUT;
4159 /* Specify how many text lines, from the top of the window,
4160 should be affected by insert-lines and delete-lines operations.
4161 This, and those operations, are used only within an update
4162 that is bounded by calls to x_update_begin and x_update_end. */
4164 static void
4165 XTset_terminal_window (n)
4166 register int n;
4168 /* This function intentionally left blank. */
4173 /***********************************************************************
4174 Line Dance
4175 ***********************************************************************/
4177 /* Perform an insert-lines or delete-lines operation, inserting N
4178 lines or deleting -N lines at vertical position VPOS. */
4180 static void
4181 x_ins_del_lines (vpos, n)
4182 int vpos, n;
4184 abort ();
4188 /* Scroll part of the display as described by RUN. */
4190 static void
4191 x_scroll_run (w, run)
4192 struct window *w;
4193 struct run *run;
4195 struct frame *f = XFRAME (w->frame);
4196 int x, y, width, height, from_y, to_y, bottom_y;
4198 /* Get frame-relative bounding box of the text display area of W,
4199 without mode lines. Include in this box the left and right
4200 fringe of W. */
4201 window_box (w, -1, &x, &y, &width, &height);
4203 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4204 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4205 bottom_y = y + height;
4207 if (to_y < from_y)
4209 /* Scrolling up. Make sure we don't copy part of the mode
4210 line at the bottom. */
4211 if (from_y + run->height > bottom_y)
4212 height = bottom_y - from_y;
4213 else
4214 height = run->height;
4216 else
4218 /* Scolling down. Make sure we don't copy over the mode line.
4219 at the bottom. */
4220 if (to_y + run->height > bottom_y)
4221 height = bottom_y - to_y;
4222 else
4223 height = run->height;
4226 BLOCK_INPUT;
4228 /* Cursor off. Will be switched on again in x_update_window_end. */
4229 updated_window = w;
4230 x_clear_cursor (w);
4232 mac_scroll_area (f, f->output_data.mac->normal_gc,
4233 x, from_y,
4234 width, height,
4235 x, to_y);
4237 UNBLOCK_INPUT;
4242 /***********************************************************************
4243 Exposure Events
4244 ***********************************************************************/
4247 static void
4248 frame_highlight (f)
4249 struct frame *f;
4251 x_update_cursor (f, 1);
4254 static void
4255 frame_unhighlight (f)
4256 struct frame *f;
4258 x_update_cursor (f, 1);
4261 /* The focus has changed. Update the frames as necessary to reflect
4262 the new situation. Note that we can't change the selected frame
4263 here, because the Lisp code we are interrupting might become confused.
4264 Each event gets marked with the frame in which it occurred, so the
4265 Lisp code can tell when the switch took place by examining the events. */
4267 static void
4268 x_new_focus_frame (dpyinfo, frame)
4269 struct x_display_info *dpyinfo;
4270 struct frame *frame;
4272 struct frame *old_focus = dpyinfo->x_focus_frame;
4274 if (frame != dpyinfo->x_focus_frame)
4276 /* Set this before calling other routines, so that they see
4277 the correct value of x_focus_frame. */
4278 dpyinfo->x_focus_frame = frame;
4280 if (old_focus && old_focus->auto_lower)
4281 x_lower_frame (old_focus);
4283 #if 0
4284 selected_frame = frame;
4285 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4286 selected_frame);
4287 Fselect_window (selected_frame->selected_window, Qnil);
4288 choose_minibuf_frame ();
4289 #endif /* ! 0 */
4291 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4292 pending_autoraise_frame = dpyinfo->x_focus_frame;
4293 else
4294 pending_autoraise_frame = 0;
4296 #if USE_MAC_FONT_PANEL
4297 if (frame)
4298 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4299 #endif
4302 x_frame_rehighlight (dpyinfo);
4305 /* Handle FocusIn and FocusOut state changes for FRAME.
4306 If FRAME has focus and there exists more than one frame, puts
4307 a FOCUS_IN_EVENT into *BUFP. */
4309 void
4310 mac_focus_changed (type, dpyinfo, frame, bufp)
4311 int type;
4312 struct mac_display_info *dpyinfo;
4313 struct frame *frame;
4314 struct input_event *bufp;
4316 if (type == activeFlag)
4318 if (dpyinfo->x_focus_event_frame != frame)
4320 x_new_focus_frame (dpyinfo, frame);
4321 dpyinfo->x_focus_event_frame = frame;
4323 /* Don't stop displaying the initial startup message
4324 for a switch-frame event we don't need. */
4325 if (GC_NILP (Vterminal_frame)
4326 && GC_CONSP (Vframe_list)
4327 && !GC_NILP (XCDR (Vframe_list)))
4329 bufp->kind = FOCUS_IN_EVENT;
4330 XSETFRAME (bufp->frame_or_window, frame);
4334 else
4336 if (dpyinfo->x_focus_event_frame == frame)
4338 dpyinfo->x_focus_event_frame = 0;
4339 x_new_focus_frame (dpyinfo, 0);
4344 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4346 void
4347 x_mouse_leave (dpyinfo)
4348 struct x_display_info *dpyinfo;
4350 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4353 /* The focus has changed, or we have redirected a frame's focus to
4354 another frame (this happens when a frame uses a surrogate
4355 mini-buffer frame). Shift the highlight as appropriate.
4357 The FRAME argument doesn't necessarily have anything to do with which
4358 frame is being highlighted or un-highlighted; we only use it to find
4359 the appropriate X display info. */
4361 static void
4362 XTframe_rehighlight (frame)
4363 struct frame *frame;
4365 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4368 static void
4369 x_frame_rehighlight (dpyinfo)
4370 struct x_display_info *dpyinfo;
4372 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4374 if (dpyinfo->x_focus_frame)
4376 dpyinfo->x_highlight_frame
4377 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4378 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4379 : dpyinfo->x_focus_frame);
4380 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4382 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4383 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4386 else
4387 dpyinfo->x_highlight_frame = 0;
4389 if (dpyinfo->x_highlight_frame != old_highlight)
4391 if (old_highlight)
4392 frame_unhighlight (old_highlight);
4393 if (dpyinfo->x_highlight_frame)
4394 frame_highlight (dpyinfo->x_highlight_frame);
4400 /* Convert a keysym to its name. */
4402 char *
4403 x_get_keysym_name (keysym)
4404 int keysym;
4406 char *value;
4408 BLOCK_INPUT;
4409 #if 0
4410 value = XKeysymToString (keysym);
4411 #else
4412 value = 0;
4413 #endif
4414 UNBLOCK_INPUT;
4416 return value;
4421 /* Function to report a mouse movement to the mainstream Emacs code.
4422 The input handler calls this.
4424 We have received a mouse movement event, which is given in *event.
4425 If the mouse is over a different glyph than it was last time, tell
4426 the mainstream emacs code by setting mouse_moved. If not, ask for
4427 another motion event, so we can check again the next time it moves. */
4429 static Point last_mouse_motion_position;
4430 static Lisp_Object last_mouse_motion_frame;
4433 note_mouse_movement (frame, pos)
4434 FRAME_PTR frame;
4435 Point *pos;
4437 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4438 Rect r;
4440 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4441 last_mouse_motion_position = *pos;
4442 XSETFRAME (last_mouse_motion_frame, frame);
4444 if (frame == dpyinfo->mouse_face_mouse_frame
4445 && !PtInRect (*pos, mac_get_frame_bounds (frame, &r)))
4447 /* This case corresponds to LeaveNotify in X11. If we move
4448 outside the frame, then we're certainly no longer on any text
4449 in the frame. */
4450 clear_mouse_face (dpyinfo);
4451 dpyinfo->mouse_face_mouse_frame = 0;
4452 if (!dpyinfo->grabbed)
4453 rif->define_frame_cursor (frame,
4454 frame->output_data.mac->nontext_cursor);
4457 /* Has the mouse moved off the glyph it was on at the last sighting? */
4458 if (frame != last_mouse_glyph_frame
4459 || !PtInRect (*pos, &last_mouse_glyph))
4461 frame->mouse_moved = 1;
4462 last_mouse_scroll_bar = Qnil;
4463 note_mouse_highlight (frame, pos->h, pos->v);
4464 /* Remember which glyph we're now on. */
4465 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4466 last_mouse_glyph_frame = frame;
4467 return 1;
4470 return 0;
4474 /************************************************************************
4475 Mouse Face
4476 ************************************************************************/
4478 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4480 static void
4481 redo_mouse_highlight ()
4483 if (!NILP (last_mouse_motion_frame)
4484 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4485 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4486 last_mouse_motion_position.h,
4487 last_mouse_motion_position.v);
4491 struct frame *
4492 mac_focus_frame (dpyinfo)
4493 struct mac_display_info *dpyinfo;
4495 if (dpyinfo->x_focus_frame)
4496 return dpyinfo->x_focus_frame;
4497 else
4498 /* Mac version may get events, such as a menu bar click, even when
4499 all the frames are invisible. In this case, we regard the
4500 event came to the selected frame. */
4501 return SELECTED_FRAME ();
4505 /* Return the current position of the mouse.
4506 *FP should be a frame which indicates which display to ask about.
4508 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4509 and *PART to the frame, window, and scroll bar part that the mouse
4510 is over. Set *X and *Y to the portion and whole of the mouse's
4511 position on the scroll bar.
4513 If the mouse movement started elsewhere, set *FP to the frame the
4514 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4515 the mouse is over.
4517 Set *TIME to the server time-stamp for the time at which the mouse
4518 was at this position.
4520 Don't store anything if we don't have a valid set of values to report.
4522 This clears the mouse_moved flag, so we can wait for the next mouse
4523 movement. */
4525 static void
4526 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4527 FRAME_PTR *fp;
4528 int insist;
4529 Lisp_Object *bar_window;
4530 enum scroll_bar_part *part;
4531 Lisp_Object *x, *y;
4532 unsigned long *time;
4534 FRAME_PTR f1;
4536 BLOCK_INPUT;
4538 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4539 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4540 else
4542 Lisp_Object frame, tail;
4544 /* Clear the mouse-moved flag for every frame on this display. */
4545 FOR_EACH_FRAME (tail, frame)
4546 XFRAME (frame)->mouse_moved = 0;
4548 last_mouse_scroll_bar = Qnil;
4550 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4551 && FRAME_LIVE_P (last_mouse_frame))
4552 f1 = last_mouse_frame;
4553 else
4554 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4556 if (f1)
4558 /* Ok, we found a frame. Store all the values.
4559 last_mouse_glyph is a rectangle used to reduce the
4560 generation of mouse events. To not miss any motion
4561 events, we must divide the frame into rectangles of the
4562 size of the smallest character that could be displayed
4563 on it, i.e. into the same rectangles that matrices on
4564 the frame are divided into. */
4565 Point mouse_pos;
4567 mac_get_frame_mouse (f1, &mouse_pos);
4568 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4569 &last_mouse_glyph);
4570 last_mouse_glyph_frame = f1;
4572 *bar_window = Qnil;
4573 *part = 0;
4574 *fp = f1;
4575 XSETINT (*x, mouse_pos.h);
4576 XSETINT (*y, mouse_pos.v);
4577 *time = last_mouse_movement_time;
4581 UNBLOCK_INPUT;
4585 /************************************************************************
4586 Scroll bars, general
4587 ************************************************************************/
4589 /* Create a scroll bar and return the scroll bar vector for it. W is
4590 the Emacs window on which to create the scroll bar. TOP, LEFT,
4591 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4592 scroll bar. */
4594 static struct scroll_bar *
4595 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4596 struct window *w;
4597 int top, left, width, height, disp_top, disp_height;
4599 struct frame *f = XFRAME (w->frame);
4600 struct scroll_bar *bar
4601 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4602 Rect r;
4604 BLOCK_INPUT;
4606 XSETWINDOW (bar->window, w);
4607 XSETINT (bar->top, top);
4608 XSETINT (bar->left, left);
4609 XSETINT (bar->width, width);
4610 XSETINT (bar->height, height);
4611 #ifdef MAC_OSX
4612 bar->fringe_extended_p = Qnil;
4613 #endif
4614 bar->redraw_needed_p = Qnil;
4616 SetRect (&r, left, disp_top, left + width, disp_top + disp_height);
4617 mac_create_scroll_bar (bar, &r,
4618 #ifdef USE_TOOLKIT_SCROLL_BARS
4619 false
4620 #else
4621 width < disp_height
4622 #endif
4625 /* Add bar to its frame's list of scroll bars. */
4626 bar->next = FRAME_SCROLL_BARS (f);
4627 bar->prev = Qnil;
4628 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4629 if (!NILP (bar->next))
4630 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4632 UNBLOCK_INPUT;
4633 return bar;
4637 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4638 nil. */
4640 static void
4641 x_scroll_bar_remove (bar)
4642 struct scroll_bar *bar;
4644 BLOCK_INPUT;
4646 /* Destroy the Mac scroll bar control */
4647 mac_dispose_scroll_bar (bar);
4649 /* Disassociate this scroll bar from its window. */
4650 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4652 UNBLOCK_INPUT;
4656 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4657 that we are displaying PORTION characters out of a total of WHOLE
4658 characters, starting at POSITION. If WINDOW has no scroll bar,
4659 create one. */
4661 static void
4662 XTset_vertical_scroll_bar (w, portion, whole, position)
4663 struct window *w;
4664 int portion, whole, position;
4666 struct frame *f = XFRAME (w->frame);
4667 struct scroll_bar *bar;
4668 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4669 int window_y, window_height;
4670 #ifdef MAC_OSX
4671 int fringe_extended_p;
4672 #endif
4674 /* Get window dimensions. */
4675 window_box (w, -1, 0, &window_y, 0, &window_height);
4676 top = window_y;
4677 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4678 height = window_height;
4680 /* Compute the left edge of the scroll bar area. */
4681 left = WINDOW_SCROLL_BAR_AREA_X (w);
4683 /* Compute the width of the scroll bar which might be less than
4684 the width of the area reserved for the scroll bar. */
4685 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4686 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4687 else
4688 sb_width = width;
4690 /* Compute the left edge of the scroll bar. */
4691 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4692 sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
4693 else
4694 sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
4696 /* Adjustments according to Inside Macintosh to make it look nice */
4697 disp_top = top;
4698 disp_height = height;
4699 #ifdef MAC_OS8
4700 if (disp_top == 0)
4702 disp_top = -1;
4703 disp_height++;
4705 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4707 disp_top++;
4708 disp_height--;
4711 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4712 sb_left++;
4713 #endif
4715 #ifdef MAC_OSX
4716 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
4717 fringe_extended_p = (WINDOW_LEFTMOST_P (w)
4718 && WINDOW_LEFT_FRINGE_WIDTH (w)
4719 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4720 || WINDOW_LEFT_MARGIN_COLS (w) == 0));
4721 else
4722 fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
4723 && WINDOW_RIGHT_FRINGE_WIDTH (w)
4724 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
4725 || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
4726 #endif
4728 /* Does the scroll bar exist yet? */
4729 if (NILP (w->vertical_scroll_bar))
4731 BLOCK_INPUT;
4732 #ifdef MAC_OSX
4733 if (fringe_extended_p)
4734 mac_clear_area (f, sb_left, top, sb_width, height);
4735 else
4736 #endif
4737 mac_clear_area (f, left, top, width, height);
4738 UNBLOCK_INPUT;
4739 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4740 disp_height);
4741 XSETVECTOR (w->vertical_scroll_bar, bar);
4743 else
4745 /* It may just need to be moved and resized. */
4746 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4748 BLOCK_INPUT;
4750 /* If already correctly positioned, do nothing. */
4751 if (XINT (bar->left) == sb_left
4752 && XINT (bar->top) == top
4753 && XINT (bar->width) == sb_width
4754 && XINT (bar->height) == height
4755 #ifdef MAC_OSX
4756 && !NILP (bar->fringe_extended_p) == fringe_extended_p
4757 #endif
4760 if (!NILP (bar->redraw_needed_p))
4761 mac_redraw_scroll_bar (bar);
4763 else
4765 Rect r;
4767 /* Since toolkit scroll bars are smaller than the space reserved
4768 for them on the frame, we have to clear "under" them. */
4769 #ifdef MAC_OSX
4770 if (fringe_extended_p)
4771 mac_clear_area (f, sb_left, top, sb_width, height);
4772 else
4773 #endif
4774 mac_clear_area (f, left, top, width, height);
4776 SetRect (&r, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top,
4777 sb_left + sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
4778 disp_top + disp_height);
4779 mac_set_scroll_bar_bounds (bar, &r);
4781 /* Remember new settings. */
4782 XSETINT (bar->left, sb_left);
4783 XSETINT (bar->top, top);
4784 XSETINT (bar->width, sb_width);
4785 XSETINT (bar->height, height);
4788 UNBLOCK_INPUT;
4791 #ifdef MAC_OSX
4792 bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
4793 #endif
4794 bar->redraw_needed_p = Qnil;
4796 #ifdef USE_TOOLKIT_SCROLL_BARS
4797 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4798 #else /* not USE_TOOLKIT_SCROLL_BARS */
4799 /* Set the scroll bar's current state, unless we're currently being
4800 dragged. */
4801 if (NILP (bar->dragging))
4803 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4805 if (whole == 0)
4806 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4807 else
4809 int start = ((double) position * top_range) / whole;
4810 int end = ((double) (position + portion) * top_range) / whole;
4811 x_scroll_bar_set_handle (bar, start, end, 0);
4814 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4818 /* The following three hooks are used when we're doing a thorough
4819 redisplay of the frame. We don't explicitly know which scroll bars
4820 are going to be deleted, because keeping track of when windows go
4821 away is a real pain - "Can you say set-window-configuration, boys
4822 and girls?" Instead, we just assert at the beginning of redisplay
4823 that *all* scroll bars are to be removed, and then save a scroll bar
4824 from the fiery pit when we actually redisplay its window. */
4826 /* Arrange for all scroll bars on FRAME to be removed at the next call
4827 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4828 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4830 static void
4831 XTcondemn_scroll_bars (frame)
4832 FRAME_PTR frame;
4834 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4835 while (! NILP (FRAME_SCROLL_BARS (frame)))
4837 Lisp_Object bar;
4838 bar = FRAME_SCROLL_BARS (frame);
4839 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4840 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4841 XSCROLL_BAR (bar)->prev = Qnil;
4842 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4843 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4844 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4849 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4850 Note that WINDOW isn't necessarily condemned at all. */
4852 static void
4853 XTredeem_scroll_bar (window)
4854 struct window *window;
4856 struct scroll_bar *bar;
4857 struct frame *f;
4859 /* We can't redeem this window's scroll bar if it doesn't have one. */
4860 if (NILP (window->vertical_scroll_bar))
4861 abort ();
4863 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4865 /* Unlink it from the condemned list. */
4866 f = XFRAME (WINDOW_FRAME (window));
4867 if (NILP (bar->prev))
4869 /* If the prev pointer is nil, it must be the first in one of
4870 the lists. */
4871 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4872 /* It's not condemned. Everything's fine. */
4873 return;
4874 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4875 window->vertical_scroll_bar))
4876 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4877 else
4878 /* If its prev pointer is nil, it must be at the front of
4879 one or the other! */
4880 abort ();
4882 else
4883 XSCROLL_BAR (bar->prev)->next = bar->next;
4885 if (! NILP (bar->next))
4886 XSCROLL_BAR (bar->next)->prev = bar->prev;
4888 bar->next = FRAME_SCROLL_BARS (f);
4889 bar->prev = Qnil;
4890 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4891 if (! NILP (bar->next))
4892 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4895 /* Remove all scroll bars on FRAME that haven't been saved since the
4896 last call to `*condemn_scroll_bars_hook'. */
4898 static void
4899 XTjudge_scroll_bars (f)
4900 FRAME_PTR f;
4902 Lisp_Object bar, next;
4904 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4906 /* Clear out the condemned list now so we won't try to process any
4907 more events on the hapless scroll bars. */
4908 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4910 for (; ! NILP (bar); bar = next)
4912 struct scroll_bar *b = XSCROLL_BAR (bar);
4914 x_scroll_bar_remove (b);
4916 next = b->next;
4917 b->next = b->prev = Qnil;
4920 /* Now there should be no references to the condemned scroll bars,
4921 and they should get garbage-collected. */
4924 /* The screen has been cleared so we may have changed foreground or
4925 background colors, and the scroll bars may need to be redrawn.
4926 Clear out the scroll bars, and ask for expose events, so we can
4927 redraw them. */
4929 void
4930 x_scroll_bar_clear (f)
4931 FRAME_PTR f;
4933 Lisp_Object bar;
4935 /* We can have scroll bars even if this is 0,
4936 if we just turned off scroll bar mode.
4937 But in that case we should not clear them. */
4938 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4939 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
4940 bar = XSCROLL_BAR (bar)->next)
4941 XSCROLL_BAR (bar)->redraw_needed_p = Qt;
4945 /***********************************************************************
4946 Tool-bars
4947 ***********************************************************************/
4948 #if USE_MAC_TOOLBAR
4949 void
4950 mac_move_window_with_gravity (f, win_gravity, left, top)
4951 struct frame *f;
4952 int win_gravity;
4953 short left, top;
4955 Rect inner, outer;
4957 mac_get_window_bounds (f, &inner, &outer);
4959 switch (win_gravity)
4961 case NorthWestGravity:
4962 case WestGravity:
4963 case SouthWestGravity:
4964 left += inner.left - outer.left;
4965 break;
4967 case NorthGravity:
4968 case CenterGravity:
4969 case SouthGravity:
4970 left += ((inner.left - outer.left) + (inner.right - outer.right)) / 2;
4971 break;
4973 case NorthEastGravity:
4974 case EastGravity:
4975 case SouthEastGravity:
4976 left += inner.right - outer.right;
4977 break;
4980 switch (win_gravity)
4982 case NorthWestGravity:
4983 case NorthGravity:
4984 case NorthEastGravity:
4985 top += inner.top - outer.top;
4986 break;
4988 case WestGravity:
4989 case CenterGravity:
4990 case EastGravity:
4991 top += ((inner.top - outer.top) + (inner.bottom - outer.bottom)) / 2;
4992 break;
4994 case SouthWestGravity:
4995 case SouthGravity:
4996 case SouthEastGravity:
4997 top += inner.bottom - outer.bottom;
4998 break;
5001 mac_move_window (FRAME_MAC_WINDOW (f), left, top, false);
5004 void
5005 mac_get_window_origin_with_gravity (f, win_gravity, left, top)
5006 struct frame *f;
5007 int win_gravity;
5008 short *left, *top;
5010 Rect inner, outer;
5012 mac_get_window_bounds (f, &inner, &outer);
5014 switch (win_gravity)
5016 case NorthWestGravity:
5017 case WestGravity:
5018 case SouthWestGravity:
5019 *left = outer.left;
5020 break;
5022 case NorthGravity:
5023 case CenterGravity:
5024 case SouthGravity:
5025 *left = outer.left + ((outer.right - outer.left)
5026 - (inner.right - inner.left)) / 2;
5027 break;
5029 case NorthEastGravity:
5030 case EastGravity:
5031 case SouthEastGravity:
5032 *left = outer.right - (inner.right - inner.left);
5033 break;
5036 switch (win_gravity)
5038 case NorthWestGravity:
5039 case NorthGravity:
5040 case NorthEastGravity:
5041 *top = outer.top;
5042 break;
5044 case WestGravity:
5045 case CenterGravity:
5046 case EastGravity:
5047 *top = outer.top + ((outer.bottom - outer.top)
5048 - (inner.bottom - inner.top)) / 2;
5049 break;
5051 case SouthWestGravity:
5052 case SouthGravity:
5053 case SouthEastGravity:
5054 *top = outer.bottom - (inner.bottom - inner.top);
5055 break;
5059 CGImageRef
5060 mac_image_spec_to_cg_image (f, image)
5061 struct frame *f;
5062 Lisp_Object image;
5064 if (!valid_image_p (image))
5065 return NULL;
5066 else
5068 int img_id = lookup_image (f, image);
5069 struct image *img = IMAGE_FROM_ID (f, img_id);
5071 prepare_image_for_display (f, img);
5073 return img->data.ptr_val;
5076 #endif /* USE_MAC_TOOLBAR */
5079 /***********************************************************************
5080 Text Cursor
5081 ***********************************************************************/
5083 /* Set clipping for output in glyph row ROW. W is the window in which
5084 we operate. GC is the graphics context to set clipping in.
5086 ROW may be a text row or, e.g., a mode line. Text rows must be
5087 clipped to the interior of the window dedicated to text display,
5088 mode lines must be clipped to the whole window. */
5090 static void
5091 x_clip_to_row (w, row, area, gc)
5092 struct window *w;
5093 struct glyph_row *row;
5094 int area;
5095 GC gc;
5097 struct frame *f = XFRAME (WINDOW_FRAME (w));
5098 Rect clip_rect;
5099 int window_x, window_y, window_width;
5101 window_box (w, area, &window_x, &window_y, &window_width, 0);
5103 clip_rect.left = window_x;
5104 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5105 clip_rect.top = max (clip_rect.top, window_y);
5106 clip_rect.right = clip_rect.left + window_width;
5107 clip_rect.bottom = clip_rect.top + row->visible_height;
5109 mac_set_clip_rectangles (f, gc, &clip_rect, 1);
5113 /* Draw a hollow box cursor on window W in glyph row ROW. */
5115 static void
5116 x_draw_hollow_cursor (w, row)
5117 struct window *w;
5118 struct glyph_row *row;
5120 struct frame *f = XFRAME (WINDOW_FRAME (w));
5121 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5122 Display *dpy = FRAME_MAC_DISPLAY (f);
5123 int x, y, wd, h;
5124 XGCValues xgcv;
5125 struct glyph *cursor_glyph;
5126 GC gc;
5128 /* Get the glyph the cursor is on. If we can't tell because
5129 the current matrix is invalid or such, give up. */
5130 cursor_glyph = get_phys_cursor_glyph (w);
5131 if (cursor_glyph == NULL)
5132 return;
5134 /* Compute frame-relative coordinates for phys cursor. */
5135 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5136 wd = w->phys_cursor_width;
5138 /* The foreground of cursor_gc is typically the same as the normal
5139 background color, which can cause the cursor box to be invisible. */
5140 xgcv.foreground = f->output_data.mac->cursor_pixel;
5141 if (dpyinfo->scratch_cursor_gc)
5142 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5143 else
5144 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5145 GCForeground, &xgcv);
5146 gc = dpyinfo->scratch_cursor_gc;
5148 /* Set clipping, draw the rectangle, and reset clipping again. */
5149 x_clip_to_row (w, row, TEXT_AREA, gc);
5150 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5151 mac_reset_clip_rectangles (f, gc);
5155 /* Draw a bar cursor on window W in glyph row ROW.
5157 Implementation note: One would like to draw a bar cursor with an
5158 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5159 Unfortunately, I didn't find a font yet that has this property set.
5160 --gerd. */
5162 static void
5163 x_draw_bar_cursor (w, row, width, kind)
5164 struct window *w;
5165 struct glyph_row *row;
5166 int width;
5167 enum text_cursor_kinds kind;
5169 struct frame *f = XFRAME (w->frame);
5170 struct glyph *cursor_glyph;
5172 /* If cursor is out of bounds, don't draw garbage. This can happen
5173 in mini-buffer windows when switching between echo area glyphs
5174 and mini-buffer. */
5175 cursor_glyph = get_phys_cursor_glyph (w);
5176 if (cursor_glyph == NULL)
5177 return;
5179 /* If on an image, draw like a normal cursor. That's usually better
5180 visible than drawing a bar, esp. if the image is large so that
5181 the bar might not be in the window. */
5182 if (cursor_glyph->type == IMAGE_GLYPH)
5184 struct glyph_row *row;
5185 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5186 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5188 else
5190 Display *dpy = FRAME_MAC_DISPLAY (f);
5191 Window window = FRAME_MAC_WINDOW (f);
5192 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5193 unsigned long mask = GCForeground | GCBackground;
5194 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5195 XGCValues xgcv;
5197 /* If the glyph's background equals the color we normally draw
5198 the bar cursor in, the bar cursor in its normal color is
5199 invisible. Use the glyph's foreground color instead in this
5200 case, on the assumption that the glyph's colors are chosen so
5201 that the glyph is legible. */
5202 if (face->background == f->output_data.mac->cursor_pixel)
5203 xgcv.background = xgcv.foreground = face->foreground;
5204 else
5205 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5207 if (gc)
5208 XChangeGC (dpy, gc, mask, &xgcv);
5209 else
5211 gc = XCreateGC (dpy, window, mask, &xgcv);
5212 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5215 if (width < 0)
5216 width = FRAME_CURSOR_WIDTH (f);
5217 width = min (cursor_glyph->pixel_width, width);
5219 w->phys_cursor_width = width;
5220 x_clip_to_row (w, row, TEXT_AREA, gc);
5222 if (kind == BAR_CURSOR)
5223 mac_fill_rectangle (f, gc,
5224 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5225 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5226 width, row->height);
5227 else
5228 mac_fill_rectangle (f, gc,
5229 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5230 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5231 row->height - width),
5232 cursor_glyph->pixel_width,
5233 width);
5235 mac_reset_clip_rectangles (f, gc);
5240 /* RIF: Define cursor CURSOR on frame F. */
5242 static void
5243 mac_define_frame_cursor (f, cursor)
5244 struct frame *f;
5245 Cursor cursor;
5247 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5249 if (dpyinfo->x_focus_frame == f)
5250 SetThemeCursor (cursor);
5254 /* RIF: Clear area on frame F. */
5256 static void
5257 mac_clear_frame_area (f, x, y, width, height)
5258 struct frame *f;
5259 int x, y, width, height;
5261 mac_clear_area (f, x, y, width, height);
5265 /* RIF: Draw cursor on window W. */
5267 static void
5268 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5269 struct window *w;
5270 struct glyph_row *glyph_row;
5271 int x, y;
5272 int cursor_type, cursor_width;
5273 int on_p, active_p;
5275 if (on_p)
5277 w->phys_cursor_type = cursor_type;
5278 w->phys_cursor_on_p = 1;
5280 if (glyph_row->exact_window_width_line_p
5281 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5283 glyph_row->cursor_in_fringe_p = 1;
5284 draw_fringe_bitmap (w, glyph_row, 0);
5286 else
5287 switch (cursor_type)
5289 case HOLLOW_BOX_CURSOR:
5290 x_draw_hollow_cursor (w, glyph_row);
5291 break;
5293 case FILLED_BOX_CURSOR:
5294 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5295 break;
5297 case BAR_CURSOR:
5298 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5299 break;
5301 case HBAR_CURSOR:
5302 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5303 break;
5305 case NO_CURSOR:
5306 w->phys_cursor_width = 0;
5307 break;
5309 default:
5310 abort ();
5316 /* Icons. */
5318 #if 0 /* MAC_TODO: no icon support yet. */
5320 x_bitmap_icon (f, icon)
5321 struct frame *f;
5322 Lisp_Object icon;
5324 HANDLE hicon;
5326 if (FRAME_W32_WINDOW (f) == 0)
5327 return 1;
5329 if (NILP (icon))
5330 hicon = LoadIcon (hinst, EMACS_CLASS);
5331 else if (STRINGP (icon))
5332 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5333 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5334 else if (SYMBOLP (icon))
5336 LPCTSTR name;
5338 if (EQ (icon, intern ("application")))
5339 name = (LPCTSTR) IDI_APPLICATION;
5340 else if (EQ (icon, intern ("hand")))
5341 name = (LPCTSTR) IDI_HAND;
5342 else if (EQ (icon, intern ("question")))
5343 name = (LPCTSTR) IDI_QUESTION;
5344 else if (EQ (icon, intern ("exclamation")))
5345 name = (LPCTSTR) IDI_EXCLAMATION;
5346 else if (EQ (icon, intern ("asterisk")))
5347 name = (LPCTSTR) IDI_ASTERISK;
5348 else if (EQ (icon, intern ("winlogo")))
5349 name = (LPCTSTR) IDI_WINLOGO;
5350 else
5351 return 1;
5353 hicon = LoadIcon (NULL, name);
5355 else
5356 return 1;
5358 if (hicon == NULL)
5359 return 1;
5361 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5362 (LPARAM) hicon);
5364 return 0;
5366 #endif /* MAC_TODO */
5368 /************************************************************************
5369 Handling X errors
5370 ************************************************************************/
5372 /* Display Error Handling functions not used on W32. Listing them here
5373 helps diff stay in step when comparing w32term.c with xterm.c.
5375 x_error_catcher (display, error)
5376 x_catch_errors (dpy)
5377 x_catch_errors_unwind (old_val)
5378 x_check_errors (dpy, format)
5379 x_had_errors_p (dpy)
5380 x_clear_errors (dpy)
5381 x_uncatch_errors (dpy, count)
5382 x_trace_wire ()
5383 x_connection_signal (signalnum)
5384 x_connection_closed (dpy, error_message)
5385 x_error_quitter (display, error)
5386 x_error_handler (display, error)
5387 x_io_error_quitter (display)
5392 /* Changing the font of the frame. */
5394 /* Give frame F the font named FONTNAME as its default font, and
5395 return the full name of that font. FONTNAME may be a wildcard
5396 pattern; in that case, we choose some font that fits the pattern.
5397 The return value shows which font we chose. */
5399 Lisp_Object
5400 x_new_font (f, fontname)
5401 struct frame *f;
5402 register char *fontname;
5404 struct font_info *fontp
5405 = FS_LOAD_FONT (f, 0, fontname, -1);
5407 if (!fontp)
5408 return Qnil;
5410 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5411 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5412 FRAME_FONTSET (f) = -1;
5414 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5415 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5416 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5418 compute_fringe_widths (f, 1);
5420 /* Compute the scroll bar width in character columns. */
5421 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5423 int wid = FRAME_COLUMN_WIDTH (f);
5424 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5425 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5427 else
5429 int wid = FRAME_COLUMN_WIDTH (f);
5430 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5433 /* Now make the frame display the given font. */
5434 if (FRAME_MAC_WINDOW (f) != 0)
5436 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5437 FRAME_FONT (f));
5438 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5439 FRAME_FONT (f));
5440 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5441 FRAME_FONT (f));
5443 /* Don't change the size of a tip frame; there's no point in
5444 doing it because it's done in Fx_show_tip, and it leads to
5445 problems because the tip frame has no widget. */
5446 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5447 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5450 return build_string (fontp->full_name);
5453 /* Give frame F the fontset named FONTSETNAME as its default font, and
5454 return the full name of that fontset. FONTSETNAME may be a wildcard
5455 pattern; in that case, we choose some fontset that fits the pattern.
5456 The return value shows which fontset we chose. */
5458 Lisp_Object
5459 x_new_fontset (f, fontsetname)
5460 struct frame *f;
5461 char *fontsetname;
5463 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5464 Lisp_Object result;
5466 if (fontset < 0)
5467 return Qnil;
5469 if (FRAME_FONTSET (f) == fontset)
5470 /* This fontset is already set in frame F. There's nothing more
5471 to do. */
5472 return fontset_name (fontset);
5474 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5476 if (!STRINGP (result))
5477 /* Can't load ASCII font. */
5478 return Qnil;
5480 /* Since x_new_font doesn't update any fontset information, do it now. */
5481 FRAME_FONTSET (f) = fontset;
5483 return build_string (fontsetname);
5487 /***********************************************************************
5488 TODO: W32 Input Methods
5489 ***********************************************************************/
5490 /* Listing missing functions from xterm.c helps diff stay in step.
5492 xim_destroy_callback (xim, client_data, call_data)
5493 xim_open_dpy (dpyinfo, resource_name)
5494 struct xim_inst_t
5495 xim_instantiate_callback (display, client_data, call_data)
5496 xim_initialize (dpyinfo, resource_name)
5497 xim_close_dpy (dpyinfo)
5502 void
5503 mac_handle_origin_change (f)
5504 struct frame *f;
5506 x_real_positions (f, &f->left_pos, &f->top_pos);
5509 void
5510 mac_handle_size_change (f, pixelwidth, pixelheight)
5511 struct frame *f;
5512 int pixelwidth, pixelheight;
5514 int cols, rows;
5516 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
5517 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
5519 if (cols != FRAME_COLS (f)
5520 || rows != FRAME_LINES (f)
5521 || pixelwidth != FRAME_PIXEL_WIDTH (f)
5522 || pixelheight != FRAME_PIXEL_HEIGHT (f))
5524 /* We pass 1 for DELAY since we can't run Lisp code inside of
5525 a BLOCK_INPUT. */
5526 change_frame_size (f, rows, cols, 0, 1, 0);
5527 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5528 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5530 /* If cursor was outside the new size, mark it as off. */
5531 mark_window_cursors_off (XWINDOW (f->root_window));
5533 /* Clear out any recollection of where the mouse highlighting
5534 was, since it might be in a place that's outside the new
5535 frame size. Actually checking whether it is outside is a
5536 pain in the neck, so don't try--just let the highlighting be
5537 done afresh with new size. */
5538 cancel_mouse_face (f);
5540 #if TARGET_API_MAC_CARBON
5541 mac_reposition_hourglass (f);
5542 #endif
5547 /* Calculate the absolute position in frame F
5548 from its current recorded position values and gravity. */
5550 void
5551 x_calc_absolute_position (f)
5552 struct frame *f;
5554 int flags = f->size_hint_flags;
5555 Rect inner, outer;
5557 /* We have nothing to do if the current position
5558 is already for the top-left corner. */
5559 if (! ((flags & XNegative) || (flags & YNegative)))
5560 return;
5562 /* Find the offsets of the outside upper-left corner of
5563 the inner window, with respect to the outer window. */
5564 BLOCK_INPUT;
5565 mac_get_window_bounds (f, &inner, &outer);
5566 UNBLOCK_INPUT;
5568 /* Treat negative positions as relative to the leftmost bottommost
5569 position that fits on the screen. */
5570 if (flags & XNegative)
5571 f->left_pos += (FRAME_MAC_DISPLAY_INFO (f)->width
5572 - (outer.right - outer.left));
5574 if (flags & YNegative)
5575 f->top_pos += (FRAME_MAC_DISPLAY_INFO (f)->height
5576 - (outer.bottom - outer.top));
5578 /* The left_pos and top_pos
5579 are now relative to the top and left screen edges,
5580 so the flags should correspond. */
5581 f->size_hint_flags &= ~ (XNegative | YNegative);
5584 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5585 to really change the position, and 0 when calling from
5586 x_make_frame_visible (in that case, XOFF and YOFF are the current
5587 position values). It is -1 when calling from x_set_frame_parameters,
5588 which means, do adjust for borders but don't change the gravity. */
5590 void
5591 x_set_offset (f, xoff, yoff, change_gravity)
5592 struct frame *f;
5593 register int xoff, yoff;
5594 int change_gravity;
5596 if (change_gravity > 0)
5598 f->top_pos = yoff;
5599 f->left_pos = xoff;
5600 f->size_hint_flags &= ~ (XNegative | YNegative);
5601 if (xoff < 0)
5602 f->size_hint_flags |= XNegative;
5603 if (yoff < 0)
5604 f->size_hint_flags |= YNegative;
5605 f->win_gravity = NorthWestGravity;
5607 x_calc_absolute_position (f);
5609 BLOCK_INPUT;
5610 x_wm_set_size_hint (f, (long) 0, 0);
5612 #if TARGET_API_MAC_CARBON
5613 mac_move_window_structure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5614 /* If the title bar is completely outside the screen, adjust the
5615 position. */
5616 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5617 kWindowConstrainMoveRegardlessOfFit
5618 | kWindowConstrainAllowPartial, NULL, NULL);
5619 if (!NILP (tip_frame) && XFRAME (tip_frame) == f)
5620 mac_handle_origin_change (f);
5621 #else
5623 Rect inner, outer, screen_rect, dummy;
5624 RgnHandle region = NewRgn ();
5626 mac_get_window_bounds (f, &inner, &outer);
5627 f->x_pixels_diff = inner.left - outer.left;
5628 f->y_pixels_diff = inner.top - outer.top;
5629 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5630 f->top_pos + f->y_pixels_diff, false);
5632 /* If the title bar is completely outside the screen, adjust the
5633 position. The variable `outer' holds the title bar rectangle.
5634 The variable `inner' holds slightly smaller one than `outer',
5635 so that the calculation of overlapping may not become too
5636 strict. */
5637 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5638 outer = (*region)->rgnBBox;
5639 DisposeRgn (region);
5640 inner = outer;
5641 InsetRect (&inner, 8, 8);
5642 screen_rect = qd.screenBits.bounds;
5643 screen_rect.top += GetMBarHeight ();
5645 if (!SectRect (&inner, &screen_rect, &dummy))
5647 if (inner.right <= screen_rect.left)
5648 f->left_pos = screen_rect.left;
5649 else if (inner.left >= screen_rect.right)
5650 f->left_pos = screen_rect.right - (outer.right - outer.left);
5652 if (inner.bottom <= screen_rect.top)
5653 f->top_pos = screen_rect.top;
5654 else if (inner.top >= screen_rect.bottom)
5655 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5657 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5658 f->top_pos + f->y_pixels_diff, false);
5661 #endif
5663 UNBLOCK_INPUT;
5666 /* Call this to change the size of frame F's x-window.
5667 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5668 for this size change and subsequent size changes.
5669 Otherwise we leave the window gravity unchanged. */
5671 void
5672 x_set_window_size (f, change_gravity, cols, rows)
5673 struct frame *f;
5674 int change_gravity;
5675 int cols, rows;
5677 int pixelwidth, pixelheight;
5679 BLOCK_INPUT;
5681 check_frame_size (f, &rows, &cols);
5682 f->scroll_bar_actual_width
5683 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5685 compute_fringe_widths (f, 0);
5687 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5688 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5690 f->win_gravity = NorthWestGravity;
5691 x_wm_set_size_hint (f, (long) 0, 0);
5693 mac_size_window (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5695 #if TARGET_API_MAC_CARBON
5696 if (!NILP (tip_frame) && f == XFRAME (tip_frame))
5697 #endif
5698 mac_handle_size_change (f, pixelwidth, pixelheight);
5700 if (f->output_data.mac->internal_border_width
5701 != FRAME_INTERNAL_BORDER_WIDTH (f))
5703 mac_clear_window (f);
5704 f->output_data.mac->internal_border_width
5705 = FRAME_INTERNAL_BORDER_WIDTH (f);
5708 SET_FRAME_GARBAGED (f);
5710 UNBLOCK_INPUT;
5713 /* Mouse warping. */
5715 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5717 void
5718 x_set_mouse_position (f, x, y)
5719 struct frame *f;
5720 int x, y;
5722 int pix_x, pix_y;
5724 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5725 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5727 if (pix_x < 0) pix_x = 0;
5728 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5730 if (pix_y < 0) pix_y = 0;
5731 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5733 x_set_mouse_pixel_position (f, pix_x, pix_y);
5736 void
5737 x_set_mouse_pixel_position (f, pix_x, pix_y)
5738 struct frame *f;
5739 int pix_x, pix_y;
5741 #ifdef MAC_OSX
5742 BLOCK_INPUT;
5743 mac_convert_frame_point_to_global (f, &pix_x, &pix_y);
5744 CGWarpMouseCursorPosition (CGPointMake (pix_x, pix_y));
5745 UNBLOCK_INPUT;
5746 #else
5747 #if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */
5748 BLOCK_INPUT;
5750 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5751 0, 0, 0, 0, pix_x, pix_y);
5752 UNBLOCK_INPUT;
5753 #endif
5754 #endif
5757 /* focus shifting, raising and lowering. */
5759 void
5760 x_focus_on_frame (f)
5761 struct frame *f;
5763 #if 0 /* This proves to be unpleasant. */
5764 x_raise_frame (f);
5765 #endif
5766 #if 0
5767 /* I don't think that the ICCCM allows programs to do things like this
5768 without the interaction of the window manager. Whatever you end up
5769 doing with this code, do it to x_unfocus_frame too. */
5770 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5771 RevertToPointerRoot, CurrentTime);
5772 #endif /* ! 0 */
5775 void
5776 x_unfocus_frame (f)
5777 struct frame *f;
5781 /* Raise frame F. */
5783 void
5784 x_raise_frame (f)
5785 struct frame *f;
5787 if (f->async_visible)
5789 BLOCK_INPUT;
5790 mac_bring_window_to_front (FRAME_MAC_WINDOW (f));
5791 UNBLOCK_INPUT;
5795 /* Lower frame F. */
5797 void
5798 x_lower_frame (f)
5799 struct frame *f;
5801 if (f->async_visible)
5803 BLOCK_INPUT;
5804 mac_send_window_behind (FRAME_MAC_WINDOW (f), NULL);
5805 UNBLOCK_INPUT;
5809 static void
5810 XTframe_raise_lower (f, raise_flag)
5811 FRAME_PTR f;
5812 int raise_flag;
5814 if (raise_flag)
5815 x_raise_frame (f);
5816 else
5817 x_lower_frame (f);
5820 /* Change of visibility. */
5822 void
5823 mac_handle_visibility_change (f)
5824 struct frame *f;
5826 Window wp = FRAME_MAC_WINDOW (f);
5827 int visible = 0, iconified = 0;
5828 struct input_event buf;
5830 if (mac_is_window_visible (wp))
5832 if (mac_is_window_collapsed (wp))
5833 iconified = 1;
5834 else
5835 visible = 1;
5838 if (!f->async_visible && visible)
5840 if (f->iconified)
5842 /* wait_reading_process_output will notice this and update
5843 the frame's display structures. If we were made
5844 invisible, we should not set garbaged, because that stops
5845 redrawing on Update events. */
5846 SET_FRAME_GARBAGED (f);
5848 EVENT_INIT (buf);
5849 buf.kind = DEICONIFY_EVENT;
5850 XSETFRAME (buf.frame_or_window, f);
5851 buf.arg = Qnil;
5852 kbd_buffer_store_event (&buf);
5854 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
5855 /* Force a redisplay sooner or later to update the
5856 frame titles in case this is the second frame. */
5857 record_asynch_buffer_change ();
5859 else if (f->async_visible && !visible)
5860 if (iconified)
5862 EVENT_INIT (buf);
5863 buf.kind = ICONIFY_EVENT;
5864 XSETFRAME (buf.frame_or_window, f);
5865 buf.arg = Qnil;
5866 kbd_buffer_store_event (&buf);
5869 f->async_visible = visible;
5870 f->async_iconified = iconified;
5873 /* This tries to wait until the frame is really visible.
5874 However, if the window manager asks the user where to position
5875 the frame, this will return before the user finishes doing that.
5876 The frame will not actually be visible at that time,
5877 but it will become visible later when the window manager
5878 finishes with it. */
5880 void
5881 x_make_frame_visible (f)
5882 struct frame *f;
5884 BLOCK_INPUT;
5886 if (! FRAME_VISIBLE_P (f))
5888 /* We test FRAME_GARBAGED_P here to make sure we don't
5889 call x_set_offset a second time
5890 if we get to x_make_frame_visible a second time
5891 before the window gets really visible. */
5892 if (! FRAME_ICONIFIED_P (f)
5893 && ! f->output_data.mac->asked_for_visible)
5894 x_set_offset (f, f->left_pos, f->top_pos, 0);
5896 f->output_data.mac->asked_for_visible = 1;
5898 mac_collapse_window (FRAME_MAC_WINDOW (f), false);
5899 mac_show_window (FRAME_MAC_WINDOW (f));
5902 XFlush (FRAME_MAC_DISPLAY (f));
5904 /* Synchronize to ensure Emacs knows the frame is visible
5905 before we do anything else. We do this loop with input not blocked
5906 so that incoming events are handled. */
5908 Lisp_Object frame;
5909 int count;
5911 /* This must come after we set COUNT. */
5912 UNBLOCK_INPUT;
5914 XSETFRAME (frame, f);
5916 /* Wait until the frame is visible. Process X events until a
5917 MapNotify event has been seen, or until we think we won't get a
5918 MapNotify at all.. */
5919 for (count = input_signal_count + 10;
5920 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5922 /* Force processing of queued events. */
5923 x_sync (f);
5925 /* Machines that do polling rather than SIGIO have been
5926 observed to go into a busy-wait here. So we'll fake an
5927 alarm signal to let the handler know that there's something
5928 to be read. We used to raise a real alarm, but it seems
5929 that the handler isn't always enabled here. This is
5930 probably a bug. */
5931 if (input_polling_used ())
5933 /* It could be confusing if a real alarm arrives while
5934 processing the fake one. Turn it off and let the
5935 handler reset it. */
5936 extern void poll_for_input_1 P_ ((void));
5937 int old_poll_suppress_count = poll_suppress_count;
5938 poll_suppress_count = 1;
5939 poll_for_input_1 ();
5940 poll_suppress_count = old_poll_suppress_count;
5943 /* See if a MapNotify event has been processed. */
5944 FRAME_SAMPLE_VISIBILITY (f);
5949 /* Change from mapped state to withdrawn state. */
5951 /* Make the frame visible (mapped and not iconified). */
5953 void
5954 x_make_frame_invisible (f)
5955 struct frame *f;
5957 /* A deactivate event does not occur when the last visible frame is
5958 made invisible. So if we clear the highlight here, it will not
5959 be rehighlighted when it is made visible. */
5960 #if 0
5961 /* Don't keep the highlight on an invisible frame. */
5962 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5963 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5964 #endif
5966 BLOCK_INPUT;
5968 #if !TARGET_API_MAC_CARBON
5969 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5970 that the current position of the window is user-specified, rather than
5971 program-specified, so that when the window is mapped again, it will be
5972 placed at the same location, without forcing the user to position it
5973 by hand again (they have already done that once for this window.) */
5974 x_wm_set_size_hint (f, (long) 0, 1);
5975 #endif
5977 mac_hide_window (FRAME_MAC_WINDOW (f));
5979 UNBLOCK_INPUT;
5981 #if !TARGET_API_MAC_CARBON
5982 mac_handle_visibility_change (f);
5983 #endif
5986 /* Change window state from mapped to iconified. */
5988 void
5989 x_iconify_frame (f)
5990 struct frame *f;
5992 OSStatus err;
5994 /* A deactivate event does not occur when the last visible frame is
5995 iconified. So if we clear the highlight here, it will not be
5996 rehighlighted when it is deiconified. */
5997 #if 0
5998 /* Don't keep the highlight on an invisible frame. */
5999 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6000 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6001 #endif
6003 if (f->async_iconified)
6004 return;
6006 BLOCK_INPUT;
6008 FRAME_SAMPLE_VISIBILITY (f);
6010 if (! FRAME_VISIBLE_P (f))
6011 mac_show_window (FRAME_MAC_WINDOW (f));
6013 err = mac_collapse_window (FRAME_MAC_WINDOW (f), true);
6015 UNBLOCK_INPUT;
6017 if (err != noErr)
6018 error ("Can't notify window manager of iconification");
6020 #if !TARGET_API_MAC_CARBON
6021 mac_handle_visibility_change (f);
6022 #endif
6026 /* Free X resources of frame F. */
6028 void
6029 x_free_frame_resources (f)
6030 struct frame *f;
6032 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6033 Window wp = FRAME_MAC_WINDOW (f);
6035 BLOCK_INPUT;
6037 /* AppKit version of mac_dispose_frame_window, which is implemented
6038 as -[NSWindow close], will change the focus to the next window
6039 during its call. So, unlike other platforms, we clean up the
6040 focus-related variables before calling mac_dispose_frame_window. */
6041 if (f == dpyinfo->x_focus_frame)
6043 dpyinfo->x_focus_frame = 0;
6044 #if USE_MAC_FONT_PANEL
6045 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6046 #endif
6048 if (f == dpyinfo->x_focus_event_frame)
6049 dpyinfo->x_focus_event_frame = 0;
6050 if (f == dpyinfo->x_highlight_frame)
6051 dpyinfo->x_highlight_frame = 0;
6053 if (f == dpyinfo->mouse_face_mouse_frame)
6055 dpyinfo->mouse_face_beg_row
6056 = dpyinfo->mouse_face_beg_col = -1;
6057 dpyinfo->mouse_face_end_row
6058 = dpyinfo->mouse_face_end_col = -1;
6059 dpyinfo->mouse_face_window = Qnil;
6060 dpyinfo->mouse_face_deferred_gc = 0;
6061 dpyinfo->mouse_face_mouse_frame = 0;
6064 mac_dispose_frame_window (f);
6065 if (wp == tip_window)
6066 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6067 closed' event. So we reset tip_window here. */
6068 tip_window = NULL;
6070 free_frame_menubar (f);
6072 if (FRAME_FACE_CACHE (f))
6073 free_frame_faces (f);
6075 x_free_gcs (f);
6077 if (FRAME_SIZE_HINTS (f))
6078 xfree (FRAME_SIZE_HINTS (f));
6080 xfree (f->output_data.mac);
6081 f->output_data.mac = NULL;
6083 UNBLOCK_INPUT;
6087 /* Destroy the X window of frame F. */
6089 void
6090 x_destroy_window (f)
6091 struct frame *f;
6093 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6095 x_free_frame_resources (f);
6097 dpyinfo->reference_count--;
6101 /* Setting window manager hints. */
6103 /* Set the normal size hints for the window manager, for frame F.
6104 FLAGS is the flags word to use--or 0 meaning preserve the flags
6105 that the window now has.
6106 If USER_POSITION is nonzero, we set the USPosition
6107 flag (this is useful when FLAGS is 0). */
6108 void
6109 x_wm_set_size_hint (f, flags, user_position)
6110 struct frame *f;
6111 long flags;
6112 int user_position;
6114 int base_width, base_height, width_inc, height_inc;
6115 int min_rows = 0, min_cols = 0;
6116 XSizeHints *size_hints;
6118 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6119 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6120 width_inc = FRAME_COLUMN_WIDTH (f);
6121 height_inc = FRAME_LINE_HEIGHT (f);
6123 check_frame_size (f, &min_rows, &min_cols);
6125 size_hints = FRAME_SIZE_HINTS (f);
6126 if (size_hints == NULL)
6128 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6129 bzero (size_hints, sizeof (XSizeHints));
6132 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6133 size_hints->width_inc = width_inc;
6134 size_hints->height_inc = height_inc;
6135 size_hints->min_width = base_width + min_cols * width_inc;
6136 size_hints->min_height = base_height + min_rows * height_inc;
6137 size_hints->base_width = base_width;
6138 size_hints->base_height = base_height;
6140 if (flags)
6141 size_hints->flags = flags;
6142 else if (user_position)
6144 size_hints->flags &= ~ PPosition;
6145 size_hints->flags |= USPosition;
6149 #if 0 /* MAC_TODO: hide application instead of iconify? */
6150 /* Used for IconicState or NormalState */
6152 void
6153 x_wm_set_window_state (f, state)
6154 struct frame *f;
6155 int state;
6157 #ifdef USE_X_TOOLKIT
6158 Arg al[1];
6160 XtSetArg (al[0], XtNinitialState, state);
6161 XtSetValues (f->output_data.x->widget, al, 1);
6162 #else /* not USE_X_TOOLKIT */
6163 Window window = FRAME_X_WINDOW (f);
6165 f->output_data.x->wm_hints.flags |= StateHint;
6166 f->output_data.x->wm_hints.initial_state = state;
6168 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6169 #endif /* not USE_X_TOOLKIT */
6172 void
6173 x_wm_set_icon_pixmap (f, pixmap_id)
6174 struct frame *f;
6175 int pixmap_id;
6177 Pixmap icon_pixmap;
6179 #ifndef USE_X_TOOLKIT
6180 Window window = FRAME_X_WINDOW (f);
6181 #endif
6183 if (pixmap_id > 0)
6185 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6186 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6188 else
6190 /* It seems there is no way to turn off use of an icon pixmap.
6191 The following line does it, only if no icon has yet been created,
6192 for some window managers. But with mwm it crashes.
6193 Some people say it should clear the IconPixmapHint bit in this case,
6194 but that doesn't work, and the X consortium said it isn't the
6195 right thing at all. Since there is no way to win,
6196 best to explicitly give up. */
6197 #if 0
6198 f->output_data.x->wm_hints.icon_pixmap = None;
6199 #else
6200 return;
6201 #endif
6204 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6207 Arg al[1];
6208 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6209 XtSetValues (f->output_data.x->widget, al, 1);
6212 #else /* not USE_X_TOOLKIT */
6214 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6215 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6217 #endif /* not USE_X_TOOLKIT */
6220 #endif /* MAC_TODO */
6222 void
6223 x_wm_set_icon_position (f, icon_x, icon_y)
6224 struct frame *f;
6225 int icon_x, icon_y;
6227 #if 0 /* MAC_TODO: no icons on Mac */
6228 #ifdef USE_X_TOOLKIT
6229 Window window = XtWindow (f->output_data.x->widget);
6230 #else
6231 Window window = FRAME_X_WINDOW (f);
6232 #endif
6234 f->output_data.x->wm_hints.flags |= IconPositionHint;
6235 f->output_data.x->wm_hints.icon_x = icon_x;
6236 f->output_data.x->wm_hints.icon_y = icon_y;
6238 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6239 #endif /* MAC_TODO */
6243 /***********************************************************************
6244 XLFD Pattern Match
6245 ***********************************************************************/
6247 /* An XLFD pattern is divided into blocks delimited by '*'. This
6248 structure holds information for each block. */
6249 struct xlfdpat_block
6251 /* Length of the pattern string in this block. Non-zero except for
6252 the first and the last blocks. */
6253 int len;
6255 /* Pattern string except the last character in this block. The last
6256 character is replaced with NUL in order to use it as a
6257 sentinel. */
6258 unsigned char *pattern;
6260 /* Last character of the pattern string. Must not be '?'. */
6261 unsigned char last_char;
6263 /* One of the tables for the Boyer-Moore string search. It
6264 specifies the number of positions to proceed for each character
6265 with which the match fails. */
6266 int skip[256];
6268 /* The skip value for the last character in the above `skip' is
6269 assigned to `infinity' in order to simplify a loop condition.
6270 The original value is saved here. */
6271 int last_char_skip;
6274 struct xlfdpat
6276 /* Normalized pattern string. "Normalized" means that capital
6277 letters are lowered, blocks are not empty except the first and
6278 the last ones, and trailing '?'s in a block that is not the last
6279 one are moved to the next one. The last character in each block
6280 is replaced with NUL. */
6281 unsigned char *buf;
6283 /* Number of characters except '*'s and trailing '?'s in the
6284 normalized pattern string. */
6285 int nchars;
6287 /* Number of trailing '?'s in the normalized pattern string. */
6288 int trailing_anychars;
6290 /* Number of blocks and information for each block. The latter is
6291 NULL if the pattern is exact (no '*' or '?' in it). */
6292 int nblocks;
6293 struct xlfdpat_block *blocks;
6296 static void
6297 xlfdpat_destroy (pat)
6298 struct xlfdpat *pat;
6300 if (pat)
6302 if (pat->buf)
6304 if (pat->blocks)
6305 xfree (pat->blocks);
6306 xfree (pat->buf);
6308 xfree (pat);
6312 static struct xlfdpat *
6313 xlfdpat_create (pattern)
6314 const char *pattern;
6316 struct xlfdpat *pat;
6317 int nblocks, i, skip;
6318 unsigned char last_char, *p, *q, *anychar_head;
6319 const unsigned char *ptr;
6320 struct xlfdpat_block *blk;
6322 pat = xmalloc (sizeof (struct xlfdpat));
6323 pat->buf = xmalloc (strlen (pattern) + 1);
6325 /* Normalize the pattern string and store it to `pat->buf'. */
6326 nblocks = 0;
6327 anychar_head = NULL;
6328 q = pat->buf;
6329 last_char = '\0';
6330 for (ptr = pattern; *ptr; ptr++)
6332 unsigned char c = *ptr;
6334 if (c == '*')
6335 if (last_char == '*')
6336 /* ...a** -> ...a* */
6337 continue;
6338 else
6340 if (last_char == '?')
6342 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6343 /* ...*??* -> ...*?? */
6344 continue;
6345 else
6346 /* ...a??* -> ...a*?? */
6348 *anychar_head++ = '*';
6349 c = '?';
6352 nblocks++;
6354 else if (c == '?')
6356 if (last_char != '?')
6357 anychar_head = q;
6359 else
6360 /* On Mac OS X 10.3, tolower also converts non-ASCII
6361 characters for some locales. */
6362 if (isascii (c))
6363 c = tolower (c);
6365 *q++ = last_char = c;
6367 *q = '\0';
6368 nblocks++;
6369 pat->nblocks = nblocks;
6370 if (last_char != '?')
6371 pat->trailing_anychars = 0;
6372 else
6374 pat->trailing_anychars = q - anychar_head;
6375 q = anychar_head;
6377 pat->nchars = q - pat->buf - (nblocks - 1);
6379 if (anychar_head == NULL && nblocks == 1)
6381 /* The pattern is exact. */
6382 pat->blocks = NULL;
6383 return pat;
6386 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6388 /* Divide the normalized pattern into blocks. */
6389 p = pat->buf;
6390 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6392 blk->pattern = p;
6393 while (*p != '*')
6394 p++;
6395 blk->len = p - blk->pattern;
6396 p++;
6398 blk->pattern = p;
6399 blk->len = q - blk->pattern;
6401 /* Setup a table for the Boyer-Moore string search. */
6402 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6403 if (blk->len != 0)
6405 blk->last_char = blk->pattern[blk->len - 1];
6406 blk->pattern[blk->len - 1] = '\0';
6408 for (skip = 1; skip < blk->len; skip++)
6409 if (blk->pattern[blk->len - skip - 1] == '?')
6410 break;
6412 for (i = 0; i < 256; i++)
6413 blk->skip[i] = skip;
6415 p = blk->pattern + (blk->len - skip);
6416 while (--skip > 0)
6417 blk->skip[*p++] = skip;
6419 blk->last_char_skip = blk->skip[blk->last_char];
6422 return pat;
6425 static INLINE int
6426 xlfdpat_exact_p (pat)
6427 struct xlfdpat *pat;
6429 return pat->blocks == NULL;
6432 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6433 that the pattern in *BLK matches with its prefix. Return NULL
6434 there is no such strings. STRING must be lowered in advance. */
6436 static const char *
6437 xlfdpat_block_match_1 (blk, string, start_max)
6438 struct xlfdpat_block *blk;
6439 const unsigned char *string;
6440 int start_max;
6442 int start, infinity;
6443 unsigned char *p;
6444 const unsigned char *s;
6446 xassert (blk->len > 0);
6447 xassert (start_max + blk->len <= strlen (string));
6448 xassert (blk->last_char != '?');
6450 /* See the comments in the function `boyer_moore' (search.c) for the
6451 use of `infinity'. */
6452 infinity = start_max + blk->len + 1;
6453 blk->skip[blk->last_char] = infinity;
6455 start = 0;
6458 /* Check the last character of the pattern. */
6459 s = string + blk->len - 1;
6462 start += blk->skip[*(s + start)];
6464 while (start <= start_max);
6466 if (start < infinity)
6467 /* Couldn't find the last character. */
6468 return NULL;
6470 /* No less than `infinity' means we could find the last
6471 character at `s[start - infinity]'. */
6472 start -= infinity;
6474 /* Check the remaining characters. We prefer making no-'?'
6475 cases faster because the use of '?' is really rare. */
6476 p = blk->pattern;
6477 s = string + start;
6480 while (*p++ == *s++)
6483 while (*(p - 1) == '?');
6485 if (*(p - 1) == '\0')
6486 /* Matched. */
6487 return string + start;
6489 /* Didn't match. */
6490 start += blk->last_char_skip;
6492 while (start <= start_max);
6494 return NULL;
6497 #define xlfdpat_block_match(b, s, m) \
6498 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6499 : xlfdpat_block_match_1 (b, s, m))
6501 /* Check if XLFD pattern PAT, which is generated by `xlfdpat_create',
6502 matches with STRING. STRING must be lowered in advance. */
6504 static int
6505 xlfdpat_match (pat, string)
6506 struct xlfdpat *pat;
6507 const unsigned char *string;
6509 int str_len, nblocks, i, start_max;
6510 struct xlfdpat_block *blk;
6511 const unsigned char *s;
6513 xassert (pat->nblocks > 0);
6515 if (xlfdpat_exact_p (pat))
6516 return strcmp (pat->buf, string) == 0;
6518 /* The number of the characters in the string must not be smaller
6519 than that in the pattern. */
6520 str_len = strlen (string);
6521 if (str_len < pat->nchars + pat->trailing_anychars)
6522 return 0;
6524 /* Chop off the trailing '?'s. */
6525 str_len -= pat->trailing_anychars;
6527 /* The last block. When it is non-empty, it must match at the end
6528 of the string. */
6529 nblocks = pat->nblocks;
6530 blk = pat->blocks + (nblocks - 1);
6531 if (nblocks == 1)
6532 /* The last block is also the first one. */
6533 return (str_len == blk->len
6534 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6535 else if (blk->len != 0)
6536 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6537 return 0;
6539 /* The first block. When it is non-empty, it must match at the
6540 beginning of the string. */
6541 blk = pat->blocks;
6542 if (blk->len != 0)
6544 s = xlfdpat_block_match (blk, string, 0);
6545 if (s == NULL)
6546 return 0;
6547 string = s + blk->len;
6550 /* The rest of the blocks. */
6551 start_max = str_len - pat->nchars;
6552 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6554 s = xlfdpat_block_match (blk, string, start_max);
6555 if (s == NULL)
6556 return 0;
6557 start_max -= s - string;
6558 string = s + blk->len;
6561 return 1;
6565 /***********************************************************************
6566 Fonts
6567 ***********************************************************************/
6569 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6571 struct font_info *
6572 x_get_font_info (f, font_idx)
6573 FRAME_PTR f;
6574 int font_idx;
6576 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6579 /* the global font name table */
6580 static char **font_name_table = NULL;
6581 static int font_name_table_size = 0;
6582 static int font_name_count = 0;
6584 /* Alist linking font family names to Font Manager font family
6585 references (which can also be used as QuickDraw font IDs). We use
6586 an alist because hash tables are not ready when the terminal frame
6587 for Mac OS Classic is created. */
6588 static Lisp_Object fm_font_family_alist;
6589 #if USE_ATSUI
6590 /* Hash table linking font family names to ATSU font IDs. */
6591 static Lisp_Object atsu_font_id_hash;
6592 /* Alist linking Font Manager style to face attributes. */
6593 static Lisp_Object fm_style_face_attributes_alist;
6594 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
6595 #endif
6596 #if USE_MAC_FONT_PANEL
6597 Lisp_Object Qpanel_closed, Qselection;
6598 #endif
6600 /* Alist linking character set strings to Mac text encoding and Emacs
6601 coding system. */
6602 static Lisp_Object Vmac_charset_info_alist;
6604 static Lisp_Object
6605 create_text_encoding_info_alist ()
6607 Lisp_Object result = Qnil, rest;
6609 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6611 Lisp_Object charset_info = XCAR (rest);
6612 Lisp_Object charset, coding_system, text_encoding;
6613 Lisp_Object existing_info;
6615 if (!(CONSP (charset_info)
6616 && (charset = XCAR (charset_info),
6617 STRINGP (charset))
6618 && CONSP (XCDR (charset_info))
6619 && (text_encoding = XCAR (XCDR (charset_info)),
6620 INTEGERP (text_encoding))
6621 && CONSP (XCDR (XCDR (charset_info)))
6622 && (coding_system = XCAR (XCDR (XCDR (charset_info))),
6623 SYMBOLP (coding_system))))
6624 continue;
6626 existing_info = assq_no_quit (text_encoding, result);
6627 if (NILP (existing_info))
6628 result = Fcons (list3 (text_encoding, coding_system, charset),
6629 result);
6630 else
6631 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6632 XSETCDR (XCDR (existing_info),
6633 Fcons (charset, XCDR (XCDR (existing_info))));
6636 return result;
6640 static void
6641 decode_mac_font_name (name, size, coding_system)
6642 char *name;
6643 int size;
6644 Lisp_Object coding_system;
6646 struct coding_system coding;
6647 char *buf, *p;
6649 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6651 for (p = name; *p; p++)
6652 if (!isascii (*p) || iscntrl (*p))
6653 break;
6655 if (*p)
6657 setup_coding_system (coding_system, &coding);
6658 coding.src_multibyte = 0;
6659 coding.dst_multibyte = 1;
6660 coding.mode |= CODING_MODE_LAST_BLOCK;
6661 coding.composing = COMPOSITION_DISABLED;
6662 buf = (char *) alloca (size);
6664 decode_coding (&coding, name, buf, strlen (name), size - 1);
6665 bcopy (buf, name, coding.produced);
6666 name[coding.produced] = '\0';
6670 /* If there's just one occurrence of '-' in the family name, it is
6671 replaced with '_'. (More than one occurrence of '-' means a
6672 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6673 p = strchr (name, '-');
6674 if (p && strchr (p + 1, '-') == NULL)
6675 *p = '_';
6677 for (p = name; *p; p++)
6678 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6679 for some locales. */
6680 if (isascii (*p))
6681 *p = tolower (*p);
6685 static char *
6686 mac_to_x_fontname (name, size, style, charset)
6687 const char *name;
6688 int size;
6689 Style style;
6690 char *charset;
6692 Str31 foundry, cs;
6693 Str255 family;
6694 char xf[256], *result;
6695 unsigned char *p;
6697 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6698 charset = cs;
6699 else
6701 strcpy(foundry, "Apple");
6702 strcpy(family, name);
6705 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6706 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
6707 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
6709 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6710 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6711 for (p = result; *p; p++)
6712 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6713 for some locales. */
6714 if (isascii (*p))
6715 *p = tolower (*p);
6716 return result;
6720 /* Parse fully-specified and instantiated X11 font spec XF, and store
6721 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6722 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6723 caller must allocate at least 256 and 32 bytes respectively. For
6724 ordinary Mac fonts, the value stored to FAMILY should just be their
6725 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6726 intlfonts collection contain their charset designation in their
6727 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6728 types of font names are handled accordingly. */
6730 const int kDefaultFontSize = 12;
6732 static int
6733 parse_x_font_name (xf, family, size, style, charset)
6734 const char *xf;
6735 char *family;
6736 int *size;
6737 Style *style;
6738 char *charset;
6740 Str31 foundry, weight;
6741 int point_size, avgwidth;
6742 char slant[2], *p;
6744 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6745 foundry, family, weight, slant, size,
6746 &point_size, &avgwidth, charset) != 8
6747 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6748 foundry, family, weight, slant, size,
6749 &point_size, &avgwidth, charset) != 8)
6750 return 0;
6752 if (*size == 0)
6754 if (point_size > 0)
6755 *size = point_size / 10;
6756 else if (avgwidth > 0)
6757 *size = avgwidth / 10;
6759 if (*size == 0)
6760 *size = kDefaultFontSize;
6762 *style = normal;
6763 if (strcmp (weight, "bold") == 0)
6764 *style |= bold;
6765 if (*slant == 'i')
6766 *style |= italic;
6768 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
6770 int foundry_len = strlen (foundry), family_len = strlen (family);
6772 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
6774 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6775 but take overlap into account. */
6776 memmove (family + foundry_len + 1, family, family_len);
6777 memcpy (family, foundry, foundry_len);
6778 family[foundry_len] = '-';
6779 family[foundry_len + 1 + family_len] = '-';
6780 strcpy (family + foundry_len + 1 + family_len + 1, charset);
6782 else
6783 return 0;
6786 for (p = family; *p; p++)
6787 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6788 for some locales. */
6789 if (isascii (*p))
6790 *p = tolower (*p);
6792 return 1;
6796 static void
6797 add_font_name_table_entry (char *font_name)
6799 if (font_name_table_size == 0)
6801 font_name_table_size = 256;
6802 font_name_table = (char **)
6803 xmalloc (font_name_table_size * sizeof (char *));
6805 else if (font_name_count + 1 >= font_name_table_size)
6807 font_name_table_size *= 2;
6808 font_name_table = (char **)
6809 xrealloc (font_name_table,
6810 font_name_table_size * sizeof (char *));
6813 font_name_table[font_name_count++] = font_name;
6816 static void
6817 add_mac_font_name (name, size, style, charset)
6818 const char *name;
6819 int size;
6820 Style style;
6821 const char *charset;
6823 if (size > 0)
6824 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
6825 else
6827 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
6828 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
6829 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
6830 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
6831 charset));
6835 #if USE_ATSUI
6836 static FMFontStyle
6837 fm_get_style_from_font (font)
6838 FMFont font;
6840 OSStatus err;
6841 FMFontStyle style = normal;
6842 ByteCount len;
6843 UInt16 mac_style;
6844 FMFontFamily font_family;
6845 #define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4)
6847 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of
6848 some font (e.g., Optima) even if it is `bold'. */
6849 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET,
6850 sizeof (mac_style), &mac_style, &len);
6851 if (err == noErr
6852 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style))
6853 style = EndianU16_BtoN (mac_style);
6854 else
6855 FMGetFontFamilyInstanceFromFont (font, &font_family, &style);
6857 return style;
6860 static ATSUFontID
6861 atsu_find_font_from_family_name (family)
6862 const char *family;
6864 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash);
6865 unsigned hash_code;
6866 int i;
6867 Lisp_Object rest, best;
6868 FMFontStyle min_style, style;
6870 i = hash_lookup (h, make_unibyte_string (family, strlen (family)),
6871 &hash_code);
6872 if (i < 0)
6873 return kATSUInvalidFontID;
6875 rest = HASH_VALUE (h, i);
6876 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest))))
6877 return cons_to_long (rest);
6879 rest = Fnreverse (rest);
6880 best = XCAR (rest);
6881 rest = XCDR (rest);
6882 if (!NILP (rest)
6883 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal)
6886 style = fm_get_style_from_font (cons_to_long (XCAR (rest)));
6887 if (style < min_style)
6889 best = XCAR (rest);
6890 if (style == normal)
6891 break;
6892 else
6893 min_style = style;
6895 rest = XCDR (rest);
6897 while (!NILP (rest));
6899 HASH_VALUE (h, i) = best;
6900 return cons_to_long (best);
6903 static Lisp_Object
6904 fm_style_to_face_attributes (fm_style)
6905 FMFontStyle fm_style;
6907 Lisp_Object tem;
6909 fm_style &= (bold | italic);
6910 tem = assq_no_quit (make_number (fm_style),
6911 fm_style_face_attributes_alist);
6912 if (!NILP (tem))
6913 return XCDR (tem);
6915 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal,
6916 QCslant, fm_style & italic ? Qitalic : Qnormal);
6917 fm_style_face_attributes_alist =
6918 Fcons (Fcons (make_number (fm_style), tem),
6919 fm_style_face_attributes_alist);
6921 return tem;
6924 static Lisp_Object
6925 atsu_find_font_family_name (font_id)
6926 ATSUFontID font_id;
6928 OSStatus err;
6929 ByteCount len;
6930 Lisp_Object family = Qnil;
6932 err = ATSUFindFontName (font_id, kFontFamilyName,
6933 kFontMacintoshPlatform, kFontNoScript,
6934 kFontNoLanguage, 0, NULL, &len, NULL);
6935 if (err == noErr)
6937 family = make_uninit_string (len);
6938 err = ATSUFindFontName (font_id, kFontFamilyName,
6939 kFontMacintoshPlatform, kFontNoScript,
6940 kFontNoLanguage, len, SDATA (family),
6941 NULL, NULL);
6943 if (err == noErr)
6944 decode_mac_font_name (SDATA (family), len + 1, Qnil);
6946 return family;
6949 Lisp_Object
6950 mac_atsu_font_face_attributes (font_id)
6951 ATSUFontID font_id;
6953 Lisp_Object family, style_attrs;
6955 family = atsu_find_font_family_name (font_id);
6956 if (NILP (family))
6957 return Qnil;
6958 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id));
6959 return Fcons (QCfamily, Fcons (family, style_attrs));
6961 #endif
6963 /* Sets up the table font_name_table to contain the list of all fonts
6964 in the system the first time the table is used so that the Resource
6965 Manager need not be accessed every time this information is
6966 needed. */
6968 static void
6969 init_font_name_table ()
6971 #if TARGET_API_MAC_CARBON
6972 FMFontFamilyIterator ffi;
6973 FMFontFamilyInstanceIterator ffii;
6974 FMFontFamily ff;
6975 Lisp_Object text_encoding_info_alist;
6976 struct gcpro gcpro1;
6978 text_encoding_info_alist = create_text_encoding_info_alist ();
6980 #if USE_ATSUI
6981 #if USE_CG_TEXT_DRAWING
6982 init_cg_text_anti_aliasing_threshold ();
6983 #endif
6984 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6985 text_encoding_info_alist)))
6987 OSStatus err;
6988 struct Lisp_Hash_Table *h;
6989 unsigned hash_code;
6990 ItemCount nfonts, i;
6991 ATSUFontID *font_ids = NULL;
6992 Lisp_Object prev_family = Qnil;
6993 int j;
6995 atsu_font_id_hash =
6996 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
6997 make_float (DEFAULT_REHASH_SIZE),
6998 make_float (DEFAULT_REHASH_THRESHOLD),
6999 Qnil, Qnil, Qnil);
7000 h = XHASH_TABLE (atsu_font_id_hash);
7002 err = ATSUFontCount (&nfonts);
7003 if (err == noErr)
7005 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7006 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7008 if (err == noErr)
7009 for (i = 0; i < nfonts; i++)
7011 Lisp_Object family;
7013 family = atsu_find_font_family_name (font_ids[i]);
7014 if (NILP (family) || SREF (family, 0) == '.')
7015 continue;
7016 if (!NILP (Fequal (prev_family, family)))
7017 family = prev_family;
7018 else
7019 j = hash_lookup (h, family, &hash_code);
7020 if (j < 0)
7022 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1");
7023 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]),
7024 Qnil), hash_code);
7026 else if (EQ (prev_family, family))
7027 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]),
7028 HASH_VALUE (h, j));
7029 prev_family = family;
7031 if (font_ids)
7032 xfree (font_ids);
7034 #endif
7036 /* Create a dummy instance iterator here to avoid creating and
7037 destroying it in the loop. */
7038 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7039 return;
7040 /* Create an iterator to enumerate the font families. */
7041 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7042 != noErr)
7044 FMDisposeFontFamilyInstanceIterator (&ffii);
7045 return;
7048 GCPRO1 (text_encoding_info_alist);
7050 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
7052 Str255 name;
7053 FMFont font;
7054 FMFontStyle style;
7055 FMFontSize size;
7056 TextEncoding encoding;
7057 TextEncodingBase sc;
7058 Lisp_Object text_encoding_info, family;
7060 if (FMGetFontFamilyName (ff, name) != noErr)
7061 continue;
7062 p2cstr (name);
7063 if (*name == '.')
7064 continue;
7066 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
7067 continue;
7068 sc = GetTextEncodingBase (encoding);
7069 text_encoding_info = assq_no_quit (make_number (sc),
7070 text_encoding_info_alist);
7071 if (NILP (text_encoding_info))
7072 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7073 text_encoding_info_alist);
7074 decode_mac_font_name (name, sizeof (name),
7075 XCAR (XCDR (text_encoding_info)));
7076 family = build_string (name);
7077 if (!NILP (Fassoc (family, fm_font_family_alist)))
7078 continue;
7079 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7080 fm_font_family_alist);
7082 /* Point the instance iterator at the current font family. */
7083 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7084 continue;
7086 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7087 == noErr)
7089 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7091 if (size > 0 || style == normal)
7092 for (; !NILP (rest); rest = XCDR (rest))
7093 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7097 UNGCPRO;
7099 /* Dispose of the iterators. */
7100 FMDisposeFontFamilyIterator (&ffi);
7101 FMDisposeFontFamilyInstanceIterator (&ffii);
7102 #else /* !TARGET_API_MAC_CARBON */
7103 GrafPtr port;
7104 SInt16 fontnum, old_fontnum;
7105 int num_mac_fonts = CountResources('FOND');
7106 int i, j;
7107 Handle font_handle, font_handle_2;
7108 short id, scriptcode;
7109 ResType type;
7110 Str255 name;
7111 struct FontAssoc *fat;
7112 struct AsscEntry *assc_entry;
7113 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7114 struct gcpro gcpro1;
7116 GetPort (&port); /* save the current font number used */
7117 old_fontnum = port->txFont;
7119 text_encoding_info_alist = create_text_encoding_info_alist ();
7121 GCPRO1 (text_encoding_info_alist);
7123 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7125 font_handle = GetIndResource ('FOND', i);
7126 if (!font_handle)
7127 continue;
7129 GetResInfo (font_handle, &id, &type, name);
7130 GetFNum (name, &fontnum);
7131 p2cstr (name);
7132 if (fontnum == 0 || *name == '.')
7133 continue;
7135 TextFont (fontnum);
7136 scriptcode = FontToScript (fontnum);
7137 text_encoding_info = assq_no_quit (make_number (scriptcode),
7138 text_encoding_info_alist);
7139 if (NILP (text_encoding_info))
7140 text_encoding_info = assq_no_quit (make_number (smRoman),
7141 text_encoding_info_alist);
7142 decode_mac_font_name (name, sizeof (name),
7143 XCAR (XCDR (text_encoding_info)));
7144 family = build_string (name);
7145 if (!NILP (Fassoc (family, fm_font_family_alist)))
7146 continue;
7147 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7148 fm_font_family_alist);
7151 HLock (font_handle);
7153 if (GetResourceSizeOnDisk (font_handle)
7154 >= sizeof (struct FamRec))
7156 fat = (struct FontAssoc *) (*font_handle
7157 + sizeof (struct FamRec));
7158 assc_entry
7159 = (struct AsscEntry *) (*font_handle
7160 + sizeof (struct FamRec)
7161 + sizeof (struct FontAssoc));
7163 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7165 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7167 for (; !NILP (rest); rest = XCDR (rest))
7168 add_mac_font_name (name, assc_entry->fontSize,
7169 assc_entry->fontStyle,
7170 SDATA (XCAR (rest)));
7174 HUnlock (font_handle);
7175 font_handle_2 = GetNextFOND (font_handle);
7176 ReleaseResource (font_handle);
7177 font_handle = font_handle_2;
7179 while (ResError () == noErr && font_handle);
7182 UNGCPRO;
7184 TextFont (old_fontnum);
7185 #endif /* !TARGET_API_MAC_CARBON */
7189 void
7190 mac_clear_font_name_table ()
7192 int i;
7194 for (i = 0; i < font_name_count; i++)
7195 xfree (font_name_table[i]);
7196 xfree (font_name_table);
7197 font_name_table = NULL;
7198 font_name_table_size = font_name_count = 0;
7199 fm_font_family_alist = Qnil;
7203 enum xlfd_scalable_field_index
7205 XLFD_SCL_PIXEL_SIZE,
7206 XLFD_SCL_POINT_SIZE,
7207 XLFD_SCL_AVGWIDTH,
7208 XLFD_SCL_LAST
7211 static const int xlfd_scalable_fields[] =
7213 6, /* PIXEL_SIZE */
7214 7, /* POINT_SIZE */
7215 11, /* AVGWIDTH */
7219 static Lisp_Object
7220 mac_do_list_fonts (pattern, maxnames)
7221 const char *pattern;
7222 int maxnames;
7224 int i, n_fonts = 0;
7225 Lisp_Object font_list = Qnil;
7226 struct xlfdpat *pat;
7227 char *scaled;
7228 const char *ptr;
7229 int scl_val[XLFD_SCL_LAST], *val;
7230 const int *field;
7231 int exact;
7233 if (font_name_table == NULL) /* Initialize when first used. */
7234 init_font_name_table ();
7236 for (i = 0; i < XLFD_SCL_LAST; i++)
7237 scl_val[i] = -1;
7239 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7240 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7241 fonts are scaled according to the specified size. */
7242 ptr = pattern;
7243 i = 0;
7244 field = xlfd_scalable_fields;
7245 val = scl_val;
7246 if (*ptr == '-')
7249 ptr++;
7250 if (i == *field)
7252 if ('0' <= *ptr && *ptr <= '9')
7254 *val = *ptr++ - '0';
7255 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7256 *val = *val * 10 + *ptr++ - '0';
7257 if (*ptr != '-')
7258 *val = -1;
7260 field++;
7261 val++;
7263 ptr = strchr (ptr, '-');
7264 i++;
7266 while (ptr && i < 14);
7268 if (i == 14 && ptr == NULL)
7270 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7271 scl_val[XLFD_SCL_PIXEL_SIZE] =
7272 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7273 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7274 : -1));
7275 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7276 scl_val[XLFD_SCL_POINT_SIZE] =
7277 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7278 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7279 : -1));
7280 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7281 scl_val[XLFD_SCL_AVGWIDTH] =
7282 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7283 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7284 : -1));
7286 else
7287 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7289 pat = xlfdpat_create (pattern);
7290 if (pat == NULL)
7291 return Qnil;
7293 exact = xlfdpat_exact_p (pat);
7295 for (i = 0; i < font_name_count; i++)
7297 if (xlfdpat_match (pat, font_name_table[i]))
7299 font_list = Fcons (build_string (font_name_table[i]), font_list);
7300 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7301 break;
7303 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7304 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7306 int former_len = ptr - font_name_table[i];
7308 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7309 memcpy (scaled, font_name_table[i], former_len);
7310 sprintf (scaled + former_len,
7311 "-%d-%d-72-72-m-%d-%s",
7312 scl_val[XLFD_SCL_PIXEL_SIZE],
7313 scl_val[XLFD_SCL_POINT_SIZE],
7314 scl_val[XLFD_SCL_AVGWIDTH],
7315 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7317 if (xlfdpat_match (pat, scaled))
7319 font_list = Fcons (build_string (scaled), font_list);
7320 xfree (scaled);
7321 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7322 break;
7324 else
7325 xfree (scaled);
7329 xlfdpat_destroy (pat);
7331 return font_list;
7334 /* Return a list of names of available fonts matching PATTERN on frame F.
7336 Frame F null means we have not yet created any frame on Mac, and
7337 consult the first display in x_display_list. MAXNAMES sets a limit
7338 on how many fonts to match. */
7340 Lisp_Object
7341 x_list_fonts (f, pattern, size, maxnames)
7342 struct frame *f;
7343 Lisp_Object pattern;
7344 int size, maxnames;
7346 Lisp_Object list = Qnil, patterns, tem, key;
7347 struct mac_display_info *dpyinfo
7348 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7350 xassert (size <= 0);
7352 patterns = Fassoc (pattern, Valternate_fontname_alist);
7353 if (NILP (patterns))
7354 patterns = Fcons (pattern, Qnil);
7356 for (; CONSP (patterns); patterns = XCDR (patterns))
7358 pattern = XCAR (patterns);
7360 if (!STRINGP (pattern))
7361 continue;
7363 tem = XCAR (XCDR (dpyinfo->name_list_element));
7364 key = Fcons (pattern, make_number (maxnames));
7366 list = Fassoc (key, tem);
7367 if (!NILP (list))
7369 list = Fcdr_safe (list);
7370 /* We have a cashed list. Don't have to get the list again. */
7371 goto label_cached;
7374 BLOCK_INPUT;
7375 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7376 UNBLOCK_INPUT;
7378 /* MAC_TODO: add code for matching outline fonts here */
7380 /* Now store the result in the cache. */
7381 XSETCAR (XCDR (dpyinfo->name_list_element),
7382 Fcons (Fcons (key, list),
7383 XCAR (XCDR (dpyinfo->name_list_element))));
7385 label_cached:
7386 if (NILP (list)) continue; /* Try the remaining alternatives. */
7389 return list;
7393 #if GLYPH_DEBUG
7395 /* Check that FONT is valid on frame F. It is if it can be found in F's
7396 font table. */
7398 static void
7399 x_check_font (f, font)
7400 struct frame *f;
7401 XFontStruct *font;
7403 int i;
7404 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7406 xassert (font != NULL);
7408 for (i = 0; i < dpyinfo->n_fonts; i++)
7409 if (dpyinfo->font_table[i].name
7410 && font == dpyinfo->font_table[i].font)
7411 break;
7413 xassert (i < dpyinfo->n_fonts);
7416 #endif /* GLYPH_DEBUG != 0 */
7418 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7419 Note: There are (broken) X fonts out there with invalid XFontStruct
7420 min_bounds contents. For example, handa@etl.go.jp reports that
7421 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7422 have font->min_bounds.width == 0. */
7424 static INLINE void
7425 x_font_min_bounds (font, w, h)
7426 MacFontStruct *font;
7427 int *w, *h;
7429 *h = FONT_HEIGHT (font);
7430 *w = font->min_bounds.width;
7434 /* Compute the smallest character width and smallest font height over
7435 all fonts available on frame F. Set the members smallest_char_width
7436 and smallest_font_height in F's x_display_info structure to
7437 the values computed. Value is non-zero if smallest_font_height or
7438 smallest_char_width become smaller than they were before. */
7440 static int
7441 x_compute_min_glyph_bounds (f)
7442 struct frame *f;
7444 int i;
7445 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7446 MacFontStruct *font;
7447 int old_width = dpyinfo->smallest_char_width;
7448 int old_height = dpyinfo->smallest_font_height;
7450 dpyinfo->smallest_font_height = 100000;
7451 dpyinfo->smallest_char_width = 100000;
7453 for (i = 0; i < dpyinfo->n_fonts; ++i)
7454 if (dpyinfo->font_table[i].name)
7456 struct font_info *fontp = dpyinfo->font_table + i;
7457 int w, h;
7459 font = (MacFontStruct *) fontp->font;
7460 xassert (font != (MacFontStruct *) ~0);
7461 x_font_min_bounds (font, &w, &h);
7463 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7464 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7467 xassert (dpyinfo->smallest_char_width > 0
7468 && dpyinfo->smallest_font_height > 0);
7470 return (dpyinfo->n_fonts == 1
7471 || dpyinfo->smallest_char_width < old_width
7472 || dpyinfo->smallest_font_height < old_height);
7476 /* Determine whether given string is a fully-specified XLFD: all 14
7477 fields are present, none is '*'. */
7479 static int
7480 is_fully_specified_xlfd (p)
7481 const char *p;
7483 int i;
7484 char *q;
7486 if (*p != '-')
7487 return 0;
7489 for (i = 0; i < 13; i++)
7491 q = strchr (p + 1, '-');
7492 if (q == NULL)
7493 return 0;
7494 if (q - p == 2 && *(p + 1) == '*')
7495 return 0;
7496 p = q;
7499 if (strchr (p + 1, '-') != NULL)
7500 return 0;
7502 if (*(p + 1) == '*' && *(p + 2) == '\0')
7503 return 0;
7505 return 1;
7509 /* mac_load_query_font creates and returns an internal representation
7510 for a font in a MacFontStruct struct. There is really no concept
7511 corresponding to "loading" a font on the Mac. But we check its
7512 existence and find the font number and all other information for it
7513 and store them in the returned MacFontStruct. */
7515 static MacFontStruct *
7516 mac_load_query_font (f, fontname)
7517 struct frame *f;
7518 char *fontname;
7520 int size;
7521 char *name;
7522 Str255 family;
7523 Str31 charset;
7524 SInt16 fontnum;
7525 #if USE_ATSUI
7526 static ATSUFontID font_id;
7527 ATSUStyle mac_style = NULL;
7528 #endif
7529 Style fontface;
7530 #if TARGET_API_MAC_CARBON
7531 TextEncoding encoding;
7532 int scriptcode;
7533 #else
7534 short scriptcode;
7535 #endif
7536 MacFontStruct *font;
7537 XCharStruct *space_bounds = NULL, *pcm;
7539 if (is_fully_specified_xlfd (fontname))
7540 name = fontname;
7541 else
7543 Lisp_Object matched_fonts;
7545 matched_fonts = mac_do_list_fonts (fontname, 1);
7546 if (NILP (matched_fonts))
7547 return NULL;
7548 name = SDATA (XCAR (matched_fonts));
7551 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7552 return NULL;
7554 #if USE_ATSUI
7555 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7557 OSStatus err;
7558 static const ATSUAttributeTag tags[] =
7559 {kATSUFontTag, kATSUSizeTag,
7560 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7561 static const ByteCount sizes[] =
7562 {sizeof (ATSUFontID), sizeof (Fixed),
7563 sizeof (Boolean), sizeof (Boolean)};
7564 static Fixed size_fixed;
7565 static Boolean bold_p, italic_p;
7566 static const ATSUAttributeValuePtr values[] =
7567 {&font_id, &size_fixed,
7568 &bold_p, &italic_p};
7569 static const ATSUFontFeatureType types[] =
7570 {kAllTypographicFeaturesType, kDiacriticsType};
7571 static const ATSUFontFeatureSelector selectors[] =
7572 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector};
7573 FMFontStyle style;
7575 font_id = atsu_find_font_from_family_name (family);
7576 if (font_id == kATSUInvalidFontID)
7577 return NULL;
7578 size_fixed = Long2Fix (size);
7579 bold_p = (fontface & bold) != 0;
7580 italic_p = (fontface & italic) != 0;
7581 err = ATSUCreateStyle (&mac_style);
7582 if (err != noErr)
7583 return NULL;
7584 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7585 types, selectors);
7586 if (err != noErr)
7587 return NULL;
7588 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7589 tags, sizes, values);
7590 if (err != noErr)
7591 return NULL;
7592 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
7593 if (err != noErr)
7594 fontnum = -1;
7595 scriptcode = kTextEncodingMacUnicode;
7597 else
7598 #endif
7600 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7602 if (NILP (tmp))
7603 return NULL;
7604 fontnum = XINT (XCDR (tmp));
7605 #if TARGET_API_MAC_CARBON
7606 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7607 return NULL;
7608 scriptcode = GetTextEncodingBase (encoding);
7609 #else
7610 scriptcode = FontToScript (fontnum);
7611 #endif
7614 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7616 font->mac_fontnum = fontnum;
7617 font->mac_fontsize = size;
7618 font->mac_fontface = fontface;
7619 font->mac_scriptcode = scriptcode;
7620 #if USE_ATSUI
7621 font->mac_style = mac_style;
7622 #if USE_CG_TEXT_DRAWING
7623 font->cg_font = NULL;
7624 font->cg_glyphs = NULL;
7625 #endif
7626 #endif
7628 /* Apple Japanese (SJIS) font is listed as both
7629 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7630 (Roman script) in init_font_name_table (). The latter should be
7631 treated as a one-byte font. */
7632 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7633 font->mac_scriptcode = smRoman;
7635 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
7637 #if USE_ATSUI
7638 if (font->mac_style)
7640 OSStatus err;
7641 UniChar c;
7643 font->min_byte1 = 0;
7644 font->max_byte1 = 0xff;
7645 font->min_char_or_byte2 = 0;
7646 font->max_char_or_byte2 = 0xff;
7648 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
7649 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
7650 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
7651 pcm_init (font->bounds.rows[0], 0x100);
7653 #if USE_CG_TEXT_DRAWING
7654 if (fontnum != -1)
7656 FMFontStyle style;
7657 ATSFontRef ats_font;
7659 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
7660 &font_id, &style);
7661 /* Use CG text drawing if italic/bold is not synthesized. */
7662 if (err == noErr && style == fontface)
7664 ats_font = FMGetATSFontRefFromFont (font_id);
7665 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7669 if (font->cg_font)
7671 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7672 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7674 #endif
7675 space_bounds = font->bounds.rows[0] + 0x20;
7676 err = mac_query_char_extents (font->mac_style, 0x20,
7677 &font->ascent, &font->descent,
7678 space_bounds,
7679 #if USE_CG_TEXT_DRAWING
7680 (font->cg_glyphs ? font->cg_glyphs + 0x20
7681 : NULL)
7682 #else
7683 NULL
7684 #endif
7686 if (err != noErr
7687 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0)
7689 mac_unload_font (&one_mac_display_info, font);
7690 return NULL;
7693 pcm = font->bounds.rows[0];
7694 for (c = 0x21; c <= 0xff; c++)
7696 if (c == 0xad)
7697 /* Soft hyphen is not supported in ATSUI. */
7698 continue;
7699 else if (c == 0x7f)
7701 #if USE_CG_TEXT_DRAWING
7702 if (font->cg_glyphs)
7704 c = 0x9f;
7705 pcm = NULL;
7706 continue;
7708 #endif
7709 break;
7712 mac_query_char_extents (font->mac_style, c, NULL, NULL,
7713 pcm ? pcm + c : NULL,
7714 #if USE_CG_TEXT_DRAWING
7715 (font->cg_glyphs ? font->cg_glyphs + c
7716 : NULL)
7717 #else
7718 NULL
7719 #endif
7722 #if USE_CG_TEXT_DRAWING
7723 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
7725 /* Don't use CG text drawing if font substitution occurs in
7726 ASCII or Latin-1 characters. */
7727 CGFontRelease (font->cg_font);
7728 font->cg_font = NULL;
7729 xfree (font->cg_glyphs);
7730 font->cg_glyphs = NULL;
7731 if (pcm == NULL)
7732 break;
7734 #endif
7737 else
7738 #endif
7740 OSStatus err;
7741 FontInfo the_fontinfo;
7742 int is_two_byte_font;
7744 mac_begin_clip (f, NULL);
7746 TextFont (fontnum);
7747 TextSize (size);
7748 TextFace (fontface);
7750 GetFontInfo (&the_fontinfo);
7752 font->ascent = the_fontinfo.ascent;
7753 font->descent = the_fontinfo.descent;
7755 is_two_byte_font = (font->mac_scriptcode == smJapanese
7756 || font->mac_scriptcode == smTradChinese
7757 || font->mac_scriptcode == smSimpChinese
7758 || font->mac_scriptcode == smKorean);
7760 if (is_two_byte_font)
7762 int char_width;
7764 font->min_byte1 = 0xa1;
7765 font->max_byte1 = 0xfe;
7766 font->min_char_or_byte2 = 0xa1;
7767 font->max_char_or_byte2 = 0xfe;
7769 /* Use the width of an "ideographic space" of that font
7770 because the_fontinfo.widMax returns the wrong width for
7771 some fonts. */
7772 switch (font->mac_scriptcode)
7774 case smJapanese:
7775 font->min_byte1 = 0x81;
7776 font->max_byte1 = 0xfc;
7777 font->min_char_or_byte2 = 0x40;
7778 font->max_char_or_byte2 = 0xfc;
7779 char_width = StringWidth("\p\x81\x40");
7780 break;
7781 case smTradChinese:
7782 font->min_char_or_byte2 = 0x40;
7783 char_width = StringWidth("\p\xa1\x40");
7784 break;
7785 case smSimpChinese:
7786 char_width = StringWidth("\p\xa1\xa1");
7787 break;
7788 case smKorean:
7789 char_width = StringWidth("\p\xa1\xa1");
7790 break;
7793 font->bounds.per_char = NULL;
7795 if (fontface & italic)
7796 font->max_bounds.rbearing = char_width + 1;
7797 else
7798 font->max_bounds.rbearing = char_width;
7799 font->max_bounds.lbearing = 0;
7800 font->max_bounds.width = char_width;
7801 font->max_bounds.ascent = the_fontinfo.ascent;
7802 font->max_bounds.descent = the_fontinfo.descent;
7804 font->min_bounds = font->max_bounds;
7806 else
7808 int c;
7810 font->min_byte1 = font->max_byte1 = 0;
7811 font->min_char_or_byte2 = 0x20;
7812 font->max_char_or_byte2 = 0xff;
7814 font->bounds.per_char =
7815 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7816 bzero (font->bounds.per_char,
7817 sizeof (XCharStruct) * (0xff - 0x20 + 1));
7819 space_bounds = font->bounds.per_char;
7820 err = mac_query_char_extents (NULL, 0x20, &font->ascent,
7821 &font->descent, space_bounds, NULL);
7822 if (err != noErr || space_bounds->width <= 0)
7824 mac_unload_font (&one_mac_display_info, font);
7825 return NULL;
7828 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
7829 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
7832 mac_end_clip (f, NULL);
7835 if (space_bounds)
7837 int c;
7839 font->min_bounds = font->max_bounds = *space_bounds;
7840 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
7841 if (pcm->width > 0)
7843 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
7844 pcm->lbearing);
7845 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
7846 pcm->rbearing);
7847 font->min_bounds.width = min (font->min_bounds.width,
7848 pcm->width);
7849 font->min_bounds.ascent = min (font->min_bounds.ascent,
7850 pcm->ascent);
7851 font->min_bounds.descent = min (font->min_bounds.descent,
7852 pcm->descent);
7854 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
7855 pcm->lbearing);
7856 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
7857 pcm->rbearing);
7858 font->max_bounds.width = max (font->max_bounds.width,
7859 pcm->width);
7860 font->max_bounds.ascent = max (font->max_bounds.ascent,
7861 pcm->ascent);
7862 font->max_bounds.descent = max (font->max_bounds.descent,
7863 pcm->descent);
7865 if (
7866 #if USE_ATSUI
7867 font->mac_style == NULL &&
7868 #endif
7869 font->max_bounds.width == font->min_bounds.width
7870 && font->min_bounds.lbearing >= 0
7871 && font->max_bounds.rbearing <= font->max_bounds.width)
7873 /* Fixed width and no overhangs. */
7874 xfree (font->bounds.per_char);
7875 font->bounds.per_char = NULL;
7879 #if !defined (MAC_OS8) || USE_ATSUI
7880 /* AppKit and WebKit do some adjustment to the heights of Courier,
7881 Helvetica, and Times. This only works on the environments where
7882 srcCopy text transfer mode is never used. */
7883 if (
7884 #ifdef MAC_OS8 /* implies USE_ATSUI */
7885 font->mac_style &&
7886 #endif
7887 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
7888 || strcmp (family, "times") == 0))
7889 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
7890 #endif
7892 return font;
7896 void
7897 mac_unload_font (dpyinfo, font)
7898 struct mac_display_info *dpyinfo;
7899 XFontStruct *font;
7901 xfree (font->full_name);
7902 #if USE_ATSUI
7903 if (font->mac_style)
7905 int i;
7907 for (i = font->min_byte1; i <= font->max_byte1; i++)
7908 if (font->bounds.rows[i])
7909 xfree (font->bounds.rows[i]);
7910 xfree (font->bounds.rows);
7911 ATSUDisposeStyle (font->mac_style);
7913 else
7914 #endif
7915 if (font->bounds.per_char)
7916 xfree (font->bounds.per_char);
7917 #if USE_CG_TEXT_DRAWING
7918 if (font->cg_font)
7919 CGFontRelease (font->cg_font);
7920 if (font->cg_glyphs)
7921 xfree (font->cg_glyphs);
7922 #endif
7923 xfree (font);
7927 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7928 pointer to the structure font_info while allocating it dynamically.
7929 If SIZE is 0, load any size of font.
7930 If loading is failed, return NULL. */
7932 struct font_info *
7933 x_load_font (f, fontname, size)
7934 struct frame *f;
7935 register char *fontname;
7936 int size;
7938 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7939 Lisp_Object font_names;
7941 /* Get a list of all the fonts that match this name. Once we
7942 have a list of matching fonts, we compare them against the fonts
7943 we already have by comparing names. */
7944 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7946 if (!NILP (font_names))
7948 Lisp_Object tail;
7949 int i;
7951 for (i = 0; i < dpyinfo->n_fonts; i++)
7952 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7953 if (dpyinfo->font_table[i].name
7954 && (!strcmp (dpyinfo->font_table[i].name,
7955 SDATA (XCAR (tail)))
7956 || !strcmp (dpyinfo->font_table[i].full_name,
7957 SDATA (XCAR (tail)))))
7958 return (dpyinfo->font_table + i);
7960 else
7961 return NULL;
7963 /* Load the font and add it to the table. */
7965 struct MacFontStruct *font;
7966 struct font_info *fontp;
7967 int i;
7969 fontname = (char *) SDATA (XCAR (font_names));
7971 BLOCK_INPUT;
7972 font = mac_load_query_font (f, fontname);
7973 UNBLOCK_INPUT;
7974 if (!font)
7975 return NULL;
7977 /* Find a free slot in the font table. */
7978 for (i = 0; i < dpyinfo->n_fonts; ++i)
7979 if (dpyinfo->font_table[i].name == NULL)
7980 break;
7982 /* If no free slot found, maybe enlarge the font table. */
7983 if (i == dpyinfo->n_fonts
7984 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7986 int sz;
7987 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7988 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
7989 dpyinfo->font_table
7990 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
7993 fontp = dpyinfo->font_table + i;
7994 if (i == dpyinfo->n_fonts)
7995 ++dpyinfo->n_fonts;
7997 /* Now fill in the slots of *FONTP. */
7998 BLOCK_INPUT;
7999 bzero (fontp, sizeof (*fontp));
8000 fontp->font = font;
8001 fontp->font_idx = i;
8002 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8003 bcopy (fontname, fontp->name, strlen (fontname) + 1);
8005 if (font->min_bounds.width == font->max_bounds.width)
8007 /* Fixed width font. */
8008 fontp->average_width = fontp->space_width = font->min_bounds.width;
8010 else
8012 XChar2b char2b;
8013 XCharStruct *pcm;
8015 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8016 pcm = mac_per_char_metric (font, &char2b, 0);
8017 if (pcm)
8018 fontp->space_width = pcm->width;
8019 else
8020 fontp->space_width = FONT_WIDTH (font);
8022 if (pcm)
8024 int width = pcm->width;
8025 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8026 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8027 width += pcm->width;
8028 fontp->average_width = width / 95.0 + 0.5;
8030 else
8031 fontp->average_width = FONT_WIDTH (font);
8034 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8035 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
8037 fontp->size = font->max_bounds.width;
8038 fontp->height = FONT_HEIGHT (font);
8040 /* For some font, ascent and descent in max_bounds field is
8041 larger than the above value. */
8042 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8043 if (max_height > fontp->height)
8044 fontp->height = max_height;
8047 /* The slot `encoding' specifies how to map a character
8048 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8049 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8050 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8051 2:0xA020..0xFF7F). For the moment, we don't know which charset
8052 uses this font. So, we set information in fontp->encoding[1]
8053 which is never used by any charset. If mapping can't be
8054 decided, set FONT_ENCODING_NOT_DECIDED. */
8055 if (font->mac_scriptcode == smJapanese)
8056 fontp->encoding[1] = 4;
8057 else
8059 fontp->encoding[1]
8060 = (font->max_byte1 == 0
8061 /* 1-byte font */
8062 ? (font->min_char_or_byte2 < 0x80
8063 ? (font->max_char_or_byte2 < 0x80
8064 ? 0 /* 0x20..0x7F */
8065 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8066 : 1) /* 0xA0..0xFF */
8067 /* 2-byte font */
8068 : (font->min_byte1 < 0x80
8069 ? (font->max_byte1 < 0x80
8070 ? (font->min_char_or_byte2 < 0x80
8071 ? (font->max_char_or_byte2 < 0x80
8072 ? 0 /* 0x2020..0x7F7F */
8073 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8074 : 3) /* 0x20A0..0x7FFF */
8075 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8076 : (font->min_char_or_byte2 < 0x80
8077 ? (font->max_char_or_byte2 < 0x80
8078 ? 2 /* 0xA020..0xFF7F */
8079 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8080 : 1))); /* 0xA0A0..0xFFFF */
8083 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8084 fontp->baseline_offset
8085 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8086 ? (long) value : 0);
8087 fontp->relative_compose
8088 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8089 ? (long) value : 0);
8090 fontp->default_ascent
8091 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8092 ? (long) value : 0);
8093 #else
8094 fontp->baseline_offset = 0;
8095 fontp->relative_compose = 0;
8096 fontp->default_ascent = 0;
8097 #endif
8099 /* Set global flag fonts_changed_p to non-zero if the font loaded
8100 has a character with a smaller width than any other character
8101 before, or if the font loaded has a smaller height than any
8102 other font loaded before. If this happens, it will make a
8103 glyph matrix reallocation necessary. */
8104 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8105 UNBLOCK_INPUT;
8106 return fontp;
8111 /* Return a pointer to struct font_info of a font named FONTNAME for
8112 frame F. If no such font is loaded, return NULL. */
8114 struct font_info *
8115 x_query_font (f, fontname)
8116 struct frame *f;
8117 register char *fontname;
8119 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8120 int i;
8122 for (i = 0; i < dpyinfo->n_fonts; i++)
8123 if (dpyinfo->font_table[i].name
8124 && (!xstricmp (dpyinfo->font_table[i].name, fontname)
8125 || !xstricmp (dpyinfo->font_table[i].full_name, fontname)))
8126 return (dpyinfo->font_table + i);
8127 return NULL;
8131 /* Find a CCL program for a font specified by FONTP, and set the member
8132 `encoder' of the structure. */
8134 void
8135 x_find_ccl_program (fontp)
8136 struct font_info *fontp;
8138 Lisp_Object list, elt;
8140 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8142 elt = XCAR (list);
8143 if (CONSP (elt)
8144 && STRINGP (XCAR (elt))
8145 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8146 >= 0))
8147 break;
8149 if (! NILP (list))
8151 struct ccl_program *ccl
8152 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8154 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8155 xfree (ccl);
8156 else
8157 fontp->font_encoder = ccl;
8162 /* The Mac Event loop code */
8164 #if !TARGET_API_MAC_CARBON
8165 #include <Events.h>
8166 #include <Quickdraw.h>
8167 #include <Balloons.h>
8168 #include <Devices.h>
8169 #include <Fonts.h>
8170 #include <Gestalt.h>
8171 #include <Menus.h>
8172 #include <Processes.h>
8173 #include <Sound.h>
8174 #include <ToolUtils.h>
8175 #include <TextUtils.h>
8176 #include <Dialogs.h>
8177 #include <Script.h>
8178 #include <Types.h>
8179 #include <Resources.h>
8181 #if __MWERKS__
8182 #include <unix.h>
8183 #endif
8184 #endif /* ! TARGET_API_MAC_CARBON */
8186 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8187 Lisp_Object Qreverse;
8190 /* Modifier associated with the control key, or nil to ignore. */
8191 Lisp_Object Vmac_control_modifier;
8193 /* Modifier associated with the option key, or nil to ignore. */
8194 Lisp_Object Vmac_option_modifier;
8196 /* Modifier associated with the command key, or nil to ignore. */
8197 Lisp_Object Vmac_command_modifier;
8199 /* Modifier associated with the function key, or nil to ignore. */
8200 Lisp_Object Vmac_function_modifier;
8202 /* True if the option and command modifiers should be used to emulate
8203 a three button mouse */
8204 Lisp_Object Vmac_emulate_three_button_mouse;
8206 #if TARGET_API_MAC_CARBON
8207 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8208 mouse-2, instead of mouse-3. */
8209 int mac_wheel_button_is_mouse_2;
8211 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8212 for processing before Emacs sees it. */
8213 int mac_pass_command_to_system;
8215 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8216 for processing before Emacs sees it. */
8217 int mac_pass_control_to_system;
8218 #endif
8220 /* Whether or not the screen configuration has changed. */
8221 int mac_screen_config_changed = 0;
8223 /* Apple Events */
8224 #if TARGET_API_MAC_CARBON
8225 Lisp_Object Qhi_command;
8226 #ifdef MAC_OSX
8227 Lisp_Object Qtoolbar_switch_mode;
8228 #endif
8229 #if USE_MAC_TSM
8230 Lisp_Object Qtext_input;
8231 Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8232 Lisp_Object Vmac_ts_active_input_overlay, Vmac_ts_active_input_buf;
8233 static Lisp_Object Vmac_ts_script_language_on_focus;
8234 static Lisp_Object saved_ts_script_language_on_focus;
8235 static ScriptLanguageRecord saved_ts_language;
8236 static Component saved_ts_component;
8237 #endif
8238 #ifdef MAC_OSX
8239 Lisp_Object Qservice, Qpaste, Qperform;
8240 Lisp_Object Qmouse_drag_overlay;
8241 #endif
8242 #endif /* TARGET_API_MAC_CARBON */
8243 extern Lisp_Object Qundefined;
8244 extern int XTread_socket P_ ((int, int, struct input_event *));
8245 extern void init_apple_event_handler P_ ((void));
8246 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8247 Lisp_Object *, Lisp_Object *,
8248 Lisp_Object *));
8249 extern OSErr init_coercion_handler P_ ((void));
8251 /* Table for translating Mac keycode to X keysym values. Contributed
8252 by Sudhir Shenoy.
8253 Mapping for special keys is now identical to that in Apple X11
8254 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8255 on the right of the Cmd key on laptops, and fn + `enter' (->
8256 <linefeed>). */
8257 const unsigned char keycode_to_xkeysym_table[] = {
8258 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8259 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8260 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8262 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8263 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8264 /*0x38*/ 0, 0, 0, 0,
8265 /*0x3C*/ 0, 0, 0, 0,
8267 /*0x40*/ 0xce /*f17*/, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/,
8268 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/,
8269 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/,
8270 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0xcf /*f18*/,
8272 /*0x50*/ 0xd0 /*f19*/, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8273 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8274 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8275 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8277 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8278 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8279 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
8280 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8282 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8283 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8284 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8285 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8288 #ifdef MAC_OSX
8289 /* Table for translating Mac keycode with the laptop `fn' key to that
8290 without it. Destination symbols in comments are keys on US
8291 keyboard, and they may not be the same on other types of keyboards.
8292 If the destination is identical to the source, it doesn't map `fn'
8293 key to a modifier. */
8294 static const unsigned char fn_keycode_to_keycode_table[] = {
8295 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8296 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8297 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8299 /*0x30*/ 0, 0, 0, 0,
8300 /*0x34*/ 0, 0, 0, 0,
8301 /*0x38*/ 0, 0, 0, 0,
8302 /*0x3C*/ 0, 0, 0, 0,
8304 /*0x40*/ 0x40 /*f17 = f17*/, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/,
8305 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/,
8306 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
8307 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0x4f /*f18 = f18*/,
8309 /*0x50*/ 0x50 /*f19 = f19*/, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
8310 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
8311 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
8312 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
8314 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
8315 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
8316 /*0x68*/ 0, 0x69 /*f13 = f13*/, 0x6a /*f16 = f16*/, 0x6b /*f14 = f14*/,
8317 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
8319 /*0x70*/ 0, 0x71 /*f15 = f15*/, 0x72 /*help = help*/, 0x7b /*home -> left*/,
8320 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
8321 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0x7b /*left = left*/,
8322 /*0x7C*/ 0x7c /*right = right*/, 0x7d /*down = down*/, 0x7e /*up = up*/, 0
8324 #endif /* MAC_OSX */
8327 #if TARGET_API_MAC_CARBON
8328 mac_to_emacs_modifiers (UInt32 mods, UInt32 unmapped_mods)
8329 #else
8330 mac_to_emacs_modifiers (EventModifiers mods, EventModifiers unmapped_mods)
8331 #endif
8333 unsigned int result = 0;
8334 if ((mods | unmapped_mods) & shiftKey)
8335 result |= shift_modifier;
8337 /* Deactivated to simplify configuration:
8338 if Vmac_option_modifier is non-NIL, we fully process the Option
8339 key. Otherwise, we only process it if an additional Ctrl or Command
8340 is pressed. That way the system may convert the character to a
8341 composed one.
8342 if ((mods & optionKey) &&
8343 (( !NILP(Vmac_option_modifier) ||
8344 ((mods & cmdKey) || (mods & controlKey))))) */
8346 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
8347 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8348 if (INTEGERP(val))
8349 result |= XUINT(val);
8351 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8352 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8353 if (INTEGERP(val))
8354 result |= XUINT(val);
8356 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8357 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8358 if (INTEGERP(val))
8359 result |= XUINT(val);
8362 #ifdef MAC_OSX
8363 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8364 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8365 if (INTEGERP(val))
8366 result |= XUINT(val);
8368 #endif
8370 return result;
8373 UInt32
8374 mac_mapped_modifiers (modifiers, key_code)
8375 UInt32 modifiers, key_code;
8377 UInt32 mapped_modifiers_all =
8378 (NILP (Vmac_control_modifier) ? 0 : controlKey)
8379 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
8380 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
8382 #ifdef MAC_OSX
8383 mapped_modifiers_all |=
8384 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
8386 /* The meaning of kEventKeyModifierFnMask has changed in Mac OS X
8387 10.5, and it now behaves much like Cocoa's NSFunctionKeyMask. It
8388 no longer means laptop's `fn' key is down for the following keys:
8389 F1, F2, and so on, Help, Forward Delete, Home, End, Page Up, Page
8390 Down, the arrow keys, and Clear. We ignore the corresponding bit
8391 if that key can be entered without the `fn' key on laptops. */
8392 if (modifiers & kEventKeyModifierFnMask
8393 && key_code <= 0x7f
8394 && fn_keycode_to_keycode_table[key_code] == key_code)
8395 modifiers &= ~kEventKeyModifierFnMask;
8396 #endif
8398 return mapped_modifiers_all & modifiers;
8402 mac_get_emulated_btn ( UInt32 modifiers )
8404 int result = 0;
8405 if (!NILP (Vmac_emulate_three_button_mouse)) {
8406 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
8407 if (modifiers & cmdKey)
8408 result = cmdIs3 ? 2 : 1;
8409 else if (modifiers & optionKey)
8410 result = cmdIs3 ? 1 : 2;
8412 return result;
8415 #ifdef MAC_OSX
8416 void
8417 mac_get_selected_range (w, range)
8418 struct window *w;
8419 CFRange *range;
8421 Lisp_Object overlay = find_symbol_value (Qmouse_drag_overlay);
8422 struct buffer *b = XBUFFER (w->buffer);
8423 int begv = BUF_BEGV (b), zv = BUF_ZV (b);
8424 int start, end;
8426 if (OVERLAYP (overlay)
8427 && EQ (Foverlay_buffer (overlay), w->buffer)
8428 && (start = XINT (Foverlay_start (overlay)),
8429 end = XINT (Foverlay_end (overlay)),
8430 start != end))
8432 else
8434 if (w == XWINDOW (selected_window) && b == current_buffer)
8435 start = PT;
8436 else
8437 start = marker_position (w->pointm);
8439 if (NILP (Vtransient_mark_mode) || NILP (b->mark_active))
8440 end = start;
8441 else
8443 int mark_pos = marker_position (b->mark);
8445 if (start <= mark_pos)
8446 end = mark_pos;
8447 else
8449 end = start;
8450 start = mark_pos;
8455 if (start != end)
8457 if (start < begv)
8458 start = begv;
8459 else if (start > zv)
8460 start = zv;
8462 if (end < begv)
8463 end = begv;
8464 else if (end > zv)
8465 end = zv;
8468 range->location = start - begv;
8469 range->length = end - start;
8472 /* Store the text of the buffer BUF from START to END as Unicode
8473 characters in CHARACTERS. Return non-zero if successful. */
8476 mac_store_buffer_text_to_unicode_chars (buf, start, end, characters)
8477 struct buffer *buf;
8478 int start, end;
8479 UniChar *characters;
8481 int start_byte, end_byte, char_count, byte_count;
8482 struct coding_system coding;
8483 unsigned char *dst = (unsigned char *) characters;
8485 start_byte = buf_charpos_to_bytepos (buf, start);
8486 end_byte = buf_charpos_to_bytepos (buf, end);
8487 char_count = end - start;
8488 byte_count = end_byte - start_byte;
8490 if (setup_coding_system (
8491 #ifdef WORDS_BIG_ENDIAN
8492 intern ("utf-16be")
8493 #else
8494 intern ("utf-16le")
8495 #endif
8496 , &coding) < 0)
8497 return 0;
8499 coding.src_multibyte = !NILP (buf->enable_multibyte_characters);
8500 coding.dst_multibyte = 0;
8501 coding.mode |= CODING_MODE_LAST_BLOCK;
8502 coding.composing = COMPOSITION_DISABLED;
8504 if (BUF_GPT_BYTE (buf) <= start_byte || end_byte <= BUF_GPT_BYTE (buf))
8505 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8506 byte_count, char_count * sizeof (UniChar));
8507 else
8509 int first_byte_count = BUF_GPT_BYTE (buf) - start_byte;
8511 encode_coding (&coding, BUF_BYTE_ADDRESS (buf, start_byte), dst,
8512 first_byte_count, char_count * sizeof (UniChar));
8513 if (coding.result == CODING_FINISH_NORMAL)
8514 encode_coding (&coding,
8515 BUF_BYTE_ADDRESS (buf, start_byte + first_byte_count),
8516 dst + coding.produced,
8517 byte_count - first_byte_count,
8518 char_count * sizeof (UniChar) - coding.produced);
8521 if (coding.result != CODING_FINISH_NORMAL)
8522 return 0;
8524 return 1;
8527 void
8528 mac_ax_selected_text_range (f, range)
8529 struct frame *f;
8530 CFRange *range;
8532 mac_get_selected_range (XWINDOW (f->selected_window), range);
8535 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8536 unsigned int
8537 mac_ax_number_of_characters (f)
8538 struct frame *f;
8540 struct buffer *b = XBUFFER (XWINDOW (f->selected_window)->buffer);
8542 return BUF_ZV (b) - BUF_BEGV (b);
8544 #endif
8545 #endif
8547 #if USE_MAC_TSM
8548 OSStatus
8549 mac_restore_keyboard_input_source ()
8551 OSStatus err = noErr;
8552 ScriptLanguageRecord slrec, *slptr = NULL;
8554 if (EQ (Vmac_ts_script_language_on_focus, Qt)
8555 && EQ (saved_ts_script_language_on_focus, Qt))
8556 slptr = &saved_ts_language;
8557 else if (CONSP (Vmac_ts_script_language_on_focus)
8558 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8559 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))
8560 && CONSP (saved_ts_script_language_on_focus)
8561 && EQ (XCAR (saved_ts_script_language_on_focus),
8562 XCAR (Vmac_ts_script_language_on_focus))
8563 && EQ (XCDR (saved_ts_script_language_on_focus),
8564 XCDR (Vmac_ts_script_language_on_focus)))
8566 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8567 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8568 slptr = &slrec;
8571 if (slptr)
8573 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8574 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr,
8575 kKeyboardInputMethodClass);
8576 #else
8577 err = SetDefaultInputMethod (saved_ts_component, slptr);
8578 #endif
8579 if (err == noErr)
8580 err = SetTextServiceLanguage (slptr);
8582 /* Seems to be needed on Mac OS X 10.2. */
8583 if (err == noErr)
8584 KeyScript (slptr->fScript | smKeyForceKeyScriptMask);
8587 return err;
8590 void
8591 mac_save_keyboard_input_source ()
8593 OSStatus err;
8594 ScriptLanguageRecord slrec, *slptr = NULL;
8596 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus;
8598 if (EQ (Vmac_ts_script_language_on_focus, Qt))
8600 err = GetTextServiceLanguage (&saved_ts_language);
8601 if (err == noErr)
8602 slptr = &saved_ts_language;
8604 else if (CONSP (Vmac_ts_script_language_on_focus)
8605 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus))
8606 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)))
8608 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus));
8609 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus));
8610 slptr = &slrec;
8613 if (slptr)
8615 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8616 GetDefaultInputMethodOfClass (&saved_ts_component, slptr,
8617 kKeyboardInputMethodClass);
8618 #else
8619 GetDefaultInputMethod (&saved_ts_component, slptr);
8620 #endif
8623 #endif
8625 #if TARGET_API_MAC_CARBON
8626 /***** Code to handle C-g testing *****/
8627 extern int quit_char;
8628 extern int make_ctrl_char P_ ((int));
8631 mac_quit_char_key_p (modifiers, key_code)
8632 UInt32 modifiers, key_code;
8634 UInt32 char_code, mapped_modifiers;
8635 unsigned long some_state = 0;
8636 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8637 int c, emacs_modifiers;
8639 /* Mask off modifier keys that are mapped to some Emacs modifiers. */
8640 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8641 key_code |= (modifiers & ~mapped_modifiers);
8642 char_code = KeyTranslate (kchr_ptr, key_code, &some_state);
8643 if (char_code & ~0xff)
8644 return 0;
8646 emacs_modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8647 if (emacs_modifiers & ctrl_modifier)
8648 c = make_ctrl_char (char_code);
8650 c |= (emacs_modifiers
8651 & (meta_modifier | alt_modifier
8652 | hyper_modifier | super_modifier));
8654 return c == quit_char;
8656 #endif
8658 static void
8659 mac_set_unicode_keystroke_event (code, buf)
8660 UniChar code;
8661 struct input_event *buf;
8663 int charset_id, c1, c2;
8665 if (code < 0x80)
8667 buf->kind = ASCII_KEYSTROKE_EVENT;
8668 buf->code = code;
8670 else if (code < 0x100)
8672 if (code < 0xA0)
8673 charset_id = CHARSET_8_BIT_CONTROL;
8674 else
8675 charset_id = charset_latin_iso8859_1;
8676 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8677 buf->code = MAKE_CHAR (charset_id, code, 0);
8679 else
8681 if (code < 0x2500)
8682 charset_id = charset_mule_unicode_0100_24ff,
8683 code -= 0x100;
8684 else if (code < 0x33FF)
8685 charset_id = charset_mule_unicode_2500_33ff,
8686 code -= 0x2500;
8687 else if (code >= 0xE000)
8688 charset_id = charset_mule_unicode_e000_ffff,
8689 code -= 0xE000;
8690 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
8691 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
8692 buf->code = MAKE_CHAR (charset_id, c1, c2);
8696 void
8697 do_keystroke (action, char_code, key_code, modifiers, timestamp, buf)
8698 EventKind action;
8699 unsigned char char_code;
8700 UInt32 key_code, modifiers;
8701 unsigned long timestamp;
8702 struct input_event *buf;
8704 static SInt16 last_key_script = -1;
8705 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
8706 UInt32 mapped_modifiers = mac_mapped_modifiers (modifiers, key_code);
8708 #ifdef MAC_OSX
8709 if (mapped_modifiers & kEventKeyModifierFnMask
8710 && key_code <= 0x7f
8711 && fn_keycode_to_keycode_table[key_code])
8712 key_code = fn_keycode_to_keycode_table[key_code];
8713 #endif
8715 if (key_code <= 0x7f && keycode_to_xkeysym_table[key_code])
8717 buf->kind = NON_ASCII_KEYSTROKE_EVENT;
8718 buf->code = 0xff00 | keycode_to_xkeysym_table[key_code];
8720 else if (mapped_modifiers)
8722 /* translate the keycode back to determine the original key */
8723 #ifdef MAC_OSX
8724 UCKeyboardLayout *uchr_ptr = NULL;
8725 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
8726 OSStatus err;
8727 KeyboardLayoutRef layout;
8729 err = KLGetCurrentKeyboardLayout (&layout);
8730 if (err == noErr)
8731 err = KLGetKeyboardLayoutProperty (layout, kKLuchrData,
8732 (const void **) &uchr_ptr);
8733 #else
8734 static SInt16 last_key_layout_id = 0;
8735 static Handle uchr_handle = (Handle)-1;
8736 SInt16 current_key_layout_id =
8737 GetScriptVariable (current_key_script, smScriptKeys);
8739 if (uchr_handle == (Handle)-1
8740 || last_key_layout_id != current_key_layout_id)
8742 uchr_handle = GetResource ('uchr', current_key_layout_id);
8743 last_key_layout_id = current_key_layout_id;
8745 if (uchr_handle)
8746 uchr_ptr = (UCKeyboardLayout *)*uchr_handle;
8747 #endif
8749 if (uchr_ptr)
8751 OSStatus status;
8752 UInt16 key_action = action - keyDown;
8753 UInt32 modifier_key_state = (modifiers & ~mapped_modifiers) >> 8;
8754 UInt32 keyboard_type = LMGetKbdType ();
8755 SInt32 dead_key_state = 0;
8756 UniChar code;
8757 UniCharCount actual_length;
8759 status = UCKeyTranslate (uchr_ptr, key_code, key_action,
8760 modifier_key_state, keyboard_type,
8761 kUCKeyTranslateNoDeadKeysMask,
8762 &dead_key_state,
8763 1, &actual_length, &code);
8764 if (status == noErr && actual_length == 1)
8765 mac_set_unicode_keystroke_event (code, buf);
8767 #endif /* MAC_OSX */
8769 if (buf->kind == NO_EVENT)
8771 /* This code comes from Keyboard Resource, Appendix C of IM
8772 - Text. This is necessary since shift is ignored in KCHR
8773 table translation when option or command is pressed. It
8774 also does not translate correctly control-shift chars
8775 like C-% so mask off shift here also. */
8776 /* Mask off modifier keys that are mapped to some Emacs
8777 modifiers. */
8778 int new_modifiers = modifiers & ~mapped_modifiers;
8779 /* set high byte of keycode to modifier high byte*/
8780 int new_key_code = key_code | new_modifiers;
8781 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8782 unsigned long some_state = 0;
8783 UInt32 new_char_code;
8785 new_char_code = KeyTranslate (kchr_ptr, new_key_code, &some_state);
8786 if (new_char_code == 0)
8787 /* Seems like a dead key. Append up-stroke. */
8788 new_char_code = KeyTranslate (kchr_ptr, new_key_code | 0x80,
8789 &some_state);
8790 if (new_char_code)
8792 buf->kind = ASCII_KEYSTROKE_EVENT;
8793 buf->code = new_char_code & 0xff;
8798 if (buf->kind == NO_EVENT)
8800 buf->kind = ASCII_KEYSTROKE_EVENT;
8801 buf->code = char_code;
8804 buf->modifiers = mac_to_emacs_modifiers (mapped_modifiers, modifiers);
8805 buf->modifiers |= (extra_keyboard_modifiers
8806 & (meta_modifier | alt_modifier
8807 | hyper_modifier | super_modifier));
8809 #if TARGET_API_MAC_CARBON
8810 if (buf->kind == ASCII_KEYSTROKE_EVENT
8811 && buf->code >= 0x80 && buf->modifiers)
8813 OSStatus err;
8814 TextEncoding encoding = kTextEncodingMacRoman;
8815 TextToUnicodeInfo ttu_info;
8817 UpgradeScriptInfoToTextEncoding (current_key_script,
8818 kTextLanguageDontCare,
8819 kTextRegionDontCare,
8820 NULL, &encoding);
8821 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
8822 if (err == noErr)
8824 UniChar code;
8825 Str255 pstr;
8826 ByteCount unicode_len;
8828 pstr[0] = 1;
8829 pstr[1] = buf->code;
8830 err = ConvertFromPStringToUnicode (ttu_info, pstr,
8831 sizeof (UniChar),
8832 &unicode_len, &code);
8833 if (err == noErr && unicode_len == sizeof (UniChar))
8834 mac_set_unicode_keystroke_event (code, buf);
8835 DisposeTextToUnicodeInfo (&ttu_info);
8838 #endif
8840 if (buf->kind == ASCII_KEYSTROKE_EVENT
8841 && buf->code >= 0x80
8842 && last_key_script != current_key_script)
8844 struct input_event event;
8846 EVENT_INIT (event);
8847 event.kind = LANGUAGE_CHANGE_EVENT;
8848 event.arg = Qnil;
8849 event.code = current_key_script;
8850 event.timestamp = timestamp;
8851 kbd_buffer_store_event (&event);
8852 last_key_script = current_key_script;
8856 void
8857 mac_store_apple_event (class, id, desc)
8858 Lisp_Object class, id;
8859 const AEDesc *desc;
8861 struct input_event buf;
8863 EVENT_INIT (buf);
8865 buf.kind = MAC_APPLE_EVENT;
8866 buf.x = class;
8867 buf.y = id;
8868 XSETFRAME (buf.frame_or_window,
8869 mac_focus_frame (&one_mac_display_info));
8870 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
8871 is safe to use them during read_socket_hook. */
8872 buf.arg = mac_aedesc_to_lisp (desc);
8873 kbd_buffer_store_event (&buf);
8876 #if TARGET_API_MAC_CARBON
8877 OSStatus
8878 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
8879 event, num_params, names, types)
8880 AEEventClass class;
8881 AEEventID id;
8882 Lisp_Object class_key, id_key;
8883 EventRef event;
8884 UInt32 num_params;
8885 const EventParamName *names;
8886 const EventParamType *types;
8888 OSStatus err = eventNotHandledErr;
8889 Lisp_Object binding;
8891 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
8892 if (!NILP (binding) && !EQ (binding, Qundefined))
8894 if (INTEGERP (binding))
8895 err = XINT (binding);
8896 else
8898 struct input_event buf;
8900 EVENT_INIT (buf);
8902 buf.kind = MAC_APPLE_EVENT;
8903 buf.x = class_key;
8904 buf.y = id_key;
8905 XSETFRAME (buf.frame_or_window,
8906 mac_focus_frame (&one_mac_display_info));
8907 /* Now that Lisp object allocations are protected by
8908 BLOCK_INPUT, it is safe to use them during
8909 read_socket_hook. */
8910 buf.arg = Fcons (build_string ("aevt"),
8911 mac_event_parameters_to_lisp (event, num_params,
8912 names, types));
8913 kbd_buffer_store_event (&buf);
8914 mac_wakeup_from_rne ();
8915 err = noErr;
8919 return err;
8921 #endif /* TARGET_API_MAC_CARBON */
8923 static pascal void
8924 mac_handle_dm_notification (event)
8925 AppleEvent *event;
8927 mac_screen_config_changed = 1;
8930 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8931 static void
8932 mac_handle_cg_display_reconfig (display, flags, user_info)
8933 CGDirectDisplayID display;
8934 CGDisplayChangeSummaryFlags flags;
8935 void *user_info;
8937 mac_screen_config_changed = 1;
8939 #endif
8941 static OSErr
8942 init_dm_notification_handler ()
8944 OSErr err = noErr;
8946 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
8947 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8948 if (CGDisplayRegisterReconfigurationCallback != NULL)
8949 #endif
8951 CGDisplayRegisterReconfigurationCallback (mac_handle_cg_display_reconfig,
8952 NULL);
8954 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8955 else /* CGDisplayRegisterReconfigurationCallback == NULL */
8956 #endif
8957 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
8958 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020
8960 static DMNotificationUPP handle_dm_notificationUPP = NULL;
8961 ProcessSerialNumber psn;
8963 if (handle_dm_notificationUPP == NULL)
8964 handle_dm_notificationUPP =
8965 NewDMNotificationUPP (mac_handle_dm_notification);
8967 err = GetCurrentProcess (&psn);
8968 if (err == noErr)
8969 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn);
8971 #endif
8973 return err;
8976 void
8977 mac_get_screen_info (dpyinfo)
8978 struct mac_display_info *dpyinfo;
8980 #ifdef MAC_OSX
8981 /* HasDepth returns true if it is possible to have a 32 bit display,
8982 but this may not be what is actually used. Mac OSX can do better. */
8983 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1;
8984 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay);
8986 CGDisplayErr err;
8987 CGDisplayCount ndisps;
8988 CGDirectDisplayID *displays;
8990 err = CGGetActiveDisplayList (0, NULL, &ndisps);
8991 if (err == noErr)
8993 displays = alloca (sizeof (CGDirectDisplayID) * ndisps);
8994 err = CGGetActiveDisplayList (ndisps, displays, &ndisps);
8996 if (err == noErr)
8998 CGRect bounds = CGRectZero;
9000 while (ndisps-- > 0)
9001 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps]));
9002 dpyinfo->height = CGRectGetHeight (bounds);
9003 dpyinfo->width = CGRectGetWidth (bounds);
9005 else
9007 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay);
9008 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay);
9011 #else /* !MAC_OSX */
9013 GDHandle gdh = GetMainDevice ();
9014 Rect rect = (**gdh).gdRect;
9016 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType);
9017 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9018 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p))
9019 break;
9021 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh;
9022 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays))
9023 UnionRect (&rect, &(**gdh).gdRect, &rect);
9025 dpyinfo->height = rect.bottom - rect.top;
9026 dpyinfo->width = rect.right - rect.left;
9028 #endif /* !MAC_OSX */
9032 /***********************************************************************
9033 Initialization (Mac OS Classic)
9034 ***********************************************************************/
9036 #ifdef MAC_OS8
9037 extern void init_emacs_passwd_dir ();
9038 extern int emacs_main (int, char **, char **);
9040 extern void initialize_applescript();
9041 extern void terminate_applescript();
9043 static void
9044 do_get_menus (void)
9046 Handle menubar_handle;
9047 MenuRef menu;
9049 menubar_handle = GetNewMBar (128);
9050 if(menubar_handle == NULL)
9051 abort ();
9052 SetMenuBar (menubar_handle);
9053 DrawMenuBar ();
9055 #if !TARGET_API_MAC_CARBON
9056 menu = GetMenuRef (M_APPLE);
9057 if (menu != NULL)
9058 AppendResMenu (menu, 'DRVR');
9059 else
9060 abort ();
9061 #endif
9064 static void
9065 do_init_managers (void)
9067 #if !TARGET_API_MAC_CARBON
9068 InitGraf (&qd.thePort);
9069 InitFonts ();
9070 FlushEvents (everyEvent, 0);
9071 InitWindows ();
9072 InitMenus ();
9073 TEInit ();
9074 InitDialogs (NULL);
9075 #endif /* !TARGET_API_MAC_CARBON */
9076 InitCursor ();
9078 #if !TARGET_API_MAC_CARBON
9079 /* set up some extra stack space for use by emacs */
9080 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
9082 /* MaxApplZone must be called for AppleScript to execute more
9083 complicated scripts */
9084 MaxApplZone ();
9085 MoreMasters ();
9086 #endif /* !TARGET_API_MAC_CARBON */
9089 static void
9090 do_check_ram_size (void)
9092 SInt32 physical_ram_size, logical_ram_size;
9094 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
9095 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
9096 || physical_ram_size > (1 << VALBITS)
9097 || logical_ram_size > (1 << VALBITS))
9099 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
9100 exit (1);
9104 #if __profile__
9105 void
9106 profiler_exit_proc ()
9108 ProfilerDump ("\pEmacs.prof");
9109 ProfilerTerm ();
9111 #endif
9113 /* These few functions implement Emacs as a normal Mac application
9114 (almost): set up the heap and the Toolbox, handle necessary system
9115 events plus a few simple menu events. They also set up Emacs's
9116 access to functions defined in the rest of this file. Emacs uses
9117 function hooks to perform all its terminal I/O. A complete list of
9118 these functions appear in termhooks.h. For what they do, read the
9119 comments there and see also w32term.c and xterm.c. What's
9120 noticeably missing here is the event loop, which is normally
9121 present in most Mac application. After performing the necessary
9122 Mac initializations, main passes off control to emacs_main
9123 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9124 (defined further below) to read input. This is where
9125 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9127 #undef main
9129 main (void)
9131 #if __profile__ /* is the profiler on? */
9132 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
9133 exit(1);
9134 #endif
9136 #if __MWERKS__
9137 /* set creator and type for files created by MSL */
9138 _fcreator = MAC_EMACS_CREATOR_CODE;
9139 _ftype = 'TEXT';
9140 #endif
9142 do_init_managers ();
9144 do_get_menus ();
9146 #ifndef USE_LSB_TAG
9147 do_check_ram_size ();
9148 #endif
9150 init_emacs_passwd_dir ();
9152 init_environ ();
9154 init_coercion_handler ();
9156 initialize_applescript ();
9158 init_apple_event_handler ();
9160 init_dm_notification_handler ();
9163 char **argv;
9164 int argc = 0;
9166 /* set up argv array from STR# resource */
9167 get_string_list (&argv, ARGV_STRING_LIST_ID);
9168 while (argv[argc])
9169 argc++;
9171 /* free up AppleScript resources on exit */
9172 atexit (terminate_applescript);
9174 #if __profile__ /* is the profiler on? */
9175 atexit (profiler_exit_proc);
9176 #endif
9178 /* 3rd param "envp" never used in emacs_main */
9179 (void) emacs_main (argc, argv, 0);
9182 /* Never reached - real exit in Fkill_emacs */
9183 return 0;
9186 /* Need to override CodeWarrior's input function so no conversion is
9187 done on newlines Otherwise compiled functions in .elc files will be
9188 read incorrectly. Defined in ...:MSL C:MSL
9189 Common:Source:buffer_io.c. */
9190 #ifdef __MWERKS__
9191 void
9192 __convert_to_newlines (unsigned char * p, size_t * n)
9194 #pragma unused(p,n)
9197 void
9198 __convert_from_newlines (unsigned char * p, size_t * n)
9200 #pragma unused(p,n)
9202 #endif
9204 void
9205 make_mac_terminal_frame (struct frame *f)
9207 Lisp_Object frame;
9208 Rect r;
9210 XSETFRAME (frame, f);
9212 f->output_method = output_mac;
9213 f->output_data.mac = (struct mac_output *)
9214 xmalloc (sizeof (struct mac_output));
9215 bzero (f->output_data.mac, sizeof (struct mac_output));
9217 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9219 FRAME_COLS (f) = 96;
9220 FRAME_LINES (f) = 4;
9222 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9223 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9225 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9227 f->output_data.mac->cursor_pixel = 0;
9228 f->output_data.mac->border_pixel = 0x00ff00;
9229 f->output_data.mac->mouse_pixel = 0xff00ff;
9230 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9232 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9233 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9234 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9235 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9236 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9237 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9239 FRAME_FONTSET (f) = -1;
9240 f->output_data.mac->explicit_parent = 0;
9241 f->left_pos = 8;
9242 f->top_pos = 32;
9243 f->border_width = 0;
9245 f->internal_border_width = 0;
9247 f->auto_raise = 1;
9248 f->auto_lower = 1;
9250 f->new_text_cols = 0;
9251 f->new_text_lines = 0;
9253 SetRect (&r, f->left_pos, f->top_pos,
9254 f->left_pos + FRAME_PIXEL_WIDTH (f),
9255 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9257 BLOCK_INPUT;
9259 if (!(FRAME_MAC_WINDOW (f) =
9260 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9261 (WindowRef) -1, 1, (long) f->output_data.mac)))
9262 abort ();
9263 /* so that update events can find this mac_output struct */
9264 f->output_data.mac->mFP = f; /* point back to emacs frame */
9266 UNBLOCK_INPUT;
9268 x_make_gc (f);
9270 /* Need to be initialized for unshow_buffer in window.c. */
9271 selected_window = f->selected_window;
9273 Fmodify_frame_parameters (frame,
9274 Fcons (Fcons (Qfont,
9275 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9276 Fmodify_frame_parameters (frame,
9277 Fcons (Fcons (Qforeground_color,
9278 build_string ("black")), Qnil));
9279 Fmodify_frame_parameters (frame,
9280 Fcons (Fcons (Qbackground_color,
9281 build_string ("white")), Qnil));
9283 #endif /* MAC_OS8 */
9286 /***********************************************************************
9287 Initialization
9288 ***********************************************************************/
9290 static int mac_initialized = 0;
9292 static XrmDatabase
9293 mac_make_rdb (xrm_option)
9294 const char *xrm_option;
9296 XrmDatabase database;
9298 database = xrm_get_preference_database (NULL);
9299 if (xrm_option)
9300 xrm_merge_string_database (database, xrm_option);
9302 return database;
9305 struct mac_display_info *
9306 mac_term_init (display_name, xrm_option, resource_name)
9307 Lisp_Object display_name;
9308 char *xrm_option;
9309 char *resource_name;
9311 struct mac_display_info *dpyinfo;
9313 BLOCK_INPUT;
9315 if (!mac_initialized)
9317 mac_initialize ();
9318 mac_initialized = 1;
9321 if (x_display_list)
9322 error ("Sorry, this version can only handle one display");
9324 dpyinfo = &one_mac_display_info;
9325 bzero (dpyinfo, sizeof (*dpyinfo));
9327 #ifdef MAC_OSX
9328 dpyinfo->mac_id_name
9329 = (char *) xmalloc (SCHARS (Vinvocation_name)
9330 + SCHARS (Vsystem_name)
9331 + 2);
9332 sprintf (dpyinfo->mac_id_name, "%s@%s",
9333 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9334 #else
9335 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9336 strcpy (dpyinfo->mac_id_name, "Mac Display");
9337 #endif
9339 dpyinfo->reference_count = 0;
9340 dpyinfo->resx = 72.0;
9341 dpyinfo->resy = 72.0;
9343 mac_get_screen_info (dpyinfo);
9345 dpyinfo->grabbed = 0;
9346 dpyinfo->root_window = NULL;
9347 dpyinfo->image_cache = make_image_cache ();
9349 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9350 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9351 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9352 dpyinfo->mouse_face_window = Qnil;
9353 dpyinfo->mouse_face_overlay = Qnil;
9354 dpyinfo->mouse_face_hidden = 0;
9356 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9358 /* Put this display on the chain. */
9359 dpyinfo->next = x_display_list;
9360 x_display_list = dpyinfo;
9362 /* Put it on x_display_name_list. */
9363 x_display_name_list = Fcons (Fcons (display_name,
9364 Fcons (Qnil, dpyinfo->xrdb)),
9365 x_display_name_list);
9366 dpyinfo->name_list_element = XCAR (x_display_name_list);
9368 UNBLOCK_INPUT;
9370 return dpyinfo;
9373 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9375 void
9376 x_delete_display (dpyinfo)
9377 struct mac_display_info *dpyinfo;
9379 int i;
9381 /* Discard this display from x_display_name_list and x_display_list.
9382 We can't use Fdelq because that can quit. */
9383 if (! NILP (x_display_name_list)
9384 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9385 x_display_name_list = XCDR (x_display_name_list);
9386 else
9388 Lisp_Object tail;
9390 tail = x_display_name_list;
9391 while (CONSP (tail) && CONSP (XCDR (tail)))
9393 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9395 XSETCDR (tail, XCDR (XCDR (tail)));
9396 break;
9398 tail = XCDR (tail);
9402 if (x_display_list == dpyinfo)
9403 x_display_list = dpyinfo->next;
9404 else
9406 struct x_display_info *tail;
9408 for (tail = x_display_list; tail; tail = tail->next)
9409 if (tail->next == dpyinfo)
9410 tail->next = tail->next->next;
9413 /* Free the font names in the font table. */
9414 for (i = 0; i < dpyinfo->n_fonts; i++)
9415 if (dpyinfo->font_table[i].name)
9417 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9418 xfree (dpyinfo->font_table[i].full_name);
9419 xfree (dpyinfo->font_table[i].name);
9422 if (dpyinfo->font_table)
9424 if (dpyinfo->font_table->font_encoder)
9425 xfree (dpyinfo->font_table->font_encoder);
9426 xfree (dpyinfo->font_table);
9428 if (dpyinfo->mac_id_name)
9429 xfree (dpyinfo->mac_id_name);
9431 if (x_display_list == 0)
9433 mac_clear_font_name_table ();
9434 bzero (dpyinfo, sizeof (*dpyinfo));
9439 /* Set up use of X before we make the first connection. */
9441 extern frame_parm_handler mac_frame_parm_handlers[];
9443 static struct redisplay_interface x_redisplay_interface =
9445 mac_frame_parm_handlers,
9446 x_produce_glyphs,
9447 x_write_glyphs,
9448 x_insert_glyphs,
9449 x_clear_end_of_line,
9450 x_scroll_run,
9451 x_after_update_window_line,
9452 x_update_window_begin,
9453 x_update_window_end,
9454 x_cursor_to,
9455 x_flush,
9456 #if USE_CG_DRAWING
9457 mac_flush_display_optional,
9458 #else
9459 0, /* flush_display_optional */
9460 #endif
9461 x_clear_window_mouse_face,
9462 x_get_glyph_overhangs,
9463 x_fix_overlapping_area,
9464 x_draw_fringe_bitmap,
9465 #if USE_CG_DRAWING
9466 mac_define_fringe_bitmap,
9467 mac_destroy_fringe_bitmap,
9468 #else
9469 0, /* define_fringe_bitmap */
9470 0, /* destroy_fringe_bitmap */
9471 #endif
9472 mac_per_char_metric,
9473 mac_encode_char,
9474 mac_compute_glyph_string_overhangs,
9475 x_draw_glyph_string,
9476 mac_define_frame_cursor,
9477 mac_clear_frame_area,
9478 mac_draw_window_cursor,
9479 mac_draw_vertical_window_border,
9480 mac_shift_glyphs_for_insert
9483 void
9484 mac_initialize ()
9486 rif = &x_redisplay_interface;
9488 clear_frame_hook = x_clear_frame;
9489 ins_del_lines_hook = x_ins_del_lines;
9490 delete_glyphs_hook = x_delete_glyphs;
9491 ring_bell_hook = XTring_bell;
9492 reset_terminal_modes_hook = XTreset_terminal_modes;
9493 set_terminal_modes_hook = XTset_terminal_modes;
9494 update_begin_hook = x_update_begin;
9495 update_end_hook = x_update_end;
9496 set_terminal_window_hook = XTset_terminal_window;
9497 read_socket_hook = XTread_socket;
9498 frame_up_to_date_hook = XTframe_up_to_date;
9499 mouse_position_hook = XTmouse_position;
9500 frame_rehighlight_hook = XTframe_rehighlight;
9501 frame_raise_lower_hook = XTframe_raise_lower;
9503 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9504 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9505 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9506 judge_scroll_bars_hook = XTjudge_scroll_bars;
9508 scroll_region_ok = 1; /* we'll scroll partial frames */
9509 char_ins_del_ok = 1;
9510 line_ins_del_ok = 1; /* we'll just blt 'em */
9511 fast_clear_end_of_line = 1; /* X does this well */
9512 memory_below_frame = 0; /* we don't remember what scrolls
9513 off the bottom */
9514 baud_rate = 19200;
9516 last_tool_bar_item = -1;
9518 /* Try to use interrupt input; if we can't, then start polling. */
9519 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9521 BLOCK_INPUT;
9523 #if TARGET_API_MAC_CARBON
9524 #ifdef MAC_OSX
9525 init_coercion_handler ();
9527 init_dm_notification_handler ();
9528 #endif
9530 install_application_handler ();
9532 mac_toolbox_initialize ();
9534 #ifdef MAC_OSX
9535 if (!inhibit_window_system)
9537 static const ProcessSerialNumber psn = {0, kCurrentProcess};
9539 SetFrontProcess (&psn);
9541 #endif
9542 #endif
9544 #if USE_CG_DRAWING
9545 init_cg_color ();
9547 mac_init_fringe ();
9548 #endif
9550 UNBLOCK_INPUT;
9554 void
9555 syms_of_macterm ()
9557 #if 0
9558 staticpro (&x_error_message_string);
9559 x_error_message_string = Qnil;
9560 #endif
9562 Qcontrol = intern ("control"); staticpro (&Qcontrol);
9563 Qmeta = intern ("meta"); staticpro (&Qmeta);
9564 Qalt = intern ("alt"); staticpro (&Qalt);
9565 Qhyper = intern ("hyper"); staticpro (&Qhyper);
9566 Qsuper = intern ("super"); staticpro (&Qsuper);
9567 Qmodifier_value = intern ("modifier-value");
9568 staticpro (&Qmodifier_value);
9570 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
9571 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
9572 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9573 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9574 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9576 #if TARGET_API_MAC_CARBON
9577 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command);
9578 #ifdef MAC_OSX
9579 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
9580 staticpro (&Qtoolbar_switch_mode);
9581 #if USE_MAC_FONT_PANEL
9582 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
9583 Qselection = intern ("selection"); staticpro (&Qselection);
9584 #endif
9586 Qservice = intern ("service"); staticpro (&Qservice);
9587 Qpaste = intern ("paste"); staticpro (&Qpaste);
9588 Qperform = intern ("perform"); staticpro (&Qperform);
9590 Qmouse_drag_overlay = intern ("mouse-drag-overlay");
9591 staticpro (&Qmouse_drag_overlay);
9592 #endif
9593 #if USE_MAC_TSM
9594 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
9595 Qupdate_active_input_area = intern ("update-active-input-area");
9596 staticpro (&Qupdate_active_input_area);
9597 Qunicode_for_key_event = intern ("unicode-for-key-event");
9598 staticpro (&Qunicode_for_key_event);
9599 #endif
9600 #endif
9602 #ifdef MAC_OSX
9603 Fprovide (intern ("mac-carbon"), Qnil);
9604 #endif
9606 staticpro (&Qreverse);
9607 Qreverse = intern ("reverse");
9609 staticpro (&x_display_name_list);
9610 x_display_name_list = Qnil;
9612 staticpro (&last_mouse_scroll_bar);
9613 last_mouse_scroll_bar = Qnil;
9615 staticpro (&fm_font_family_alist);
9616 fm_font_family_alist = Qnil;
9618 #if USE_ATSUI
9619 staticpro (&atsu_font_id_hash);
9620 atsu_font_id_hash = Qnil;
9622 staticpro (&fm_style_face_attributes_alist);
9623 fm_style_face_attributes_alist = Qnil;
9624 #endif
9626 #if USE_MAC_TSM
9627 staticpro (&saved_ts_script_language_on_focus);
9628 saved_ts_script_language_on_focus = Qnil;
9629 #endif
9631 /* We don't yet support this, but defining this here avoids whining
9632 from cus-start.el and other places, like "M-x set-variable". */
9633 DEFVAR_BOOL ("x-use-underline-position-properties",
9634 &x_use_underline_position_properties,
9635 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9636 A value of nil means ignore them. If you encounter fonts with bogus
9637 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9638 to 4.1, set this to nil.
9640 NOTE: Not supported on Mac yet. */);
9641 x_use_underline_position_properties = 0;
9643 DEFVAR_BOOL ("x-underline-at-descent-line",
9644 &x_underline_at_descent_line,
9645 doc: /* *Non-nil means to draw the underline at the same place as the descent line.
9646 A value of nil means to draw the underline according to the value of the
9647 variable `x-use-underline-position-properties', which is usually at the
9648 baseline level. The default value is nil. */);
9649 x_underline_at_descent_line = 0;
9651 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9652 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9653 #ifdef USE_TOOLKIT_SCROLL_BARS
9654 Vx_toolkit_scroll_bars = Qt;
9655 #else
9656 Vx_toolkit_scroll_bars = Qnil;
9657 #endif
9659 staticpro (&last_mouse_motion_frame);
9660 last_mouse_motion_frame = Qnil;
9662 /* Variables to configure modifier key assignment. */
9664 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
9665 doc: /* *Modifier key assumed when the Mac control key is pressed.
9666 The value can be `control', `meta', `alt', `hyper', or `super' for the
9667 respective modifier. The default is `control'. */);
9668 Vmac_control_modifier = Qcontrol;
9670 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9671 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
9672 The value can be `control', `meta', `alt', `hyper', or `super' for the
9673 respective modifier. If the value is nil then the key will act as the
9674 normal Mac control modifier, and the option key can be used to compose
9675 characters depending on the chosen Mac keyboard setting. */);
9676 Vmac_option_modifier = Qnil;
9678 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
9679 doc: /* *Modifier key assumed when the Mac command key is pressed.
9680 The value can be `control', `meta', `alt', `hyper', or `super' for the
9681 respective modifier. The default is `meta'. */);
9682 Vmac_command_modifier = Qmeta;
9684 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
9685 doc: /* *Modifier key assumed when the Mac function key is pressed.
9686 The value can be `control', `meta', `alt', `hyper', or `super' for the
9687 respective modifier. Note that remapping the function key may lead to
9688 unexpected results for some keys on non-US/GB keyboards. */);
9689 Vmac_function_modifier = Qnil;
9691 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9692 &Vmac_emulate_three_button_mouse,
9693 doc: /* *Specify a way of three button mouse emulation.
9694 The value can be nil, t, or the symbol `reverse'.
9695 A value of nil means that no emulation should be done and the modifiers
9696 should be placed on the mouse-1 event.
9697 t means that when the option-key is held down while pressing the mouse
9698 button, the click will register as mouse-2 and while the command-key
9699 is held down, the click will register as mouse-3.
9700 The symbol `reverse' means that the option-key will register for
9701 mouse-3 and the command-key will register for mouse-2. */);
9702 Vmac_emulate_three_button_mouse = Qnil;
9704 #if TARGET_API_MAC_CARBON
9705 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
9706 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
9707 Otherwise, the right click will be treated as mouse-2 and the wheel
9708 button will be mouse-3. */);
9709 mac_wheel_button_is_mouse_2 = 1;
9711 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
9712 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
9713 mac_pass_command_to_system = 1;
9715 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
9716 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
9717 mac_pass_control_to_system = 1;
9719 #endif
9721 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
9722 doc: /* *If non-nil, allow anti-aliasing.
9723 The text will be rendered using Core Graphics text rendering which
9724 may anti-alias the text. */);
9725 #if USE_CG_DRAWING
9726 mac_use_core_graphics = 1;
9727 #else
9728 mac_use_core_graphics = 0;
9729 #endif
9731 /* Register an entry for `mac-roman' so that it can be used when
9732 creating the terminal frame on Mac OS 9 before loading
9733 term/mac-win.elc. */
9734 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
9735 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
9736 Each entry should be of the form:
9738 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
9740 where CHARSET-NAME is a string used in font names to identify the
9741 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
9742 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
9743 Vmac_charset_info_alist =
9744 Fcons (list3 (build_string ("mac-roman"),
9745 make_number (smRoman), Qnil), Qnil);
9747 #if USE_MAC_TSM
9748 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
9749 doc: /* Overlay used to display Mac TSM active input area. */);
9750 Vmac_ts_active_input_overlay = Qnil;
9752 DEFVAR_LISP ("mac-ts-active-input-buf", &Vmac_ts_active_input_buf,
9753 doc: /* Byte sequence of the current Mac TSM active input area. */);
9754 /* `empty_string' is not ready yet on Mac OS Classic. */
9755 Vmac_ts_active_input_buf = build_string ("");
9757 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus,
9758 doc: /* *How to change Mac TSM script/language when a frame gets focus.
9759 If the value is t, the input script and language are restored to those
9760 used in the last focus frame. If the value is a pair of integers, the
9761 input script and language codes, which are defined in the Script
9762 Manager, are set to its car and cdr parts, respectively. Otherwise,
9763 Emacs doesn't set them and thus follows the system default behavior. */);
9764 Vmac_ts_script_language_on_focus = Qnil;
9765 #endif
9768 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9769 (do not change this comment) */