Mention `redisplay-dont-pause' in doc string of
[emacs.git] / src / macterm.c
blob995422b90fc465ad5d0ea6ae1e1e3d233eb4ce61
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 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 2, or (at your option)
10 any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
24 #include <config.h>
25 #include <signal.h>
27 #include <stdio.h>
29 #include "lisp.h"
30 #include "blockinput.h"
32 #include "macterm.h"
34 #ifndef MAC_OSX
35 #include <alloca.h>
36 #endif
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
41 used instead. */
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
46 #include <Sound.h>
47 #include <Events.h>
48 #include <Script.h>
49 #include <Resources.h>
50 #include <Fonts.h>
51 #include <TextUtils.h>
52 #include <LowMem.h>
53 #include <Controls.h>
54 #include <Windows.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
57 #endif
59 #if __profile__
60 #include <profiler.h>
61 #endif
62 #endif /* not TARGET_API_MAC_CARBON */
64 #include "systty.h"
65 #include "systime.h"
67 #include <ctype.h>
68 #include <errno.h>
69 #include <setjmp.h>
70 #include <sys/stat.h>
72 #include "charset.h"
73 #include "coding.h"
74 #include "frame.h"
75 #include "dispextern.h"
76 #include "fontset.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #include "disptab.h"
81 #include "buffer.h"
82 #include "window.h"
83 #include "keyboard.h"
84 #include "intervals.h"
85 #include "atimer.h"
86 #include "keymap.h"
90 /* Non-nil means Emacs uses toolkit scroll bars. */
92 Lisp_Object Vx_toolkit_scroll_bars;
94 /* If non-zero, the text will be rendered using Core Graphics text
95 rendering which may anti-alias the text. */
96 int mac_use_core_graphics;
99 /* Non-zero means that a HELP_EVENT has been generated since Emacs
100 start. */
102 static int any_help_event_p;
104 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
105 static Lisp_Object last_window;
107 /* Non-zero means make use of UNDERLINE_POSITION font properties.
108 (Not yet supported.) */
109 int x_use_underline_position_properties;
111 /* This is a chain of structures for all the X displays currently in
112 use. */
114 struct x_display_info *x_display_list;
116 /* This is a list of cons cells, each of the form (NAME
117 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
118 x_display_list and in the same order. NAME is the name of the
119 frame. FONT-LIST-CACHE records previous values returned by
120 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
121 equivalent, which is implemented with a Lisp object, for the
122 display. */
124 Lisp_Object x_display_name_list;
126 /* This is display since Mac does not support multiple ones. */
127 struct mac_display_info one_mac_display_info;
129 /* Frame being updated by update_frame. This is declared in term.c.
130 This is set by update_begin and looked at by all the XT functions.
131 It is zero while not inside an update. In that case, the XT
132 functions assume that `selected_frame' is the frame to apply to. */
134 extern struct frame *updating_frame;
136 /* This is a frame waiting to be auto-raised, within XTread_socket. */
138 struct frame *pending_autoraise_frame;
140 /* Mouse movement.
142 Formerly, we used PointerMotionHintMask (in standard_event_mask)
143 so that we would have to call XQueryPointer after each MotionNotify
144 event to ask for another such event. However, this made mouse tracking
145 slow, and there was a bug that made it eventually stop.
147 Simply asking for MotionNotify all the time seems to work better.
149 In order to avoid asking for motion events and then throwing most
150 of them away or busy-polling the server for mouse positions, we ask
151 the server for pointer motion hints. This means that we get only
152 one event per group of mouse movements. "Groups" are delimited by
153 other kinds of events (focus changes and button clicks, for
154 example), or by XQueryPointer calls; when one of these happens, we
155 get another MotionNotify event the next time the mouse moves. This
156 is at least as efficient as getting motion events when mouse
157 tracking is on, and I suspect only negligibly worse when tracking
158 is off. */
160 /* Where the mouse was last time we reported a mouse event. */
162 static Rect last_mouse_glyph;
163 static FRAME_PTR last_mouse_glyph_frame;
165 /* The scroll bar in which the last X motion event occurred.
167 If the last X motion event occurred in a scroll bar, we set this so
168 XTmouse_position can know whether to report a scroll bar motion or
169 an ordinary motion.
171 If the last X motion event didn't occur in a scroll bar, we set
172 this to Qnil, to tell XTmouse_position to return an ordinary motion
173 event. */
175 static Lisp_Object last_mouse_scroll_bar;
177 /* This is a hack. We would really prefer that XTmouse_position would
178 return the time associated with the position it returns, but there
179 doesn't seem to be any way to wrest the time-stamp from the server
180 along with the position query. So, we just keep track of the time
181 of the last movement we received, and return that in hopes that
182 it's somewhat accurate. */
184 static Time last_mouse_movement_time;
186 struct scroll_bar *tracked_scroll_bar = NULL;
188 /* Incremented by XTread_socket whenever it really tries to read
189 events. */
191 #ifdef __STDC__
192 static int volatile input_signal_count;
193 #else
194 static int input_signal_count;
195 #endif
197 extern Lisp_Object Vsystem_name;
199 /* A mask of extra modifier bits to put into every keyboard char. */
201 extern EMACS_INT extra_keyboard_modifiers;
203 /* The keysyms to use for the various modifiers. */
205 static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
207 extern int inhibit_window_system;
209 #if __MRC__ && !TARGET_API_MAC_CARBON
210 QDGlobals qd; /* QuickDraw global information structure. */
211 #endif
213 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
215 struct mac_display_info *mac_display_info_for_display (Display *);
216 static void x_update_window_end P_ ((struct window *, int, int));
217 int x_catch_errors P_ ((Display *));
218 void x_uncatch_errors P_ ((Display *, int));
219 void x_lower_frame P_ ((struct frame *));
220 void x_scroll_bar_clear P_ ((struct frame *));
221 int x_had_errors_p P_ ((Display *));
222 void x_wm_set_size_hint P_ ((struct frame *, long, int));
223 void x_raise_frame P_ ((struct frame *));
224 void x_set_window_size P_ ((struct frame *, int, int, int));
225 void x_wm_set_window_state P_ ((struct frame *, int));
226 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
227 void mac_initialize P_ ((void));
228 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
229 static int x_compute_min_glyph_bounds P_ ((struct frame *));
230 static void x_update_end P_ ((struct frame *));
231 static void XTframe_up_to_date P_ ((struct frame *));
232 static void XTset_terminal_modes P_ ((void));
233 static void XTreset_terminal_modes P_ ((void));
234 static void x_clear_frame P_ ((void));
235 static void frame_highlight P_ ((struct frame *));
236 static void frame_unhighlight P_ ((struct frame *));
237 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
238 static void mac_focus_changed P_ ((int, struct mac_display_info *,
239 struct frame *, struct input_event *));
240 static void x_detect_focus_change P_ ((struct mac_display_info *,
241 EventRecord *, struct input_event *));
242 static void XTframe_rehighlight P_ ((struct frame *));
243 static void x_frame_rehighlight P_ ((struct x_display_info *));
244 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
245 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
246 enum text_cursor_kinds));
248 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
249 static void x_flush P_ ((struct frame *f));
250 static void x_update_begin P_ ((struct frame *));
251 static void x_update_window_begin P_ ((struct window *));
252 static void x_after_update_window_line P_ ((struct glyph_row *));
253 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
254 enum scroll_bar_part *,
255 Lisp_Object *, Lisp_Object *,
256 unsigned long *));
258 static int is_emacs_window P_ ((WindowPtr));
259 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
260 static void XSetFont P_ ((Display *, GC, XFontStruct *));
262 /* Defined in macmenu.h. */
263 extern void menubar_selection_callback (FRAME_PTR, int);
265 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
266 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
267 #define GC_FONT(gc) ((gc)->xgcv.font)
268 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
269 #define CG_SET_FILL_COLOR(context, color) \
270 CGContextSetRGBFillColor (context, \
271 RED_FROM_ULONG (color) / 255.0f, \
272 GREEN_FROM_ULONG (color) / 255.0f, \
273 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
274 #define CG_SET_STROKE_COLOR(context, color) \
275 CGContextSetRGBStrokeColor (context, \
276 RED_FROM_ULONG (color) / 255.0f, \
277 GREEN_FROM_ULONG (color) / 255.0f, \
278 BLUE_FROM_ULONG (color) / 255.0f, 1.0f)
279 #if USE_CG_DRAWING
280 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
282 /* Fringe bitmaps. */
284 static int max_fringe_bmp = 0;
285 static CGImageRef *fringe_bmp = 0;
287 static CGContextRef
288 mac_begin_cg_clip (f, gc)
289 struct frame *f;
290 GC gc;
292 CGContextRef context = FRAME_CG_CONTEXT (f);
294 if (!context)
296 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context);
297 FRAME_CG_CONTEXT (f) = context;
300 CGContextSaveGState (context);
301 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f));
302 CGContextScaleCTM (context, 1, -1);
303 if (gc && gc->n_clip_rects)
304 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
306 return context;
309 static void
310 mac_end_cg_clip (f)
311 struct frame *f;
313 CGContextRestoreGState (FRAME_CG_CONTEXT (f));
316 void
317 mac_prepare_for_quickdraw (f)
318 struct frame *f;
320 if (f == NULL)
322 Lisp_Object rest, frame;
323 FOR_EACH_FRAME (rest, frame)
324 if (FRAME_MAC_P (XFRAME (frame)))
325 mac_prepare_for_quickdraw (XFRAME (frame));
327 else
329 CGContextRef context = FRAME_CG_CONTEXT (f);
331 if (context)
333 CGContextSynchronize (context);
334 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)),
335 &FRAME_CG_CONTEXT (f));
339 #endif
341 static RgnHandle saved_port_clip_region = NULL;
343 static void
344 mac_begin_clip (gc)
345 GC gc;
347 static RgnHandle new_region = NULL;
349 if (saved_port_clip_region == NULL)
350 saved_port_clip_region = NewRgn ();
351 if (new_region == NULL)
352 new_region = NewRgn ();
354 if (gc->n_clip_rects)
356 GetClip (saved_port_clip_region);
357 SectRgn (saved_port_clip_region, gc->clip_region, new_region);
358 SetClip (new_region);
362 static void
363 mac_end_clip (gc)
364 GC gc;
366 if (gc->n_clip_rects)
367 SetClip (saved_port_clip_region);
371 /* X display function emulation */
373 void
374 XFreePixmap (display, pixmap)
375 Display *display; /* not used */
376 Pixmap pixmap;
378 DisposeGWorld (pixmap);
382 /* Mac version of XDrawLine. */
384 static void
385 mac_draw_line (f, gc, x1, y1, x2, y2)
386 struct frame *f;
387 GC gc;
388 int x1, y1, x2, y2;
390 #if USE_CG_DRAWING
391 CGContextRef context;
392 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2;
394 if (y1 != y2)
395 gx1 += 0.5f, gx2 += 0.5f;
396 if (x1 != x2)
397 gy1 += 0.5f, gy2 += 0.5f;
399 context = mac_begin_cg_clip (f, gc);
400 CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
401 CGContextBeginPath (context);
402 CGContextMoveToPoint (context, gx1, gy1);
403 CGContextAddLineToPoint (context, gx2, gy2);
404 CGContextClosePath (context);
405 CGContextStrokePath (context);
406 mac_end_cg_clip (f);
407 #else
408 if (x1 == x2)
410 if (y1 > y2)
411 y1--;
412 else if (y2 > y1)
413 y2--;
415 else if (y1 == y2)
417 if (x1 > x2)
418 x1--;
419 else
420 x2--;
423 SetPortWindowPort (FRAME_MAC_WINDOW (f));
425 RGBForeColor (GC_FORE_COLOR (gc));
427 mac_begin_clip (gc);
428 MoveTo (x1, y1);
429 LineTo (x2, y2);
430 mac_end_clip (gc);
431 #endif
434 void
435 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
436 Display *display;
437 Pixmap p;
438 GC gc;
439 int x1, y1, x2, y2;
441 CGrafPtr old_port;
442 GDHandle old_gdh;
444 if (x1 == x2)
446 if (y1 > y2)
447 y1--;
448 else if (y2 > y1)
449 y2--;
451 else if (y1 == y2)
453 if (x1 > x2)
454 x1--;
455 else
456 x2--;
459 GetGWorld (&old_port, &old_gdh);
460 SetGWorld (p, NULL);
462 RGBForeColor (GC_FORE_COLOR (gc));
464 LockPixels (GetGWorldPixMap (p));
465 MoveTo (x1, y1);
466 LineTo (x2, y2);
467 UnlockPixels (GetGWorldPixMap (p));
469 SetGWorld (old_port, old_gdh);
473 static void
474 mac_erase_rectangle (f, gc, x, y, width, height)
475 struct frame *f;
476 GC gc;
477 int x, y;
478 unsigned int width, height;
480 #if USE_CG_DRAWING
481 CGContextRef context;
483 context = mac_begin_cg_clip (f, gc);
484 CG_SET_FILL_COLOR (context, gc->xgcv.background);
485 CGContextFillRect (context, CGRectMake (x, y, width, height));
486 mac_end_cg_clip (f);
487 #else
488 Rect r;
490 SetPortWindowPort (FRAME_MAC_WINDOW (f));
492 RGBBackColor (GC_BACK_COLOR (gc));
493 SetRect (&r, x, y, x + width, y + height);
495 mac_begin_clip (gc);
496 EraseRect (&r);
497 mac_end_clip (gc);
499 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
500 #endif
504 /* Mac version of XClearArea. */
506 void
507 mac_clear_area (f, x, y, width, height)
508 struct frame *f;
509 int x, y;
510 unsigned int width, height;
512 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
515 /* Mac version of XClearWindow. */
517 static void
518 mac_clear_window (f)
519 struct frame *f;
521 #if USE_CG_DRAWING
522 CGContextRef context;
523 GC gc = FRAME_NORMAL_GC (f);
525 context = mac_begin_cg_clip (f, NULL);
526 CG_SET_FILL_COLOR (context, gc->xgcv.background);
527 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f),
528 FRAME_PIXEL_HEIGHT (f)));
529 mac_end_cg_clip (f);
530 #else
531 SetPortWindowPort (FRAME_MAC_WINDOW (f));
533 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
535 #if TARGET_API_MAC_CARBON
537 Rect r;
539 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
540 EraseRect (&r);
542 #else /* not TARGET_API_MAC_CARBON */
543 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
544 #endif /* not TARGET_API_MAC_CARBON */
545 #endif
549 /* Mac replacement for XCopyArea. */
551 #if USE_CG_DRAWING
552 static void
553 mac_draw_cg_image (image, f, gc, src_x, src_y, width, height,
554 dest_x, dest_y, overlay_p)
555 CGImageRef image;
556 struct frame *f;
557 GC gc;
558 int src_x, src_y;
559 unsigned int width, height;
560 int dest_x, dest_y, overlay_p;
562 CGContextRef context;
563 float port_height = FRAME_PIXEL_HEIGHT (f);
564 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height);
566 context = mac_begin_cg_clip (f, gc);
567 if (!overlay_p)
569 CG_SET_FILL_COLOR (context, gc->xgcv.background);
570 CGContextFillRect (context, dest_rect);
572 CGContextClipToRect (context, dest_rect);
573 CGContextScaleCTM (context, 1, -1);
574 CGContextTranslateCTM (context, 0, -port_height);
575 if (CGImageIsMask (image))
576 CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
577 CGContextDrawImage (context,
578 CGRectMake (dest_x - src_x,
579 port_height - (dest_y - src_y
580 + CGImageGetHeight (image)),
581 CGImageGetWidth (image),
582 CGImageGetHeight (image)),
583 image);
584 mac_end_cg_clip (f);
587 #else /* !USE_CG_DRAWING */
589 static void
590 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
591 struct frame *f;
592 GC gc;
593 int x, y, width, height;
594 unsigned short *bits;
595 int overlay_p;
597 BitMap bitmap;
598 Rect r;
600 bitmap.rowBytes = sizeof(unsigned short);
601 bitmap.baseAddr = (char *)bits;
602 SetRect (&(bitmap.bounds), 0, 0, width, height);
604 SetPortWindowPort (FRAME_MAC_WINDOW (f));
606 RGBForeColor (GC_FORE_COLOR (gc));
607 RGBBackColor (GC_BACK_COLOR (gc));
608 SetRect (&r, x, y, x + width, y + height);
610 mac_begin_clip (gc);
611 #if TARGET_API_MAC_CARBON
613 CGrafPtr port;
615 GetPort (&port);
616 LockPortBits (port);
617 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
618 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
619 UnlockPortBits (port);
621 #else /* not TARGET_API_MAC_CARBON */
622 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
623 overlay_p ? srcOr : srcCopy, 0);
624 #endif /* not TARGET_API_MAC_CARBON */
625 mac_end_clip (gc);
627 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
629 #endif /* !USE_CG_DRAWING */
632 /* Mac replacement for XCreateBitmapFromBitmapData. */
634 static void
635 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
636 BitMap *bitmap;
637 char *bits;
638 int w, h;
640 static unsigned char swap_nibble[16]
641 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
642 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
643 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
644 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
645 int i, j, w1;
646 char *p;
648 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
649 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
650 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
651 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
652 for (i = 0; i < h; i++)
654 p = bitmap->baseAddr + i * bitmap->rowBytes;
655 for (j = 0; j < w1; j++)
657 /* Bitswap XBM bytes to match how Mac does things. */
658 unsigned char c = *bits++;
659 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
660 | (swap_nibble[(c>>4) & 0xf]));;
664 SetRect (&(bitmap->bounds), 0, 0, w, h);
668 static void
669 mac_free_bitmap (bitmap)
670 BitMap *bitmap;
672 xfree (bitmap->baseAddr);
676 Pixmap
677 XCreatePixmap (display, w, width, height, depth)
678 Display *display; /* not used */
679 WindowPtr w;
680 unsigned int width, height;
681 unsigned int depth;
683 Pixmap pixmap;
684 Rect r;
685 QDErr err;
687 SetPortWindowPort (w);
689 SetRect (&r, 0, 0, width, height);
690 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
691 if (depth == 1)
692 #endif
693 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
694 #if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING
695 else
696 /* CreateCGImageFromPixMaps requires ARGB format. */
697 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0);
698 #endif
699 if (err != noErr)
700 return NULL;
701 return pixmap;
705 Pixmap
706 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
707 Display *display; /* not used */
708 WindowPtr 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 CGrafPtr old_port;
717 GDHandle old_gdh;
718 static GC gc = NULL; /* not reentrant */
720 if (gc == NULL)
721 gc = XCreateGC (display, w, 0, NULL);
723 pixmap = XCreatePixmap (display, w, width, height, depth);
724 if (pixmap == NULL)
725 return NULL;
727 GetGWorld (&old_port, &old_gdh);
728 SetGWorld (pixmap, NULL);
729 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
730 XSetForeground (display, gc, fg);
731 XSetBackground (display, gc, bg);
732 RGBForeColor (GC_FORE_COLOR (gc));
733 RGBBackColor (GC_BACK_COLOR (gc));
734 LockPixels (GetGWorldPixMap (pixmap));
735 #if TARGET_API_MAC_CARBON
736 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
737 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
738 #else /* not TARGET_API_MAC_CARBON */
739 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
740 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
741 #endif /* not TARGET_API_MAC_CARBON */
742 UnlockPixels (GetGWorldPixMap (pixmap));
743 SetGWorld (old_port, old_gdh);
744 mac_free_bitmap (&bitmap);
746 return pixmap;
750 /* Mac replacement for XFillRectangle. */
752 static void
753 mac_fill_rectangle (f, gc, x, y, width, height)
754 struct frame *f;
755 GC gc;
756 int x, y;
757 unsigned int width, height;
759 #if USE_CG_DRAWING
760 CGContextRef context;
762 context = mac_begin_cg_clip (f, gc);
763 CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
764 CGContextFillRect (context, CGRectMake (x, y, width, height));
765 mac_end_cg_clip (f);
766 #else
767 Rect r;
769 SetPortWindowPort (FRAME_MAC_WINDOW (f));
771 RGBForeColor (GC_FORE_COLOR (gc));
772 SetRect (&r, x, y, x + width, y + height);
774 mac_begin_clip (gc);
775 PaintRect (&r); /* using foreground color of gc */
776 mac_end_clip (gc);
777 #endif
781 /* Mac replacement for XDrawRectangle: dest is a window. */
783 static void
784 mac_draw_rectangle (f, gc, x, y, width, height)
785 struct frame *f;
786 GC gc;
787 int x, y;
788 unsigned int width, height;
790 #if USE_CG_DRAWING
791 CGContextRef context;
793 context = mac_begin_cg_clip (f, gc);
794 CG_SET_STROKE_COLOR (context, gc->xgcv.foreground);
795 CGContextStrokeRect (context,
796 CGRectMake (x + 0.5f, y + 0.5f, width, height));
797 mac_end_cg_clip (f);
798 #else
799 Rect r;
801 SetPortWindowPort (FRAME_MAC_WINDOW (f));
803 RGBForeColor (GC_FORE_COLOR (gc));
804 SetRect (&r, x, y, x + width + 1, y + height + 1);
806 mac_begin_clip (gc);
807 FrameRect (&r); /* using foreground color of gc */
808 mac_end_clip (gc);
809 #endif
813 #if USE_ATSUI
814 static OSStatus
815 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
816 ConstUniCharArrayPtr text;
817 UniCharCount text_length;
818 ATSUStyle style;
819 ATSUTextLayout *text_layout;
821 OSStatus err;
822 static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
824 if (saved_text_layout == NULL)
826 UniCharCount lengths[] = {kATSUToTextEnd};
827 ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
828 ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
829 static ATSLineLayoutOptions line_layout =
830 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
831 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
832 | kATSLineUseQDRendering
833 #else
834 kATSLineIsDisplayOnly | kATSLineFractDisable
835 #endif
837 ATSUAttributeValuePtr values[] = {&line_layout};
839 err = ATSUCreateTextLayoutWithTextPtr (text,
840 kATSUFromTextBeginning,
841 kATSUToTextEnd,
842 text_length,
843 1, lengths, &style,
844 &saved_text_layout);
845 if (err == noErr)
846 err = ATSUSetLayoutControls (saved_text_layout,
847 sizeof (tags) / sizeof (tags[0]),
848 tags, sizes, values);
849 /* XXX: Should we do this? */
850 if (err == noErr)
851 err = ATSUSetTransientFontMatching (saved_text_layout, true);
853 else
855 err = ATSUSetRunStyle (saved_text_layout, style,
856 kATSUFromTextBeginning, kATSUToTextEnd);
857 if (err == noErr)
858 err = ATSUSetTextPointerLocation (saved_text_layout, text,
859 kATSUFromTextBeginning,
860 kATSUToTextEnd,
861 text_length);
864 if (err == noErr)
865 *text_layout = saved_text_layout;
866 return err;
868 #endif
871 static void
872 mac_invert_rectangle (f, x, y, width, height)
873 struct frame *f;
874 int x, y;
875 unsigned int width, height;
877 Rect r;
879 #if USE_CG_DRAWING
880 mac_prepare_for_quickdraw (f);
881 #endif
882 SetPortWindowPort (FRAME_MAC_WINDOW (f));
884 SetRect (&r, x, y, x + width, y + height);
886 InvertRect (&r);
890 static void
891 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, bytes_per_char)
892 struct frame *f;
893 GC gc;
894 int x, y;
895 char *buf;
896 int nchars, bg_width, bytes_per_char;
898 SetPortWindowPort (FRAME_MAC_WINDOW (f));
900 #if USE_ATSUI
901 if (GC_FONT (gc)->mac_style)
903 OSErr err;
904 ATSUTextLayout text_layout;
906 xassert (bytes_per_char == 2);
908 #ifndef WORDS_BIG_ENDIAN
910 int i;
911 UniChar *text = (UniChar *)buf;
913 for (i = 0; i < nchars; i++)
914 text[i] = EndianU16_BtoN (text[i]);
916 #endif
917 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
918 nchars,
919 GC_FONT (gc)->mac_style,
920 &text_layout);
921 if (err != noErr)
922 return;
923 #ifdef MAC_OSX
924 if (!mac_use_core_graphics)
926 #endif
927 #if USE_CG_DRAWING
928 mac_prepare_for_quickdraw (f);
929 #endif
930 mac_begin_clip (gc);
931 RGBForeColor (GC_FORE_COLOR (gc));
932 if (bg_width)
934 Rect r;
936 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
937 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
938 RGBBackColor (GC_BACK_COLOR (gc));
939 EraseRect (&r);
940 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
942 MoveTo (x, y);
943 ATSUDrawText (text_layout,
944 kATSUFromTextBeginning, kATSUToTextEnd,
945 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
946 mac_end_clip (gc);
947 #ifdef MAC_OSX
949 else
951 CGrafPtr port;
952 CGContextRef context;
953 float port_height = FRAME_PIXEL_HEIGHT (f);
954 ATSUAttributeTag tags[] = {kATSUCGContextTag};
955 ByteCount sizes[] = {sizeof (CGContextRef)};
956 ATSUAttributeValuePtr values[] = {&context};
958 #if USE_CG_DRAWING
959 context = mac_begin_cg_clip (f, gc);
960 #else
961 GetPort (&port);
962 QDBeginCGContext (port, &context);
963 if (gc->n_clip_rects || bg_width)
965 CGContextTranslateCTM (context, 0, port_height);
966 CGContextScaleCTM (context, 1, -1);
967 if (gc->n_clip_rects)
968 CGContextClipToRects (context, gc->clip_rects,
969 gc->n_clip_rects);
970 #endif
971 if (bg_width)
973 CG_SET_FILL_COLOR (context, gc->xgcv.background);
974 CGContextFillRect
975 (context,
976 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)),
977 bg_width, FONT_HEIGHT (GC_FONT (gc))));
979 CGContextScaleCTM (context, 1, -1);
980 CGContextTranslateCTM (context, 0, -port_height);
981 #if !USE_CG_DRAWING
983 #endif
984 CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
985 err = ATSUSetLayoutControls (text_layout,
986 sizeof (tags) / sizeof (tags[0]),
987 tags, sizes, values);
988 if (err == noErr)
989 ATSUDrawText (text_layout,
990 kATSUFromTextBeginning, kATSUToTextEnd,
991 Long2Fix (x), Long2Fix (port_height - y));
992 #if USE_CG_DRAWING
993 mac_end_cg_clip (f);
994 context = NULL;
995 #else
996 CGContextSynchronize (context);
997 QDEndCGContext (port, &context);
998 #endif
999 #if 0
1000 /* This doesn't work on Mac OS X 10.1. */
1001 ATSUClearLayoutControls (text_layout,
1002 sizeof (tags) / sizeof (tags[0]), tags);
1003 #else
1004 ATSUSetLayoutControls (text_layout,
1005 sizeof (tags) / sizeof (tags[0]),
1006 tags, sizes, values);
1007 #endif
1009 #endif /* MAC_OSX */
1011 else
1012 #endif /* USE_ATSUI */
1014 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1015 UInt32 savedFlags;
1017 if (mac_use_core_graphics)
1018 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering);
1019 #endif
1020 #if USE_CG_DRAWING
1021 mac_prepare_for_quickdraw (f);
1022 #endif
1023 mac_begin_clip (gc);
1024 RGBForeColor (GC_FORE_COLOR (gc));
1025 #ifdef MAC_OS8
1026 if (bg_width)
1028 RGBBackColor (GC_BACK_COLOR (gc));
1029 TextMode (srcCopy);
1031 else
1032 TextMode (srcOr);
1033 #else
1034 /* We prefer not to use srcCopy text transfer mode on Mac OS X
1035 because:
1036 - Screen is double-buffered. (In srcCopy mode, a text is
1037 drawn into an offscreen graphics world first. So
1038 performance gain cannot be expected.)
1039 - It lowers rendering quality.
1040 - Some fonts leave garbage on cursor movement. */
1041 if (bg_width)
1043 Rect r;
1045 RGBBackColor (GC_BACK_COLOR (gc));
1046 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)),
1047 x + bg_width, y + FONT_DESCENT (GC_FONT (gc)));
1048 EraseRect (&r);
1050 TextMode (srcOr);
1051 #endif
1052 TextFont (GC_FONT (gc)->mac_fontnum);
1053 TextSize (GC_FONT (gc)->mac_fontsize);
1054 TextFace (GC_FONT (gc)->mac_fontface);
1055 MoveTo (x, y);
1056 DrawText (buf, 0, nchars * bytes_per_char);
1057 if (bg_width)
1058 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1059 mac_end_clip (gc);
1061 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1062 if (mac_use_core_graphics)
1063 SwapQDTextFlags(savedFlags);
1064 #endif
1069 /* Mac replacement for XDrawString. */
1071 static void
1072 mac_draw_string (f, gc, x, y, buf, nchars)
1073 struct frame *f;
1074 GC gc;
1075 int x, y;
1076 char *buf;
1077 int nchars;
1079 mac_draw_string_common (f, gc, x, y, buf, nchars, 0, 1);
1083 /* Mac replacement for XDrawString16. */
1085 static void
1086 mac_draw_string_16 (f, gc, x, y, buf, nchars)
1087 struct frame *f;
1088 GC gc;
1089 int x, y;
1090 XChar2b *buf;
1091 int nchars;
1093 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, 0, 2);
1097 /* Mac replacement for XDrawImageString. */
1099 static void
1100 mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width)
1101 struct frame *f;
1102 GC gc;
1103 int x, y;
1104 char *buf;
1105 int nchars, bg_width;
1107 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 1);
1111 /* Mac replacement for XDrawString16. */
1113 static void
1114 mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width)
1115 struct frame *f;
1116 GC gc;
1117 int x, y;
1118 XChar2b *buf;
1119 int nchars, bg_width;
1121 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width, 2);
1125 /* Mac replacement for XQueryTextExtents, but takes a character. If
1126 STYLE is NULL, measurement is done by QuickDraw Text routines for
1127 the font of the current graphics port. If CG_GLYPH is not NULL,
1128 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
1130 static OSErr
1131 mac_query_char_extents (style, c,
1132 font_ascent_return, font_descent_return,
1133 overall_return, cg_glyph)
1134 #if USE_ATSUI
1135 ATSUStyle style;
1136 #else
1137 void *style;
1138 #endif
1139 int c;
1140 int *font_ascent_return, *font_descent_return;
1141 XCharStruct *overall_return;
1142 #if USE_CG_TEXT_DRAWING
1143 CGGlyph *cg_glyph;
1144 #else
1145 void *cg_glyph;
1146 #endif
1148 OSErr err = noErr;
1149 int width;
1150 Rect char_bounds;
1152 #if USE_ATSUI
1153 if (style)
1155 ATSUTextLayout text_layout;
1156 UniChar ch = c;
1158 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
1159 if (err == noErr)
1161 ATSTrapezoid glyph_bounds;
1163 err = ATSUGetGlyphBounds (text_layout, 0, 0,
1164 kATSUFromTextBeginning, kATSUToTextEnd,
1165 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1166 kATSUseFractionalOrigins,
1167 #else
1168 kATSUseDeviceOrigins,
1169 #endif
1170 1, &glyph_bounds, NULL);
1171 if (err == noErr)
1173 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
1174 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
1176 width = Fix2Long (glyph_bounds.upperRight.x
1177 - glyph_bounds.upperLeft.x);
1178 if (font_ascent_return)
1179 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
1180 if (font_descent_return)
1181 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
1184 if (err == noErr && overall_return)
1186 err = ATSUMeasureTextImage (text_layout,
1187 kATSUFromTextBeginning, kATSUToTextEnd,
1188 0, 0, &char_bounds);
1189 if (err == noErr)
1190 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1191 #if USE_CG_TEXT_DRAWING
1192 if (err == noErr && cg_glyph)
1194 OSErr err1;
1195 ATSUGlyphInfoArray glyph_info_array;
1196 ByteCount count = sizeof (ATSUGlyphInfoArray);
1198 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
1199 kATSUToTextEnd, NULL, NULL, NULL);
1200 if (err1 == noErr)
1201 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
1202 kATSUToTextEnd, &count,
1203 &glyph_info_array);
1204 if (err1 == noErr)
1206 xassert (glyph_info_array.glyphs[0].glyphID);
1207 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
1209 else
1210 *cg_glyph = 0;
1212 #endif
1215 else
1216 #endif
1218 if (font_ascent_return || font_descent_return)
1220 FontInfo font_info;
1222 GetFontInfo (&font_info);
1223 if (font_ascent_return)
1224 *font_ascent_return = font_info.ascent;
1225 if (font_descent_return)
1226 *font_descent_return = font_info.descent;
1228 if (overall_return)
1230 char ch = c;
1232 width = CharWidth (ch);
1233 QDTextBounds (1, &ch, &char_bounds);
1234 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
1238 return err;
1242 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1244 static int
1245 mac_text_extents_16 (font_struct, string, nchars, overall_return)
1246 XFontStruct *font_struct;
1247 XChar2b *string;
1248 int nchars;
1249 XCharStruct *overall_return;
1251 int i;
1252 short width = 0, lbearing = 0, rbearing = 0;
1253 XCharStruct *pcm;
1255 for (i = 0; i < nchars; i++)
1257 pcm = mac_per_char_metric (font_struct, string, 0);
1258 if (pcm == NULL)
1259 width += FONT_WIDTH (font_struct);
1260 else
1262 lbearing = min (lbearing, width + pcm->lbearing);
1263 rbearing = max (rbearing, width + pcm->rbearing);
1264 width += pcm->width;
1266 string++;
1269 overall_return->lbearing = lbearing;
1270 overall_return->rbearing = rbearing;
1271 overall_return->width = width;
1273 /* What's the meaning of the return value of XTextExtents16? */
1277 #if USE_CG_TEXT_DRAWING
1278 static int cg_text_anti_aliasing_threshold = 8;
1280 static void
1281 init_cg_text_anti_aliasing_threshold ()
1283 int threshold;
1284 Boolean valid_p;
1286 threshold =
1287 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1288 kCFPreferencesCurrentApplication,
1289 &valid_p);
1290 if (valid_p)
1291 cg_text_anti_aliasing_threshold = threshold;
1294 static int
1295 mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width)
1296 struct frame *f;
1297 GC gc;
1298 int x, y;
1299 XChar2b *buf;
1300 int nchars, bg_width;
1302 CGrafPtr port;
1303 float port_height, gx, gy;
1304 int i;
1305 CGContextRef context;
1306 CGGlyph *glyphs;
1307 CGSize *advances;
1309 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1310 return 0;
1312 port = GetWindowPort (FRAME_MAC_WINDOW (f));
1313 port_height = FRAME_PIXEL_HEIGHT (f);
1314 gx = x;
1315 gy = port_height - y;
1316 glyphs = (CGGlyph *)buf;
1317 advances = alloca (sizeof (CGSize) * nchars);
1318 if (advances == NULL)
1319 return 0;
1320 for (i = 0; i < nchars; i++)
1322 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1324 advances[i].width = pcm->width;
1325 advances[i].height = 0;
1326 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1327 buf++;
1330 #if USE_CG_DRAWING
1331 context = mac_begin_cg_clip (f, gc);
1332 #else
1333 QDBeginCGContext (port, &context);
1334 if (gc->n_clip_rects || bg_width)
1336 CGContextTranslateCTM (context, 0, port_height);
1337 CGContextScaleCTM (context, 1, -1);
1338 if (gc->n_clip_rects)
1339 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1340 #endif
1341 if (bg_width)
1343 CG_SET_FILL_COLOR (context, gc->xgcv.background);
1344 CGContextFillRect
1345 (context,
1346 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)),
1347 bg_width, FONT_HEIGHT (GC_FONT (gc))));
1349 CGContextScaleCTM (context, 1, -1);
1350 CGContextTranslateCTM (context, 0, -port_height);
1351 #if !USE_CG_DRAWING
1353 #endif
1354 CG_SET_FILL_COLOR (context, gc->xgcv.foreground);
1355 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1356 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1357 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1358 CGContextSetShouldAntialias (context, false);
1359 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1360 CGContextSetTextPosition (context, gx, gy);
1361 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1362 #else
1363 for (i = 0; i < nchars; i++)
1365 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1366 gx += advances[i].width;
1368 #endif
1369 #if USE_CG_DRAWING
1370 mac_end_cg_clip (f);
1371 #else
1372 CGContextSynchronize (context);
1373 QDEndCGContext (port, &context);
1374 #endif
1376 return 1;
1378 #endif
1381 #if !USE_CG_DRAWING
1382 /* Mac replacement for XCopyArea: dest must be window. */
1384 static void
1385 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1386 Pixmap src;
1387 struct frame *f;
1388 GC gc;
1389 int src_x, src_y;
1390 unsigned int width, height;
1391 int dest_x, dest_y;
1393 Rect src_r, dest_r;
1395 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1397 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1398 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1400 ForeColor (blackColor);
1401 BackColor (whiteColor);
1403 mac_begin_clip (gc);
1404 LockPixels (GetGWorldPixMap (src));
1405 #if TARGET_API_MAC_CARBON
1407 CGrafPtr port;
1409 GetPort (&port);
1410 LockPortBits (port);
1411 CopyBits (GetPortBitMapForCopyBits (src),
1412 GetPortBitMapForCopyBits (port),
1413 &src_r, &dest_r, srcCopy, 0);
1414 UnlockPortBits (port);
1416 #else /* not TARGET_API_MAC_CARBON */
1417 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1418 &src_r, &dest_r, srcCopy, 0);
1419 #endif /* not TARGET_API_MAC_CARBON */
1420 UnlockPixels (GetGWorldPixMap (src));
1421 mac_end_clip (gc);
1423 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1427 static void
1428 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1429 width, height, dest_x, dest_y)
1430 Pixmap src, mask;
1431 struct frame *f;
1432 GC gc;
1433 int src_x, src_y;
1434 unsigned int width, height;
1435 int dest_x, dest_y;
1437 Rect src_r, dest_r;
1439 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1441 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1442 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1444 ForeColor (blackColor);
1445 BackColor (whiteColor);
1447 mac_begin_clip (gc);
1448 LockPixels (GetGWorldPixMap (src));
1449 LockPixels (GetGWorldPixMap (mask));
1450 #if TARGET_API_MAC_CARBON
1452 CGrafPtr port;
1454 GetPort (&port);
1455 LockPortBits (port);
1456 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1457 GetPortBitMapForCopyBits (port),
1458 &src_r, &src_r, &dest_r);
1459 UnlockPortBits (port);
1461 #else /* not TARGET_API_MAC_CARBON */
1462 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1463 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1464 #endif /* not TARGET_API_MAC_CARBON */
1465 UnlockPixels (GetGWorldPixMap (mask));
1466 UnlockPixels (GetGWorldPixMap (src));
1467 mac_end_clip (gc);
1469 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1471 #endif /* !USE_CG_DRAWING */
1474 /* Mac replacement for XCopyArea: used only for scrolling. */
1476 static void
1477 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1478 struct frame *f;
1479 GC gc;
1480 int src_x, src_y;
1481 unsigned int width, height;
1482 int dest_x, dest_y;
1484 #if TARGET_API_MAC_CARBON
1485 Rect src_r;
1486 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1488 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1489 #if USE_CG_DRAWING
1490 mac_prepare_for_quickdraw (f);
1491 #endif
1492 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1493 &src_r, dest_x - src_x, dest_y - src_y,
1494 kScrollWindowNoOptions, dummy);
1495 DisposeRgn (dummy);
1496 #else /* not TARGET_API_MAC_CARBON */
1497 Rect src_r, dest_r;
1498 WindowPtr w = FRAME_MAC_WINDOW (f);
1500 SetPort (w);
1502 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1503 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1505 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1506 color mapping in CopyBits. Otherwise, it will be slow. */
1507 ForeColor (blackColor);
1508 BackColor (whiteColor);
1509 mac_begin_clip (gc);
1510 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1511 mac_end_clip (gc);
1513 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1514 #endif /* not TARGET_API_MAC_CARBON */
1518 /* Mac replacement for XChangeGC. */
1520 static void
1521 XChangeGC (display, gc, mask, xgcv)
1522 Display *display;
1523 GC gc;
1524 unsigned long mask;
1525 XGCValues *xgcv;
1527 if (mask & GCForeground)
1528 XSetForeground (display, gc, xgcv->foreground);
1529 if (mask & GCBackground)
1530 XSetBackground (display, gc, xgcv->background);
1531 if (mask & GCFont)
1532 XSetFont (display, gc, xgcv->font);
1536 /* Mac replacement for XCreateGC. */
1539 XCreateGC (display, window, mask, xgcv)
1540 Display *display;
1541 Window window;
1542 unsigned long mask;
1543 XGCValues *xgcv;
1545 GC gc = xmalloc (sizeof (*gc));
1547 bzero (gc, sizeof (*gc));
1548 XChangeGC (display, gc, mask, xgcv);
1550 return gc;
1554 /* Used in xfaces.c. */
1556 void
1557 XFreeGC (display, gc)
1558 Display *display;
1559 GC gc;
1561 if (gc->clip_region)
1562 DisposeRgn (gc->clip_region);
1563 xfree (gc);
1567 /* Mac replacement for XGetGCValues. */
1569 static void
1570 XGetGCValues (display, gc, mask, xgcv)
1571 Display *display;
1572 GC gc;
1573 unsigned long mask;
1574 XGCValues *xgcv;
1576 if (mask & GCForeground)
1577 xgcv->foreground = gc->xgcv.foreground;
1578 if (mask & GCBackground)
1579 xgcv->background = gc->xgcv.background;
1580 if (mask & GCFont)
1581 xgcv->font = gc->xgcv.font;
1585 /* Mac replacement for XSetForeground. */
1587 void
1588 XSetForeground (display, gc, color)
1589 Display *display;
1590 GC gc;
1591 unsigned long color;
1593 if (gc->xgcv.foreground != color)
1595 gc->xgcv.foreground = color;
1596 gc->fore_color.red = RED16_FROM_ULONG (color);
1597 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1598 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1603 /* Mac replacement for XSetBackground. */
1605 void
1606 XSetBackground (display, gc, color)
1607 Display *display;
1608 GC gc;
1609 unsigned long color;
1611 if (gc->xgcv.background != color)
1613 gc->xgcv.background = color;
1614 gc->back_color.red = RED16_FROM_ULONG (color);
1615 gc->back_color.green = GREEN16_FROM_ULONG (color);
1616 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1621 /* Mac replacement for XSetFont. */
1623 static void
1624 XSetFont (display, gc, font)
1625 Display *display;
1626 GC gc;
1627 XFontStruct *font;
1629 gc->xgcv.font = font;
1633 /* Mac replacement for XSetClipRectangles. */
1635 static void
1636 mac_set_clip_rectangles (display, gc, rectangles, n)
1637 Display *display;
1638 GC gc;
1639 Rect *rectangles;
1640 int n;
1642 int i;
1644 xassert (n >= 0 && n <= MAX_CLIP_RECTS);
1646 gc->n_clip_rects = n;
1647 if (n > 0)
1649 if (gc->clip_region == NULL)
1650 gc->clip_region = NewRgn ();
1651 RectRgn (gc->clip_region, rectangles);
1652 if (n > 1)
1654 RgnHandle region = NewRgn ();
1656 for (i = 1; i < n; i++)
1658 RectRgn (region, rectangles + i);
1659 UnionRgn (gc->clip_region, region, gc->clip_region);
1661 DisposeRgn (region);
1664 #if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING)
1665 for (i = 0; i < n; i++)
1667 Rect *rect = rectangles + i;
1669 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1670 rect->right - rect->left,
1671 rect->bottom - rect->top);
1673 #endif
1677 /* Mac replacement for XSetClipMask. */
1679 static INLINE void
1680 mac_reset_clip_rectangles (display, gc)
1681 Display *display;
1682 GC gc;
1684 gc->n_clip_rects = 0;
1688 /* Mac replacement for XSetWindowBackground. */
1690 void
1691 XSetWindowBackground (display, w, color)
1692 Display *display;
1693 WindowPtr w;
1694 unsigned long color;
1696 #if !TARGET_API_MAC_CARBON
1697 AuxWinHandle aw_handle;
1698 CTabHandle ctab_handle;
1699 ColorSpecPtr ct_table;
1700 short ct_size;
1701 #endif
1702 RGBColor bg_color;
1704 bg_color.red = RED16_FROM_ULONG (color);
1705 bg_color.green = GREEN16_FROM_ULONG (color);
1706 bg_color.blue = BLUE16_FROM_ULONG (color);
1708 #if TARGET_API_MAC_CARBON
1709 SetWindowContentColor (w, &bg_color);
1710 #else
1711 if (GetAuxWin (w, &aw_handle))
1713 ctab_handle = (*aw_handle)->awCTable;
1714 HandToHand ((Handle *) &ctab_handle);
1715 ct_table = (*ctab_handle)->ctTable;
1716 ct_size = (*ctab_handle)->ctSize;
1717 while (ct_size > -1)
1719 if (ct_table->value == 0)
1721 ct_table->rgb = bg_color;
1722 CTabChanged (ctab_handle);
1723 SetWinColor (w, (WCTabHandle) ctab_handle);
1725 ct_size--;
1728 #endif
1731 /* Flush display of frame F, or of all frames if F is null. */
1733 static void
1734 x_flush (f)
1735 struct frame *f;
1737 #if TARGET_API_MAC_CARBON
1738 BLOCK_INPUT;
1739 #if USE_CG_DRAWING
1740 mac_prepare_for_quickdraw (f);
1741 #endif
1742 if (f)
1743 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1744 else
1745 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1746 UNBLOCK_INPUT;
1747 #endif
1751 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1752 Calls to XFlush should be unnecessary because the X output buffer
1753 is flushed automatically as needed by calls to XPending,
1754 XNextEvent, or XWindowEvent according to the XFlush man page.
1755 XTread_socket calls XPending. Removing XFlush improves
1756 performance. */
1758 #define XFlush(DISPLAY) (void) 0
1761 /* Return the struct mac_display_info corresponding to DPY. There's
1762 only one. */
1764 struct mac_display_info *
1765 mac_display_info_for_display (dpy)
1766 Display *dpy;
1768 return &one_mac_display_info;
1773 /***********************************************************************
1774 Starting and ending an update
1775 ***********************************************************************/
1777 /* Start an update of frame F. This function is installed as a hook
1778 for update_begin, i.e. it is called when update_begin is called.
1779 This function is called prior to calls to x_update_window_begin for
1780 each window being updated. */
1782 static void
1783 x_update_begin (f)
1784 struct frame *f;
1786 #if TARGET_API_MAC_CARBON
1787 /* During update of a frame, availability of input events is
1788 periodically checked with ReceiveNextEvent if
1789 redisplay-dont-pause is nil. That normally flushes window buffer
1790 changes for every check, and thus screen update looks waving even
1791 if no input is available. So we disable screen updates during
1792 update of a frame. */
1793 BLOCK_INPUT;
1794 DisableScreenUpdates ();
1795 UNBLOCK_INPUT;
1796 #endif
1800 /* Start update of window W. Set the global variable updated_window
1801 to the window being updated and set output_cursor to the cursor
1802 position of W. */
1804 static void
1805 x_update_window_begin (w)
1806 struct window *w;
1808 struct frame *f = XFRAME (WINDOW_FRAME (w));
1809 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1811 updated_window = w;
1812 set_output_cursor (&w->cursor);
1814 BLOCK_INPUT;
1816 if (f == display_info->mouse_face_mouse_frame)
1818 /* Don't do highlighting for mouse motion during the update. */
1819 display_info->mouse_face_defer = 1;
1821 /* If F needs to be redrawn, simply forget about any prior mouse
1822 highlighting. */
1823 if (FRAME_GARBAGED_P (f))
1824 display_info->mouse_face_window = Qnil;
1826 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1827 their mouse_face_p flag set, which means that they are always
1828 unequal to rows in a desired matrix which never have that
1829 flag set. So, rows containing mouse-face glyphs are never
1830 scrolled, and we don't have to switch the mouse highlight off
1831 here to prevent it from being scrolled. */
1833 /* Can we tell that this update does not affect the window
1834 where the mouse highlight is? If so, no need to turn off.
1835 Likewise, don't do anything if the frame is garbaged;
1836 in that case, the frame's current matrix that we would use
1837 is all wrong, and we will redisplay that line anyway. */
1838 if (!NILP (display_info->mouse_face_window)
1839 && w == XWINDOW (display_info->mouse_face_window))
1841 int i;
1843 for (i = 0; i < w->desired_matrix->nrows; ++i)
1844 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1845 break;
1847 if (i < w->desired_matrix->nrows)
1848 clear_mouse_face (display_info);
1850 #endif /* 0 */
1853 UNBLOCK_INPUT;
1857 /* Draw a vertical window border from (x,y0) to (x,y1) */
1859 static void
1860 mac_draw_vertical_window_border (w, x, y0, y1)
1861 struct window *w;
1862 int x, y0, y1;
1864 struct frame *f = XFRAME (WINDOW_FRAME (w));
1865 struct face *face;
1867 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1868 if (face)
1869 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1870 face->foreground);
1872 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1875 /* End update of window W (which is equal to updated_window).
1877 Draw vertical borders between horizontally adjacent windows, and
1878 display W's cursor if CURSOR_ON_P is non-zero.
1880 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1881 glyphs in mouse-face were overwritten. In that case we have to
1882 make sure that the mouse-highlight is properly redrawn.
1884 W may be a menu bar pseudo-window in case we don't have X toolkit
1885 support. Such windows don't have a cursor, so don't display it
1886 here. */
1888 static void
1889 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1890 struct window *w;
1891 int cursor_on_p, mouse_face_overwritten_p;
1893 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1895 if (!w->pseudo_window_p)
1897 BLOCK_INPUT;
1899 if (cursor_on_p)
1900 display_and_set_cursor (w, 1, output_cursor.hpos,
1901 output_cursor.vpos,
1902 output_cursor.x, output_cursor.y);
1904 if (draw_window_fringes (w, 1))
1905 x_draw_vertical_border (w);
1907 UNBLOCK_INPUT;
1910 /* If a row with mouse-face was overwritten, arrange for
1911 XTframe_up_to_date to redisplay the mouse highlight. */
1912 if (mouse_face_overwritten_p)
1914 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1915 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1916 dpyinfo->mouse_face_window = Qnil;
1919 updated_window = NULL;
1923 /* End update of frame F. This function is installed as a hook in
1924 update_end. */
1926 static void
1927 x_update_end (f)
1928 struct frame *f;
1930 /* Mouse highlight may be displayed again. */
1931 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1933 BLOCK_INPUT;
1934 #if TARGET_API_MAC_CARBON
1935 EnableScreenUpdates ();
1936 #endif
1937 XFlush (FRAME_MAC_DISPLAY (f));
1938 UNBLOCK_INPUT;
1942 /* This function is called from various places in xdisp.c whenever a
1943 complete update has been performed. The global variable
1944 updated_window is not available here. */
1946 static void
1947 XTframe_up_to_date (f)
1948 struct frame *f;
1950 if (FRAME_MAC_P (f))
1952 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1954 if (dpyinfo->mouse_face_deferred_gc
1955 || f == dpyinfo->mouse_face_mouse_frame)
1957 BLOCK_INPUT;
1958 if (dpyinfo->mouse_face_mouse_frame)
1959 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1960 dpyinfo->mouse_face_mouse_x,
1961 dpyinfo->mouse_face_mouse_y);
1962 dpyinfo->mouse_face_deferred_gc = 0;
1963 UNBLOCK_INPUT;
1969 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1970 arrow bitmaps, or clear the fringes if no bitmaps are required
1971 before DESIRED_ROW is made current. The window being updated is
1972 found in updated_window. This function is called from
1973 update_window_line only if it is known that there are differences
1974 between bitmaps to be drawn between current row and DESIRED_ROW. */
1976 static void
1977 x_after_update_window_line (desired_row)
1978 struct glyph_row *desired_row;
1980 struct window *w = updated_window;
1981 struct frame *f;
1982 int width, height;
1984 xassert (w);
1986 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1987 desired_row->redraw_fringe_bitmaps_p = 1;
1989 /* When a window has disappeared, make sure that no rest of
1990 full-width rows stays visible in the internal border. Could
1991 check here if updated_window is the leftmost/rightmost window,
1992 but I guess it's not worth doing since vertically split windows
1993 are almost never used, internal border is rarely set, and the
1994 overhead is very small. */
1995 if (windows_or_buffers_changed
1996 && desired_row->full_width_p
1997 && (f = XFRAME (w->frame),
1998 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1999 width != 0)
2000 && (height = desired_row->visible_height,
2001 height > 0))
2003 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2005 /* Internal border is drawn below the tool bar. */
2006 if (WINDOWP (f->tool_bar_window)
2007 && w == XWINDOW (f->tool_bar_window))
2008 y -= width;
2010 BLOCK_INPUT;
2011 mac_clear_area (f, 0, y, width, height);
2012 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
2013 UNBLOCK_INPUT;
2018 /* Draw the bitmap WHICH in one of the left or right fringes of
2019 window W. ROW is the glyph row for which to display the bitmap; it
2020 determines the vertical position at which the bitmap has to be
2021 drawn. */
2023 static void
2024 x_draw_fringe_bitmap (w, row, p)
2025 struct window *w;
2026 struct glyph_row *row;
2027 struct draw_fringe_bitmap_params *p;
2029 struct frame *f = XFRAME (WINDOW_FRAME (w));
2030 Display *display = FRAME_MAC_DISPLAY (f);
2031 struct face *face = p->face;
2032 int rowY;
2034 /* Must clip because of partially visible lines. */
2035 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2036 if (p->y < rowY)
2038 /* Adjust position of "bottom aligned" bitmap on partially
2039 visible last row. */
2040 int oldY = row->y;
2041 int oldVH = row->visible_height;
2042 row->visible_height = p->h;
2043 row->y -= rowY - p->y;
2044 x_clip_to_row (w, row, -1, face->gc);
2045 row->y = oldY;
2046 row->visible_height = oldVH;
2048 else
2049 x_clip_to_row (w, row, -1, face->gc);
2051 if (p->bx >= 0 && !p->overlay_p)
2053 #if 0 /* MAC_TODO: stipple */
2054 /* In case the same realized face is used for fringes and
2055 for something displayed in the text (e.g. face `region' on
2056 mono-displays, the fill style may have been changed to
2057 FillSolid in x_draw_glyph_string_background. */
2058 if (face->stipple)
2059 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
2060 else
2061 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
2062 #endif
2064 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
2066 #if 0 /* MAC_TODO: stipple */
2067 if (!face->stipple)
2068 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
2069 #endif
2072 if (p->which
2073 #if USE_CG_DRAWING
2074 && p->which < max_fringe_bmp
2075 #endif
2078 XGCValues gcv;
2080 XGetGCValues (display, face->gc, GCForeground, &gcv);
2081 XSetForeground (display, face->gc,
2082 (p->cursor_p
2083 ? (p->overlay_p ? face->background
2084 : f->output_data.mac->cursor_pixel)
2085 : face->foreground));
2086 #if USE_CG_DRAWING
2087 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh,
2088 p->wd, p->h, p->x, p->y, p->overlay_p);
2089 #else
2090 mac_draw_bitmap (f, face->gc, p->x, p->y,
2091 p->wd, p->h, p->bits + p->dh, p->overlay_p);
2092 #endif
2093 XSetForeground (display, face->gc, gcv.foreground);
2096 mac_reset_clip_rectangles (display, face->gc);
2099 #if USE_CG_DRAWING
2100 static void
2101 mac_define_fringe_bitmap (which, bits, h, wd)
2102 int which;
2103 unsigned short *bits;
2104 int h, wd;
2106 int i;
2107 CGDataProviderRef provider;
2109 if (which >= max_fringe_bmp)
2111 i = max_fringe_bmp;
2112 max_fringe_bmp = which + 20;
2113 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef));
2114 while (i < max_fringe_bmp)
2115 fringe_bmp[i++] = 0;
2118 for (i = 0; i < h; i++)
2119 bits[i] = ~bits[i];
2120 provider = CGDataProviderCreateWithData (NULL, bits,
2121 sizeof (unsigned short) * h, NULL);
2122 if (provider)
2124 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1,
2125 sizeof (unsigned short),
2126 provider, NULL, 0);
2127 CGDataProviderRelease (provider);
2131 static void
2132 mac_destroy_fringe_bitmap (which)
2133 int which;
2135 if (which >= max_fringe_bmp)
2136 return;
2138 if (fringe_bmp[which])
2139 CGImageRelease (fringe_bmp[which]);
2140 fringe_bmp[which] = 0;
2142 #endif
2145 /* This is called when starting Emacs and when restarting after
2146 suspend. When starting Emacs, no window is mapped. And nothing
2147 must be done to Emacs's own window if it is suspended (though that
2148 rarely happens). */
2150 static void
2151 XTset_terminal_modes ()
2155 /* This is called when exiting or suspending Emacs. Exiting will make
2156 the windows go away, and suspending requires no action. */
2158 static void
2159 XTreset_terminal_modes ()
2165 /***********************************************************************
2166 Display Iterator
2167 ***********************************************************************/
2169 /* Function prototypes of this page. */
2171 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
2172 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
2175 static void
2176 pcm_init (pcm, count)
2177 XCharStruct *pcm;
2178 int count;
2180 bzero (pcm, sizeof (XCharStruct) * count);
2181 while (--count >= 0)
2183 pcm->descent = PCM_INVALID;
2184 pcm++;
2188 static enum pcm_status
2189 pcm_get_status (pcm)
2190 XCharStruct *pcm;
2192 int height = pcm->ascent + pcm->descent;
2194 /* Negative height means some special status. */
2195 return height >= 0 ? PCM_VALID : height;
2198 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
2199 is not contained in the font. */
2201 static INLINE XCharStruct *
2202 x_per_char_metric (font, char2b)
2203 XFontStruct *font;
2204 XChar2b *char2b;
2206 /* The result metric information. */
2207 XCharStruct *pcm = NULL;
2209 xassert (font && char2b);
2211 #if USE_ATSUI
2212 if (font->mac_style)
2214 XCharStruct **row = font->bounds.rows + char2b->byte1;
2216 if (*row == NULL)
2218 *row = xmalloc (sizeof (XCharStruct) * 0x100);
2219 pcm_init (*row, 0x100);
2221 pcm = *row + char2b->byte2;
2222 if (pcm_get_status (pcm) != PCM_VALID)
2224 BLOCK_INPUT;
2225 mac_query_char_extents (font->mac_style,
2226 (char2b->byte1 << 8) + char2b->byte2,
2227 NULL, NULL, pcm, NULL);
2228 UNBLOCK_INPUT;
2231 else
2233 #endif
2234 if (font->bounds.per_char != NULL)
2236 if (font->min_byte1 == 0 && font->max_byte1 == 0)
2238 /* min_char_or_byte2 specifies the linear character index
2239 corresponding to the first element of the per_char array,
2240 max_char_or_byte2 is the index of the last character. A
2241 character with non-zero CHAR2B->byte1 is not in the font.
2242 A character with byte2 less than min_char_or_byte2 or
2243 greater max_char_or_byte2 is not in the font. */
2244 if (char2b->byte1 == 0
2245 && char2b->byte2 >= font->min_char_or_byte2
2246 && char2b->byte2 <= font->max_char_or_byte2)
2247 pcm = font->bounds.per_char
2248 + (char2b->byte2 - font->min_char_or_byte2);
2250 else
2252 /* If either min_byte1 or max_byte1 are nonzero, both
2253 min_char_or_byte2 and max_char_or_byte2 are less than
2254 256, and the 2-byte character index values corresponding
2255 to the per_char array element N (counting from 0) are:
2257 byte1 = N/D + min_byte1
2258 byte2 = N\D + min_char_or_byte2
2260 where:
2262 D = max_char_or_byte2 - min_char_or_byte2 + 1
2263 / = integer division
2264 \ = integer modulus */
2265 if (char2b->byte1 >= font->min_byte1
2266 && char2b->byte1 <= font->max_byte1
2267 && char2b->byte2 >= font->min_char_or_byte2
2268 && char2b->byte2 <= font->max_char_or_byte2)
2270 pcm = (font->bounds.per_char
2271 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
2272 * (char2b->byte1 - font->min_byte1))
2273 + (char2b->byte2 - font->min_char_or_byte2));
2277 else
2279 /* If the per_char pointer is null, all glyphs between the first
2280 and last character indexes inclusive have the same
2281 information, as given by both min_bounds and max_bounds. */
2282 if (char2b->byte2 >= font->min_char_or_byte2
2283 && char2b->byte2 <= font->max_char_or_byte2)
2284 pcm = &font->max_bounds;
2286 #if USE_ATSUI
2288 #endif
2290 return ((pcm == NULL
2291 || (pcm->width == 0
2292 #if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */
2293 && (pcm->rbearing - pcm->lbearing) == 0
2294 #endif
2296 ? NULL : pcm);
2299 /* RIF:
2302 static XCharStruct *
2303 mac_per_char_metric (font, char2b, font_type)
2304 XFontStruct *font;
2305 XChar2b *char2b;
2306 int font_type;
2308 return x_per_char_metric (font, char2b);
2311 /* RIF:
2312 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2313 the two-byte form of C. Encoding is returned in *CHAR2B. */
2315 static int
2316 mac_encode_char (c, char2b, font_info, two_byte_p)
2317 int c;
2318 XChar2b *char2b;
2319 struct font_info *font_info;
2320 int *two_byte_p;
2322 int charset = CHAR_CHARSET (c);
2323 XFontStruct *font = font_info->font;
2325 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2326 This may be either a program in a special encoder language or a
2327 fixed encoding. */
2328 if (font_info->font_encoder)
2330 /* It's a program. */
2331 struct ccl_program *ccl = font_info->font_encoder;
2333 check_ccl_update (ccl);
2334 if (CHARSET_DIMENSION (charset) == 1)
2336 ccl->reg[0] = charset;
2337 ccl->reg[1] = char2b->byte2;
2338 ccl->reg[2] = -1;
2340 else
2342 ccl->reg[0] = charset;
2343 ccl->reg[1] = char2b->byte1;
2344 ccl->reg[2] = char2b->byte2;
2347 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2349 /* We assume that MSBs are appropriately set/reset by CCL
2350 program. */
2351 if (font->max_byte1 == 0) /* 1-byte font */
2352 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2353 else
2354 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2356 else if (font_info->encoding[charset])
2358 /* Fixed encoding scheme. See fontset.h for the meaning of the
2359 encoding numbers. */
2360 int enc = font_info->encoding[charset];
2362 if ((enc == 1 || enc == 2)
2363 && CHARSET_DIMENSION (charset) == 2)
2364 char2b->byte1 |= 0x80;
2366 if (enc == 1 || enc == 3)
2367 char2b->byte2 |= 0x80;
2369 if (enc == 4)
2371 int sjis1, sjis2;
2373 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2374 char2b->byte1 = sjis1;
2375 char2b->byte2 = sjis2;
2379 if (two_byte_p)
2380 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2382 return FONT_TYPE_UNKNOWN;
2387 /***********************************************************************
2388 Glyph display
2389 ***********************************************************************/
2393 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2394 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2395 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2396 int));
2397 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2398 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2399 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2400 static void x_draw_glyph_string P_ ((struct glyph_string *));
2401 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2402 static void x_set_cursor_gc P_ ((struct glyph_string *));
2403 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2404 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2405 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2406 unsigned long *, double, int));*/
2407 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2408 double, int, unsigned long));
2409 static void x_setup_relief_colors P_ ((struct glyph_string *));
2410 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2411 static void x_draw_image_relief P_ ((struct glyph_string *));
2412 static void x_draw_image_foreground P_ ((struct glyph_string *));
2413 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2414 int, int, int));
2415 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2416 int, int, int, int, int, int,
2417 Rect *));
2418 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2419 int, int, int, Rect *));
2421 #if GLYPH_DEBUG
2422 static void x_check_font P_ ((struct frame *, XFontStruct *));
2423 #endif
2426 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2427 face. */
2429 static void
2430 x_set_cursor_gc (s)
2431 struct glyph_string *s;
2433 if (s->font == FRAME_FONT (s->f)
2434 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2435 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2436 && !s->cmp)
2437 s->gc = s->f->output_data.mac->cursor_gc;
2438 else
2440 /* Cursor on non-default face: must merge. */
2441 XGCValues xgcv;
2442 unsigned long mask;
2444 xgcv.background = s->f->output_data.mac->cursor_pixel;
2445 xgcv.foreground = s->face->background;
2447 /* If the glyph would be invisible, try a different foreground. */
2448 if (xgcv.foreground == xgcv.background)
2449 xgcv.foreground = s->face->foreground;
2450 if (xgcv.foreground == xgcv.background)
2451 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2452 if (xgcv.foreground == xgcv.background)
2453 xgcv.foreground = s->face->foreground;
2455 /* Make sure the cursor is distinct from text in this face. */
2456 if (xgcv.background == s->face->background
2457 && xgcv.foreground == s->face->foreground)
2459 xgcv.background = s->face->foreground;
2460 xgcv.foreground = s->face->background;
2463 IF_DEBUG (x_check_font (s->f, s->font));
2464 xgcv.font = s->font;
2465 mask = GCForeground | GCBackground | GCFont;
2467 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2468 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2469 mask, &xgcv);
2470 else
2471 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2472 = XCreateGC (s->display, s->window, mask, &xgcv);
2474 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2479 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2481 static void
2482 x_set_mouse_face_gc (s)
2483 struct glyph_string *s;
2485 int face_id;
2486 struct face *face;
2488 /* What face has to be used last for the mouse face? */
2489 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2490 face = FACE_FROM_ID (s->f, face_id);
2491 if (face == NULL)
2492 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2494 if (s->first_glyph->type == CHAR_GLYPH)
2495 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2496 else
2497 face_id = FACE_FOR_CHAR (s->f, face, 0);
2498 s->face = FACE_FROM_ID (s->f, face_id);
2499 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2501 /* If font in this face is same as S->font, use it. */
2502 if (s->font == s->face->font)
2503 s->gc = s->face->gc;
2504 else
2506 /* Otherwise construct scratch_cursor_gc with values from FACE
2507 but font FONT. */
2508 XGCValues xgcv;
2509 unsigned long mask;
2511 xgcv.background = s->face->background;
2512 xgcv.foreground = s->face->foreground;
2513 IF_DEBUG (x_check_font (s->f, s->font));
2514 xgcv.font = s->font;
2515 mask = GCForeground | GCBackground | GCFont;
2517 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2518 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2519 mask, &xgcv);
2520 else
2521 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2522 = XCreateGC (s->display, s->window, mask, &xgcv);
2524 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2527 xassert (s->gc != 0);
2531 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2532 Faces to use in the mode line have already been computed when the
2533 matrix was built, so there isn't much to do, here. */
2535 static INLINE void
2536 x_set_mode_line_face_gc (s)
2537 struct glyph_string *s;
2539 s->gc = s->face->gc;
2543 /* Set S->gc of glyph string S for drawing that glyph string. Set
2544 S->stippled_p to a non-zero value if the face of S has a stipple
2545 pattern. */
2547 static INLINE void
2548 x_set_glyph_string_gc (s)
2549 struct glyph_string *s;
2551 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2553 if (s->hl == DRAW_NORMAL_TEXT)
2555 s->gc = s->face->gc;
2556 s->stippled_p = s->face->stipple != 0;
2558 else if (s->hl == DRAW_INVERSE_VIDEO)
2560 x_set_mode_line_face_gc (s);
2561 s->stippled_p = s->face->stipple != 0;
2563 else if (s->hl == DRAW_CURSOR)
2565 x_set_cursor_gc (s);
2566 s->stippled_p = 0;
2568 else if (s->hl == DRAW_MOUSE_FACE)
2570 x_set_mouse_face_gc (s);
2571 s->stippled_p = s->face->stipple != 0;
2573 else if (s->hl == DRAW_IMAGE_RAISED
2574 || s->hl == DRAW_IMAGE_SUNKEN)
2576 s->gc = s->face->gc;
2577 s->stippled_p = s->face->stipple != 0;
2579 else
2581 s->gc = s->face->gc;
2582 s->stippled_p = s->face->stipple != 0;
2585 /* GC must have been set. */
2586 xassert (s->gc != 0);
2590 /* Set clipping for output of glyph string S. S may be part of a mode
2591 line or menu if we don't have X toolkit support. */
2593 static INLINE void
2594 x_set_glyph_string_clipping (s)
2595 struct glyph_string *s;
2597 Rect rects[MAX_CLIP_RECTS];
2598 int n;
2600 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2601 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2605 /* RIF:
2606 Compute left and right overhang of glyph string S. If S is a glyph
2607 string for a composition, assume overhangs don't exist. */
2609 static void
2610 mac_compute_glyph_string_overhangs (s)
2611 struct glyph_string *s;
2613 if (!(s->cmp == NULL
2614 && s->first_glyph->type == CHAR_GLYPH))
2615 return;
2617 if (!s->two_byte_p
2618 #if USE_ATSUI
2619 || s->font->mac_style
2620 #endif
2623 XCharStruct cs;
2625 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2626 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2627 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2629 else
2631 Rect r;
2632 MacFontStruct *font = s->font;
2634 TextFont (font->mac_fontnum);
2635 TextSize (font->mac_fontsize);
2636 TextFace (font->mac_fontface);
2638 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2640 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2641 s->left_overhang = r.left < 0 ? -r.left : 0;
2646 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2648 static INLINE void
2649 x_clear_glyph_string_rect (s, x, y, w, h)
2650 struct glyph_string *s;
2651 int x, y, w, h;
2653 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2657 /* Draw the background of glyph_string S. If S->background_filled_p
2658 is non-zero don't draw it. FORCE_P non-zero means draw the
2659 background even if it wouldn't be drawn normally. This is used
2660 when a string preceding S draws into the background of S, or S
2661 contains the first component of a composition. */
2663 static void
2664 x_draw_glyph_string_background (s, force_p)
2665 struct glyph_string *s;
2666 int force_p;
2668 /* Nothing to do if background has already been drawn or if it
2669 shouldn't be drawn in the first place. */
2670 if (!s->background_filled_p)
2672 int box_line_width = max (s->face->box_line_width, 0);
2674 #if 0 /* MAC_TODO: stipple */
2675 if (s->stippled_p)
2677 /* Fill background with a stipple pattern. */
2678 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2679 XFillRectangle (s->display, s->window, s->gc, s->x,
2680 s->y + box_line_width,
2681 s->background_width,
2682 s->height - 2 * box_line_width);
2683 XSetFillStyle (s->display, s->gc, FillSolid);
2684 s->background_filled_p = 1;
2686 else
2687 #endif
2688 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2689 || s->font_not_found_p
2690 || s->extends_to_end_of_line_p
2691 || force_p)
2693 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2694 s->background_width,
2695 s->height - 2 * box_line_width);
2696 s->background_filled_p = 1;
2702 /* Draw the foreground of glyph string S. */
2704 static void
2705 x_draw_glyph_string_foreground (s)
2706 struct glyph_string *s;
2708 int i, x, bg_width;
2710 /* If first glyph of S has a left box line, start drawing the text
2711 of S to the right of that box line. */
2712 if (s->face->box != FACE_NO_BOX
2713 && s->first_glyph->left_box_line_p)
2714 x = s->x + abs (s->face->box_line_width);
2715 else
2716 x = s->x;
2718 /* Draw characters of S as rectangles if S's font could not be
2719 loaded. */
2720 if (s->font_not_found_p)
2722 for (i = 0; i < s->nchars; ++i)
2724 struct glyph *g = s->first_glyph + i;
2725 mac_draw_rectangle (s->f, s->gc, x, s->y,
2726 g->pixel_width - 1, s->height - 1);
2727 x += g->pixel_width;
2730 else
2732 char *char1b = (char *) s->char2b;
2733 int boff = s->font_info->baseline_offset;
2735 if (s->font_info->vertical_centering)
2736 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2738 /* If we can use 8-bit functions, condense S->char2b. */
2739 if (!s->two_byte_p
2740 #if USE_ATSUI
2741 && GC_FONT (s->gc)->mac_style == NULL
2742 #endif
2744 for (i = 0; i < s->nchars; ++i)
2745 char1b[i] = s->char2b[i].byte2;
2747 /* Draw text with XDrawString if background has already been
2748 filled. Otherwise, use XDrawImageString. (Note that
2749 XDrawImageString is usually faster than XDrawString.) Always
2750 use XDrawImageString when drawing the cursor so that there is
2751 no chance that characters under a box cursor are invisible. */
2752 if (s->for_overlaps
2753 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2754 bg_width = 0; /* Corresponds to XDrawString. */
2755 else
2756 bg_width = s->background_width; /* Corresponds to XDrawImageString. */
2758 if (s->two_byte_p
2759 #if USE_ATSUI
2760 || GC_FONT (s->gc)->mac_style
2761 #endif
2763 #if USE_CG_TEXT_DRAWING
2764 if (!s->two_byte_p
2765 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff,
2766 s->char2b, s->nchars, bg_width))
2768 else
2769 #endif
2770 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2771 s->char2b, s->nchars, bg_width);
2772 else
2773 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2774 char1b, s->nchars, bg_width);
2778 /* Draw the foreground of composite glyph string S. */
2780 static void
2781 x_draw_composite_glyph_string_foreground (s)
2782 struct glyph_string *s;
2784 int i, x;
2786 /* If first glyph of S has a left box line, start drawing the text
2787 of S to the right of that box line. */
2788 if (s->face->box != FACE_NO_BOX
2789 && s->first_glyph->left_box_line_p)
2790 x = s->x + abs (s->face->box_line_width);
2791 else
2792 x = s->x;
2794 /* S is a glyph string for a composition. S->gidx is the index of
2795 the first character drawn for glyphs of this composition.
2796 S->gidx == 0 means we are drawing the very first character of
2797 this composition. */
2799 /* Draw a rectangle for the composition if the font for the very
2800 first character of the composition could not be loaded. */
2801 if (s->font_not_found_p)
2803 if (s->gidx == 0)
2804 mac_draw_rectangle (s->f, s->gc, x, s->y,
2805 s->width - 1, s->height - 1);
2807 else
2809 for (i = 0; i < s->nchars; i++, ++s->gidx)
2810 mac_draw_string_16 (s->f, s->gc,
2811 x + s->cmp->offsets[s->gidx * 2],
2812 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2813 s->char2b + i, 1);
2818 #ifdef USE_X_TOOLKIT
2820 static struct frame *x_frame_of_widget P_ ((Widget));
2823 /* Return the frame on which widget WIDGET is used.. Abort if frame
2824 cannot be determined. */
2826 static struct frame *
2827 x_frame_of_widget (widget)
2828 Widget widget;
2830 struct x_display_info *dpyinfo;
2831 Lisp_Object tail;
2832 struct frame *f;
2834 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2836 /* Find the top-level shell of the widget. Note that this function
2837 can be called when the widget is not yet realized, so XtWindow
2838 (widget) == 0. That's the reason we can't simply use
2839 x_any_window_to_frame. */
2840 while (!XtIsTopLevelShell (widget))
2841 widget = XtParent (widget);
2843 /* Look for a frame with that top-level widget. Allocate the color
2844 on that frame to get the right gamma correction value. */
2845 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2846 if (GC_FRAMEP (XCAR (tail))
2847 && (f = XFRAME (XCAR (tail)),
2848 (f->output_data.nothing != 1
2849 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2850 && f->output_data.x->widget == widget)
2851 return f;
2853 abort ();
2857 /* Allocate the color COLOR->pixel on the screen and display of
2858 widget WIDGET in colormap CMAP. If an exact match cannot be
2859 allocated, try the nearest color available. Value is non-zero
2860 if successful. This is called from lwlib. */
2863 x_alloc_nearest_color_for_widget (widget, cmap, color)
2864 Widget widget;
2865 Colormap cmap;
2866 XColor *color;
2868 struct frame *f = x_frame_of_widget (widget);
2869 return x_alloc_nearest_color (f, cmap, color);
2873 #endif /* USE_X_TOOLKIT */
2875 #if 0 /* MAC_TODO */
2877 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2878 CMAP. If an exact match can't be allocated, try the nearest color
2879 available. Value is non-zero if successful. Set *COLOR to the
2880 color allocated. */
2883 x_alloc_nearest_color (f, cmap, color)
2884 struct frame *f;
2885 Colormap cmap;
2886 XColor *color;
2888 Display *display = FRAME_X_DISPLAY (f);
2889 Screen *screen = FRAME_X_SCREEN (f);
2890 int rc;
2892 gamma_correct (f, color);
2893 rc = XAllocColor (display, cmap, color);
2894 if (rc == 0)
2896 /* If we got to this point, the colormap is full, so we're going
2897 to try to get the next closest color. The algorithm used is
2898 a least-squares matching, which is what X uses for closest
2899 color matching with StaticColor visuals. */
2900 int nearest, i;
2901 unsigned long nearest_delta = ~0;
2902 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2903 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2905 for (i = 0; i < ncells; ++i)
2906 cells[i].pixel = i;
2907 XQueryColors (display, cmap, cells, ncells);
2909 for (nearest = i = 0; i < ncells; ++i)
2911 long dred = (color->red >> 8) - (cells[i].red >> 8);
2912 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2913 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2914 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2916 if (delta < nearest_delta)
2918 nearest = i;
2919 nearest_delta = delta;
2923 color->red = cells[nearest].red;
2924 color->green = cells[nearest].green;
2925 color->blue = cells[nearest].blue;
2926 rc = XAllocColor (display, cmap, color);
2929 #ifdef DEBUG_X_COLORS
2930 if (rc)
2931 register_color (color->pixel);
2932 #endif /* DEBUG_X_COLORS */
2934 return rc;
2938 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2939 It's necessary to do this instead of just using PIXEL directly to
2940 get color reference counts right. */
2942 unsigned long
2943 x_copy_color (f, pixel)
2944 struct frame *f;
2945 unsigned long pixel;
2947 XColor color;
2949 color.pixel = pixel;
2950 BLOCK_INPUT;
2951 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2952 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2953 UNBLOCK_INPUT;
2954 #ifdef DEBUG_X_COLORS
2955 register_color (pixel);
2956 #endif
2957 return color.pixel;
2961 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2962 It's necessary to do this instead of just using PIXEL directly to
2963 get color reference counts right. */
2965 unsigned long
2966 x_copy_dpy_color (dpy, cmap, pixel)
2967 Display *dpy;
2968 Colormap cmap;
2969 unsigned long pixel;
2971 XColor color;
2973 color.pixel = pixel;
2974 BLOCK_INPUT;
2975 XQueryColor (dpy, cmap, &color);
2976 XAllocColor (dpy, cmap, &color);
2977 UNBLOCK_INPUT;
2978 #ifdef DEBUG_X_COLORS
2979 register_color (pixel);
2980 #endif
2981 return color.pixel;
2984 #endif /* MAC_TODO */
2987 /* Brightness beyond which a color won't have its highlight brightness
2988 boosted.
2990 Nominally, highlight colors for `3d' faces are calculated by
2991 brightening an object's color by a constant scale factor, but this
2992 doesn't yield good results for dark colors, so for colors who's
2993 brightness is less than this value (on a scale of 0-255) have to
2994 use an additional additive factor.
2996 The value here is set so that the default menu-bar/mode-line color
2997 (grey75) will not have its highlights changed at all. */
2998 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3001 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3002 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3003 If this produces the same color as COLOR, try a color where all RGB
3004 values have DELTA added. Return the allocated color in *COLOR.
3005 DISPLAY is the X display, CMAP is the colormap to operate on.
3006 Value is non-zero if successful. */
3008 static int
3009 mac_alloc_lighter_color (f, color, factor, delta)
3010 struct frame *f;
3011 unsigned long *color;
3012 double factor;
3013 int delta;
3015 unsigned long new;
3016 long bright;
3018 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
3019 delta /= 256;
3021 /* Change RGB values by specified FACTOR. Avoid overflow! */
3022 xassert (factor >= 0);
3023 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
3024 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
3025 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
3027 /* Calculate brightness of COLOR. */
3028 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
3029 + BLUE_FROM_ULONG (*color)) / 6;
3031 /* We only boost colors that are darker than
3032 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3033 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3034 /* Make an additive adjustment to NEW, because it's dark enough so
3035 that scaling by FACTOR alone isn't enough. */
3037 /* How far below the limit this color is (0 - 1, 1 being darker). */
3038 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3039 /* The additive adjustment. */
3040 int min_delta = delta * dimness * factor / 2;
3042 if (factor < 1)
3043 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
3044 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
3045 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
3046 else
3047 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
3048 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
3049 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
3052 if (new == *color)
3053 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
3054 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
3055 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
3057 /* MAC_TODO: Map to palette and retry with delta if same? */
3058 /* MAC_TODO: Free colors (if using palette)? */
3060 if (new == *color)
3061 return 0;
3063 *color = new;
3065 return 1;
3069 /* Set up the foreground color for drawing relief lines of glyph
3070 string S. RELIEF is a pointer to a struct relief containing the GC
3071 with which lines will be drawn. Use a color that is FACTOR or
3072 DELTA lighter or darker than the relief's background which is found
3073 in S->f->output_data.x->relief_background. If such a color cannot
3074 be allocated, use DEFAULT_PIXEL, instead. */
3076 static void
3077 x_setup_relief_color (f, relief, factor, delta, default_pixel)
3078 struct frame *f;
3079 struct relief *relief;
3080 double factor;
3081 int delta;
3082 unsigned long default_pixel;
3084 XGCValues xgcv;
3085 struct mac_output *di = f->output_data.mac;
3086 unsigned long mask = GCForeground;
3087 unsigned long pixel;
3088 unsigned long background = di->relief_background;
3089 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
3091 /* MAC_TODO: Free colors (if using palette)? */
3093 /* Allocate new color. */
3094 xgcv.foreground = default_pixel;
3095 pixel = background;
3096 if (dpyinfo->n_planes != 1
3097 && mac_alloc_lighter_color (f, &pixel, factor, delta))
3099 relief->allocated_p = 1;
3100 xgcv.foreground = relief->pixel = pixel;
3103 if (relief->gc == 0)
3105 #if 0 /* MAC_TODO: stipple */
3106 xgcv.stipple = dpyinfo->gray;
3107 mask |= GCStipple;
3108 #endif
3109 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
3111 else
3112 XChangeGC (NULL, relief->gc, mask, &xgcv);
3116 /* Set up colors for the relief lines around glyph string S. */
3118 static void
3119 x_setup_relief_colors (s)
3120 struct glyph_string *s;
3122 struct mac_output *di = s->f->output_data.mac;
3123 unsigned long color;
3125 if (s->face->use_box_color_for_shadows_p)
3126 color = s->face->box_color;
3127 else if (s->first_glyph->type == IMAGE_GLYPH
3128 && s->img->pixmap
3129 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3130 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3131 else
3133 XGCValues xgcv;
3135 /* Get the background color of the face. */
3136 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3137 color = xgcv.background;
3140 if (di->white_relief.gc == 0
3141 || color != di->relief_background)
3143 di->relief_background = color;
3144 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3145 WHITE_PIX_DEFAULT (s->f));
3146 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3147 BLACK_PIX_DEFAULT (s->f));
3152 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3153 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3154 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3155 relief. LEFT_P non-zero means draw a relief on the left side of
3156 the rectangle. RIGHT_P non-zero means draw a relief on the right
3157 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3158 when drawing. */
3160 static void
3161 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3162 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
3163 struct frame *f;
3164 int left_x, top_y, right_x, bottom_y, width;
3165 int top_p, bot_p, left_p, right_p, raised_p;
3166 Rect *clip_rect;
3168 Display *dpy = FRAME_MAC_DISPLAY (f);
3169 int i;
3170 GC gc;
3172 if (raised_p)
3173 gc = f->output_data.mac->white_relief.gc;
3174 else
3175 gc = f->output_data.mac->black_relief.gc;
3176 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3178 /* Top. */
3179 if (top_p)
3180 for (i = 0; i < width; ++i)
3181 mac_draw_line (f, gc,
3182 left_x + i * left_p, top_y + i,
3183 right_x + 1 - i * right_p, top_y + i);
3185 /* Left. */
3186 if (left_p)
3187 for (i = 0; i < width; ++i)
3188 mac_draw_line (f, gc,
3189 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
3191 mac_reset_clip_rectangles (dpy, gc);
3192 if (raised_p)
3193 gc = f->output_data.mac->black_relief.gc;
3194 else
3195 gc = f->output_data.mac->white_relief.gc;
3196 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
3198 /* Bottom. */
3199 if (bot_p)
3200 for (i = 0; i < width; ++i)
3201 mac_draw_line (f, gc,
3202 left_x + i * left_p, bottom_y - i,
3203 right_x + 1 - i * right_p, bottom_y - i);
3205 /* Right. */
3206 if (right_p)
3207 for (i = 0; i < width; ++i)
3208 mac_draw_line (f, gc,
3209 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3211 mac_reset_clip_rectangles (dpy, gc);
3215 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3216 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3217 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3218 left side of the rectangle. RIGHT_P non-zero means draw a line
3219 on the right side of the rectangle. CLIP_RECT is the clipping
3220 rectangle to use when drawing. */
3222 static void
3223 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3224 left_p, right_p, clip_rect)
3225 struct glyph_string *s;
3226 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3227 Rect *clip_rect;
3229 XGCValues xgcv;
3231 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3232 XSetForeground (s->display, s->gc, s->face->box_color);
3233 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
3235 /* Top. */
3236 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3237 right_x - left_x + 1, width);
3239 /* Left. */
3240 if (left_p)
3241 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
3242 width, bottom_y - top_y + 1);
3244 /* Bottom. */
3245 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
3246 right_x - left_x + 1, width);
3248 /* Right. */
3249 if (right_p)
3250 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
3251 top_y, width, bottom_y - top_y + 1);
3253 XSetForeground (s->display, s->gc, xgcv.foreground);
3254 mac_reset_clip_rectangles (s->display, s->gc);
3258 /* Draw a box around glyph string S. */
3260 static void
3261 x_draw_glyph_string_box (s)
3262 struct glyph_string *s;
3264 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3265 int left_p, right_p;
3266 struct glyph *last_glyph;
3267 Rect clip_rect;
3269 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
3270 ? WINDOW_RIGHT_EDGE_X (s->w)
3271 : window_box_right (s->w, s->area));
3273 /* The glyph that may have a right box line. */
3274 last_glyph = (s->cmp || s->img
3275 ? s->first_glyph
3276 : s->first_glyph + s->nchars - 1);
3278 width = abs (s->face->box_line_width);
3279 raised_p = s->face->box == FACE_RAISED_BOX;
3280 left_x = s->x;
3281 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3282 ? last_x - 1
3283 : min (last_x, s->x + s->background_width) - 1);
3284 top_y = s->y;
3285 bottom_y = top_y + s->height - 1;
3287 left_p = (s->first_glyph->left_box_line_p
3288 || (s->hl == DRAW_MOUSE_FACE
3289 && (s->prev == NULL
3290 || s->prev->hl != s->hl)));
3291 right_p = (last_glyph->right_box_line_p
3292 || (s->hl == DRAW_MOUSE_FACE
3293 && (s->next == NULL
3294 || s->next->hl != s->hl)));
3296 get_glyph_string_clip_rect (s, &clip_rect);
3298 if (s->face->box == FACE_SIMPLE_BOX)
3299 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3300 left_p, right_p, &clip_rect);
3301 else
3303 x_setup_relief_colors (s);
3304 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3305 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
3310 /* Draw foreground of image glyph string S. */
3312 static void
3313 x_draw_image_foreground (s)
3314 struct glyph_string *s;
3316 int x = s->x;
3317 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3319 /* If first glyph of S has a left box line, start drawing it to the
3320 right of that line. */
3321 if (s->face->box != FACE_NO_BOX
3322 && s->first_glyph->left_box_line_p
3323 && s->slice.x == 0)
3324 x += abs (s->face->box_line_width);
3326 /* If there is a margin around the image, adjust x- and y-position
3327 by that margin. */
3328 if (s->slice.x == 0)
3329 x += s->img->hmargin;
3330 if (s->slice.y == 0)
3331 y += s->img->vmargin;
3333 if (s->img->pixmap)
3335 x_set_glyph_string_clipping (s);
3337 #if USE_CG_DRAWING
3338 mac_draw_cg_image (s->img->data.ptr_val,
3339 s->f, s->gc, s->slice.x, s->slice.y,
3340 s->slice.width, s->slice.height, x, y, 1);
3341 #endif
3342 if (s->img->mask)
3343 #if !USE_CG_DRAWING
3344 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3345 s->f, s->gc, s->slice.x, s->slice.y,
3346 s->slice.width, s->slice.height, x, y);
3347 #else
3349 #endif
3350 else
3352 #if !USE_CG_DRAWING
3353 mac_copy_area (s->img->pixmap,
3354 s->f, s->gc, s->slice.x, s->slice.y,
3355 s->slice.width, s->slice.height, x, y);
3356 #endif
3358 /* When the image has a mask, we can expect that at
3359 least part of a mouse highlight or a block cursor will
3360 be visible. If the image doesn't have a mask, make
3361 a block cursor visible by drawing a rectangle around
3362 the image. I believe it's looking better if we do
3363 nothing here for mouse-face. */
3364 if (s->hl == DRAW_CURSOR)
3366 int r = s->img->relief;
3367 if (r < 0) r = -r;
3368 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3369 s->slice.width + r*2 - 1,
3370 s->slice.height + r*2 - 1);
3374 else
3375 /* Draw a rectangle if image could not be loaded. */
3376 mac_draw_rectangle (s->f, s->gc, x, y,
3377 s->slice.width - 1, s->slice.height - 1);
3381 /* Draw a relief around the image glyph string S. */
3383 static void
3384 x_draw_image_relief (s)
3385 struct glyph_string *s;
3387 int x0, y0, x1, y1, thick, raised_p;
3388 Rect r;
3389 int x = s->x;
3390 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3392 /* If first glyph of S has a left box line, start drawing it to the
3393 right of that line. */
3394 if (s->face->box != FACE_NO_BOX
3395 && s->first_glyph->left_box_line_p
3396 && s->slice.x == 0)
3397 x += abs (s->face->box_line_width);
3399 /* If there is a margin around the image, adjust x- and y-position
3400 by that margin. */
3401 if (s->slice.x == 0)
3402 x += s->img->hmargin;
3403 if (s->slice.y == 0)
3404 y += s->img->vmargin;
3406 if (s->hl == DRAW_IMAGE_SUNKEN
3407 || s->hl == DRAW_IMAGE_RAISED)
3409 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3410 raised_p = s->hl == DRAW_IMAGE_RAISED;
3412 else
3414 thick = abs (s->img->relief);
3415 raised_p = s->img->relief > 0;
3418 x0 = x - thick;
3419 y0 = y - thick;
3420 x1 = x + s->slice.width + thick - 1;
3421 y1 = y + s->slice.height + thick - 1;
3423 x_setup_relief_colors (s);
3424 get_glyph_string_clip_rect (s, &r);
3425 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3426 s->slice.y == 0,
3427 s->slice.y + s->slice.height == s->img->height,
3428 s->slice.x == 0,
3429 s->slice.x + s->slice.width == s->img->width,
3430 &r);
3434 /* Draw part of the background of glyph string S. X, Y, W, and H
3435 give the rectangle to draw. */
3437 static void
3438 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3439 struct glyph_string *s;
3440 int x, y, w, h;
3442 #if 0 /* MAC_TODO: stipple */
3443 if (s->stippled_p)
3445 /* Fill background with a stipple pattern. */
3446 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3447 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3448 XSetFillStyle (s->display, s->gc, FillSolid);
3450 else
3451 #endif /* MAC_TODO */
3452 x_clear_glyph_string_rect (s, x, y, w, h);
3456 /* Draw image glyph string S.
3458 s->y
3459 s->x +-------------------------
3460 | s->face->box
3462 | +-------------------------
3463 | | s->img->margin
3465 | | +-------------------
3466 | | | the image
3470 static void
3471 x_draw_image_glyph_string (s)
3472 struct glyph_string *s;
3474 int x, y;
3475 int box_line_hwidth = abs (s->face->box_line_width);
3476 int box_line_vwidth = max (s->face->box_line_width, 0);
3477 int height;
3479 height = s->height - 2 * box_line_vwidth;
3482 /* Fill background with face under the image. Do it only if row is
3483 taller than image or if image has a clip mask to reduce
3484 flickering. */
3485 s->stippled_p = s->face->stipple != 0;
3486 if (height > s->slice.height
3487 || s->img->hmargin
3488 || s->img->vmargin
3489 || s->img->mask
3490 || s->img->pixmap == 0
3491 || s->width != s->background_width)
3493 x = s->x;
3494 if (s->first_glyph->left_box_line_p
3495 && s->slice.x == 0)
3496 x += box_line_hwidth;
3498 y = s->y;
3499 if (s->slice.y == 0)
3500 y += box_line_vwidth;
3502 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3504 s->background_filled_p = 1;
3507 /* Draw the foreground. */
3508 x_draw_image_foreground (s);
3510 /* If we must draw a relief around the image, do it. */
3511 if (s->img->relief
3512 || s->hl == DRAW_IMAGE_RAISED
3513 || s->hl == DRAW_IMAGE_SUNKEN)
3514 x_draw_image_relief (s);
3518 /* Draw stretch glyph string S. */
3520 static void
3521 x_draw_stretch_glyph_string (s)
3522 struct glyph_string *s;
3524 xassert (s->first_glyph->type == STRETCH_GLYPH);
3525 s->stippled_p = s->face->stipple != 0;
3527 if (s->hl == DRAW_CURSOR
3528 && !x_stretch_cursor_p)
3530 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3531 as wide as the stretch glyph. */
3532 int width, background_width = s->background_width;
3533 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3535 if (x < left_x)
3537 background_width -= left_x - x;
3538 x = left_x;
3540 width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
3542 /* Draw cursor. */
3543 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
3545 /* Clear rest using the GC of the original non-cursor face. */
3546 if (width < background_width)
3548 int y = s->y;
3549 int w = background_width - width, h = s->height;
3550 Rect r;
3551 GC gc;
3553 x += width;
3554 if (s->row->mouse_face_p
3555 && cursor_in_mouse_face_p (s->w))
3557 x_set_mouse_face_gc (s);
3558 gc = s->gc;
3560 else
3561 gc = s->face->gc;
3563 get_glyph_string_clip_rect (s, &r);
3564 mac_set_clip_rectangles (s->display, gc, &r, 1);
3566 #if 0 /* MAC_TODO: stipple */
3567 if (s->face->stipple)
3569 /* Fill background with a stipple pattern. */
3570 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3571 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3572 XSetFillStyle (s->display, gc, FillSolid);
3574 else
3575 #endif /* MAC_TODO */
3576 mac_erase_rectangle (s->f, gc, x, y, w, h);
3579 else if (!s->background_filled_p)
3581 int background_width = s->background_width;
3582 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
3584 if (x < left_x)
3586 background_width -= left_x - x;
3587 x = left_x;
3589 if (background_width > 0)
3590 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
3593 s->background_filled_p = 1;
3597 /* Draw glyph string S. */
3599 static void
3600 x_draw_glyph_string (s)
3601 struct glyph_string *s;
3603 int relief_drawn_p = 0;
3605 /* If S draws into the background of its successor that does not
3606 draw a cursor, draw the background of the successor first so that
3607 S can draw into it. This makes S->next use XDrawString instead
3608 of XDrawImageString. */
3609 if (s->next && s->right_overhang && !s->for_overlaps
3610 && s->next->hl != DRAW_CURSOR)
3612 xassert (s->next->img == NULL);
3613 x_set_glyph_string_gc (s->next);
3614 x_set_glyph_string_clipping (s->next);
3615 x_draw_glyph_string_background (s->next, 1);
3618 /* Set up S->gc, set clipping and draw S. */
3619 x_set_glyph_string_gc (s);
3621 /* Draw relief (if any) in advance for char/composition so that the
3622 glyph string can be drawn over it. */
3623 if (!s->for_overlaps
3624 && s->face->box != FACE_NO_BOX
3625 && (s->first_glyph->type == CHAR_GLYPH
3626 || s->first_glyph->type == COMPOSITE_GLYPH))
3629 x_set_glyph_string_clipping (s);
3630 x_draw_glyph_string_background (s, 1);
3631 x_draw_glyph_string_box (s);
3632 x_set_glyph_string_clipping (s);
3633 relief_drawn_p = 1;
3635 else
3636 x_set_glyph_string_clipping (s);
3638 switch (s->first_glyph->type)
3640 case IMAGE_GLYPH:
3641 x_draw_image_glyph_string (s);
3642 break;
3644 case STRETCH_GLYPH:
3645 x_draw_stretch_glyph_string (s);
3646 break;
3648 case CHAR_GLYPH:
3649 if (s->for_overlaps)
3650 s->background_filled_p = 1;
3651 else
3652 x_draw_glyph_string_background (s, 0);
3653 x_draw_glyph_string_foreground (s);
3654 break;
3656 case COMPOSITE_GLYPH:
3657 if (s->for_overlaps || s->gidx > 0)
3658 s->background_filled_p = 1;
3659 else
3660 x_draw_glyph_string_background (s, 1);
3661 x_draw_composite_glyph_string_foreground (s);
3662 break;
3664 default:
3665 abort ();
3668 if (!s->for_overlaps)
3670 /* Draw underline. */
3671 if (s->face->underline_p)
3673 unsigned long h = 1;
3674 unsigned long dy = s->height - h;
3676 if (s->face->underline_defaulted_p)
3677 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3678 s->width, h);
3679 else
3681 XGCValues xgcv;
3682 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3683 XSetForeground (s->display, s->gc, s->face->underline_color);
3684 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3685 s->width, h);
3686 XSetForeground (s->display, s->gc, xgcv.foreground);
3690 /* Draw overline. */
3691 if (s->face->overline_p)
3693 unsigned long dy = 0, h = 1;
3695 if (s->face->overline_color_defaulted_p)
3696 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3697 s->width, h);
3698 else
3700 XGCValues xgcv;
3701 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3702 XSetForeground (s->display, s->gc, s->face->overline_color);
3703 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3704 s->width, h);
3705 XSetForeground (s->display, s->gc, xgcv.foreground);
3709 /* Draw strike-through. */
3710 if (s->face->strike_through_p)
3712 unsigned long h = 1;
3713 unsigned long dy = (s->height - h) / 2;
3715 if (s->face->strike_through_color_defaulted_p)
3716 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3717 s->width, h);
3718 else
3720 XGCValues xgcv;
3721 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3722 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3723 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3724 s->width, h);
3725 XSetForeground (s->display, s->gc, xgcv.foreground);
3729 /* Draw relief if not yet drawn. */
3730 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3731 x_draw_glyph_string_box (s);
3734 /* Reset clipping. */
3735 mac_reset_clip_rectangles (s->display, s->gc);
3738 /* Shift display to make room for inserted glyphs. */
3740 void
3741 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3742 struct frame *f;
3743 int x, y, width, height, shift_by;
3745 mac_scroll_area (f, f->output_data.mac->normal_gc,
3746 x, y, width, height,
3747 x + shift_by, y);
3750 /* Delete N glyphs at the nominal cursor position. Not implemented
3751 for X frames. */
3753 static void
3754 x_delete_glyphs (n)
3755 register int n;
3757 abort ();
3761 /* Clear entire frame. If updating_frame is non-null, clear that
3762 frame. Otherwise clear the selected frame. */
3764 static void
3765 x_clear_frame ()
3767 struct frame *f;
3769 if (updating_frame)
3770 f = updating_frame;
3771 else
3772 f = SELECTED_FRAME ();
3774 /* Clearing the frame will erase any cursor, so mark them all as no
3775 longer visible. */
3776 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3777 output_cursor.hpos = output_cursor.vpos = 0;
3778 output_cursor.x = -1;
3780 /* We don't set the output cursor here because there will always
3781 follow an explicit cursor_to. */
3782 BLOCK_INPUT;
3783 mac_clear_window (f);
3785 /* We have to clear the scroll bars, too. If we have changed
3786 colors or something like that, then they should be notified. */
3787 x_scroll_bar_clear (f);
3789 XFlush (FRAME_MAC_DISPLAY (f));
3790 UNBLOCK_INPUT;
3795 /* Invert the middle quarter of the frame for .15 sec. */
3797 /* We use the select system call to do the waiting, so we have to make
3798 sure it's available. If it isn't, we just won't do visual bells. */
3800 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3803 /* Subtract the `struct timeval' values X and Y, storing the result in
3804 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3806 static int
3807 timeval_subtract (result, x, y)
3808 struct timeval *result, x, y;
3810 /* Perform the carry for the later subtraction by updating y. This
3811 is safer because on some systems the tv_sec member is unsigned. */
3812 if (x.tv_usec < y.tv_usec)
3814 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3815 y.tv_usec -= 1000000 * nsec;
3816 y.tv_sec += nsec;
3819 if (x.tv_usec - y.tv_usec > 1000000)
3821 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3822 y.tv_usec += 1000000 * nsec;
3823 y.tv_sec -= nsec;
3826 /* Compute the time remaining to wait. tv_usec is certainly
3827 positive. */
3828 result->tv_sec = x.tv_sec - y.tv_sec;
3829 result->tv_usec = x.tv_usec - y.tv_usec;
3831 /* Return indication of whether the result should be considered
3832 negative. */
3833 return x.tv_sec < y.tv_sec;
3836 void
3837 XTflash (f)
3838 struct frame *f;
3840 /* Get the height not including a menu bar widget. */
3841 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3842 /* Height of each line to flash. */
3843 int flash_height = FRAME_LINE_HEIGHT (f);
3844 /* These will be the left and right margins of the rectangles. */
3845 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3846 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3848 int width;
3850 /* Don't flash the area between a scroll bar and the frame
3851 edge it is next to. */
3852 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3854 case vertical_scroll_bar_left:
3855 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3856 break;
3858 case vertical_scroll_bar_right:
3859 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3860 break;
3862 default:
3863 break;
3866 width = flash_right - flash_left;
3868 BLOCK_INPUT;
3870 /* If window is tall, flash top and bottom line. */
3871 if (height > 3 * FRAME_LINE_HEIGHT (f))
3873 mac_invert_rectangle (f, flash_left,
3874 (FRAME_INTERNAL_BORDER_WIDTH (f)
3875 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3876 width, flash_height);
3877 mac_invert_rectangle (f, flash_left,
3878 (height - flash_height
3879 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3880 width, flash_height);
3882 else
3883 /* If it is short, flash it all. */
3884 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3885 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3887 x_flush (f);
3890 struct timeval wakeup;
3892 EMACS_GET_TIME (wakeup);
3894 /* Compute time to wait until, propagating carry from usecs. */
3895 wakeup.tv_usec += 150000;
3896 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3897 wakeup.tv_usec %= 1000000;
3899 /* Keep waiting until past the time wakeup or any input gets
3900 available. */
3901 while (! detect_input_pending ())
3903 struct timeval current;
3904 struct timeval timeout;
3906 EMACS_GET_TIME (current);
3908 /* Break if result would be negative. */
3909 if (timeval_subtract (&current, wakeup, current))
3910 break;
3912 /* How long `select' should wait. */
3913 timeout.tv_sec = 0;
3914 timeout.tv_usec = 10000;
3916 /* Try to wait that long--but we might wake up sooner. */
3917 select (0, NULL, NULL, NULL, &timeout);
3921 /* If window is tall, flash top and bottom line. */
3922 if (height > 3 * FRAME_LINE_HEIGHT (f))
3924 mac_invert_rectangle (f, flash_left,
3925 (FRAME_INTERNAL_BORDER_WIDTH (f)
3926 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3927 width, flash_height);
3928 mac_invert_rectangle (f, flash_left,
3929 (height - flash_height
3930 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3931 width, flash_height);
3933 else
3934 /* If it is short, flash it all. */
3935 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3936 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3938 x_flush (f);
3940 UNBLOCK_INPUT;
3943 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3946 /* Make audible bell. */
3948 void
3949 XTring_bell ()
3951 struct frame *f = SELECTED_FRAME ();
3953 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3954 if (visible_bell)
3955 XTflash (f);
3956 else
3957 #endif
3959 BLOCK_INPUT;
3960 SysBeep (1);
3961 XFlush (FRAME_MAC_DISPLAY (f));
3962 UNBLOCK_INPUT;
3967 /* Specify how many text lines, from the top of the window,
3968 should be affected by insert-lines and delete-lines operations.
3969 This, and those operations, are used only within an update
3970 that is bounded by calls to x_update_begin and x_update_end. */
3972 static void
3973 XTset_terminal_window (n)
3974 register int n;
3976 /* This function intentionally left blank. */
3981 /***********************************************************************
3982 Line Dance
3983 ***********************************************************************/
3985 /* Perform an insert-lines or delete-lines operation, inserting N
3986 lines or deleting -N lines at vertical position VPOS. */
3988 static void
3989 x_ins_del_lines (vpos, n)
3990 int vpos, n;
3992 abort ();
3996 /* Scroll part of the display as described by RUN. */
3998 static void
3999 x_scroll_run (w, run)
4000 struct window *w;
4001 struct run *run;
4003 struct frame *f = XFRAME (w->frame);
4004 int x, y, width, height, from_y, to_y, bottom_y;
4006 /* Get frame-relative bounding box of the text display area of W,
4007 without mode lines. Include in this box the left and right
4008 fringe of W. */
4009 window_box (w, -1, &x, &y, &width, &height);
4011 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4012 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4013 bottom_y = y + height;
4015 if (to_y < from_y)
4017 /* Scrolling up. Make sure we don't copy part of the mode
4018 line at the bottom. */
4019 if (from_y + run->height > bottom_y)
4020 height = bottom_y - from_y;
4021 else
4022 height = run->height;
4024 else
4026 /* Scolling down. Make sure we don't copy over the mode line.
4027 at the bottom. */
4028 if (to_y + run->height > bottom_y)
4029 height = bottom_y - to_y;
4030 else
4031 height = run->height;
4034 BLOCK_INPUT;
4036 /* Cursor off. Will be switched on again in x_update_window_end. */
4037 updated_window = w;
4038 x_clear_cursor (w);
4040 mac_scroll_area (f, f->output_data.mac->normal_gc,
4041 x, from_y,
4042 width, height,
4043 x, to_y);
4045 UNBLOCK_INPUT;
4050 /***********************************************************************
4051 Exposure Events
4052 ***********************************************************************/
4055 static void
4056 frame_highlight (f)
4057 struct frame *f;
4059 OSErr err;
4060 ControlRef root_control;
4062 BLOCK_INPUT;
4063 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
4064 if (err == noErr)
4065 ActivateControl (root_control);
4066 UNBLOCK_INPUT;
4067 x_update_cursor (f, 1);
4070 static void
4071 frame_unhighlight (f)
4072 struct frame *f;
4074 OSErr err;
4075 ControlRef root_control;
4077 BLOCK_INPUT;
4078 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
4079 if (err == noErr)
4080 DeactivateControl (root_control);
4081 UNBLOCK_INPUT;
4082 x_update_cursor (f, 1);
4085 /* The focus has changed. Update the frames as necessary to reflect
4086 the new situation. Note that we can't change the selected frame
4087 here, because the Lisp code we are interrupting might become confused.
4088 Each event gets marked with the frame in which it occurred, so the
4089 Lisp code can tell when the switch took place by examining the events. */
4091 static void
4092 x_new_focus_frame (dpyinfo, frame)
4093 struct x_display_info *dpyinfo;
4094 struct frame *frame;
4096 struct frame *old_focus = dpyinfo->x_focus_frame;
4098 if (frame != dpyinfo->x_focus_frame)
4100 /* Set this before calling other routines, so that they see
4101 the correct value of x_focus_frame. */
4102 dpyinfo->x_focus_frame = frame;
4104 if (old_focus && old_focus->auto_lower)
4105 x_lower_frame (old_focus);
4107 #if 0
4108 selected_frame = frame;
4109 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
4110 selected_frame);
4111 Fselect_window (selected_frame->selected_window, Qnil);
4112 choose_minibuf_frame ();
4113 #endif /* ! 0 */
4115 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
4116 pending_autoraise_frame = dpyinfo->x_focus_frame;
4117 else
4118 pending_autoraise_frame = 0;
4120 #if USE_MAC_FONT_PANEL
4121 if (frame)
4122 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0);
4123 #endif
4126 x_frame_rehighlight (dpyinfo);
4129 /* Handle FocusIn and FocusOut state changes for FRAME.
4130 If FRAME has focus and there exists more than one frame, puts
4131 a FOCUS_IN_EVENT into *BUFP. */
4133 static void
4134 mac_focus_changed (type, dpyinfo, frame, bufp)
4135 int type;
4136 struct mac_display_info *dpyinfo;
4137 struct frame *frame;
4138 struct input_event *bufp;
4140 if (type == activeFlag)
4142 if (dpyinfo->x_focus_event_frame != frame)
4144 x_new_focus_frame (dpyinfo, frame);
4145 dpyinfo->x_focus_event_frame = frame;
4147 /* Don't stop displaying the initial startup message
4148 for a switch-frame event we don't need. */
4149 if (GC_NILP (Vterminal_frame)
4150 && GC_CONSP (Vframe_list)
4151 && !GC_NILP (XCDR (Vframe_list)))
4153 bufp->kind = FOCUS_IN_EVENT;
4154 XSETFRAME (bufp->frame_or_window, frame);
4158 else
4160 if (dpyinfo->x_focus_event_frame == frame)
4162 dpyinfo->x_focus_event_frame = 0;
4163 x_new_focus_frame (dpyinfo, 0);
4168 /* The focus may have changed. Figure out if it is a real focus change,
4169 by checking both FocusIn/Out and Enter/LeaveNotify events.
4171 Returns FOCUS_IN_EVENT event in *BUFP. */
4173 static void
4174 x_detect_focus_change (dpyinfo, event, bufp)
4175 struct mac_display_info *dpyinfo;
4176 EventRecord *event;
4177 struct input_event *bufp;
4179 struct frame *frame;
4181 frame = mac_window_to_frame ((WindowPtr) event->message);
4182 if (! frame)
4183 return;
4185 /* On Mac, this is only called from focus events, so no switch needed. */
4186 mac_focus_changed ((event->modifiers & activeFlag),
4187 dpyinfo, frame, bufp);
4191 /* Handle an event saying the mouse has moved out of an Emacs frame. */
4193 void
4194 x_mouse_leave (dpyinfo)
4195 struct x_display_info *dpyinfo;
4197 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
4200 /* The focus has changed, or we have redirected a frame's focus to
4201 another frame (this happens when a frame uses a surrogate
4202 mini-buffer frame). Shift the highlight as appropriate.
4204 The FRAME argument doesn't necessarily have anything to do with which
4205 frame is being highlighted or un-highlighted; we only use it to find
4206 the appropriate X display info. */
4208 static void
4209 XTframe_rehighlight (frame)
4210 struct frame *frame;
4212 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
4215 static void
4216 x_frame_rehighlight (dpyinfo)
4217 struct x_display_info *dpyinfo;
4219 struct frame *old_highlight = dpyinfo->x_highlight_frame;
4221 if (dpyinfo->x_focus_frame)
4223 dpyinfo->x_highlight_frame
4224 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
4225 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
4226 : dpyinfo->x_focus_frame);
4227 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
4229 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
4230 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
4233 else
4234 dpyinfo->x_highlight_frame = 0;
4236 if (dpyinfo->x_highlight_frame != old_highlight)
4238 if (old_highlight)
4239 frame_unhighlight (old_highlight);
4240 if (dpyinfo->x_highlight_frame)
4241 frame_highlight (dpyinfo->x_highlight_frame);
4247 /* Convert a keysym to its name. */
4249 char *
4250 x_get_keysym_name (keysym)
4251 int keysym;
4253 char *value;
4255 BLOCK_INPUT;
4256 #if 0
4257 value = XKeysymToString (keysym);
4258 #else
4259 value = 0;
4260 #endif
4261 UNBLOCK_INPUT;
4263 return value;
4268 /* Function to report a mouse movement to the mainstream Emacs code.
4269 The input handler calls this.
4271 We have received a mouse movement event, which is given in *event.
4272 If the mouse is over a different glyph than it was last time, tell
4273 the mainstream emacs code by setting mouse_moved. If not, ask for
4274 another motion event, so we can check again the next time it moves. */
4276 static Point last_mouse_motion_position;
4277 static Lisp_Object last_mouse_motion_frame;
4279 static int
4280 note_mouse_movement (frame, pos)
4281 FRAME_PTR frame;
4282 Point *pos;
4284 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4285 #if TARGET_API_MAC_CARBON
4286 Rect r;
4287 #endif
4289 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4290 last_mouse_motion_position = *pos;
4291 XSETFRAME (last_mouse_motion_frame, frame);
4293 #if TARGET_API_MAC_CARBON
4294 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
4295 #else
4296 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
4297 #endif
4299 if (frame == dpyinfo->mouse_face_mouse_frame)
4300 /* This case corresponds to LeaveNotify in X11. */
4302 /* If we move outside the frame, then we're certainly no
4303 longer on any text in the frame. */
4304 clear_mouse_face (dpyinfo);
4305 dpyinfo->mouse_face_mouse_frame = 0;
4306 if (!dpyinfo->grabbed)
4307 rif->define_frame_cursor (frame,
4308 frame->output_data.mac->nontext_cursor);
4310 return 1;
4312 /* Has the mouse moved off the glyph it was on at the last sighting? */
4313 if (frame != last_mouse_glyph_frame
4314 || !PtInRect (*pos, &last_mouse_glyph))
4316 frame->mouse_moved = 1;
4317 last_mouse_scroll_bar = Qnil;
4318 note_mouse_highlight (frame, pos->h, pos->v);
4319 /* Remember which glyph we're now on. */
4320 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4321 last_mouse_glyph_frame = frame;
4322 return 1;
4325 return 0;
4329 /************************************************************************
4330 Mouse Face
4331 ************************************************************************/
4333 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4335 static void
4336 redo_mouse_highlight ()
4338 if (!NILP (last_mouse_motion_frame)
4339 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4340 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4341 last_mouse_motion_position.h,
4342 last_mouse_motion_position.v);
4346 static struct frame *
4347 mac_focus_frame (dpyinfo)
4348 struct mac_display_info *dpyinfo;
4350 if (dpyinfo->x_focus_frame)
4351 return dpyinfo->x_focus_frame;
4352 else
4353 /* Mac version may get events, such as a menu bar click, even when
4354 all the frames are invisible. In this case, we regard the
4355 event came to the selected frame. */
4356 return SELECTED_FRAME ();
4360 /* Return the current position of the mouse.
4361 *FP should be a frame which indicates which display to ask about.
4363 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4364 and *PART to the frame, window, and scroll bar part that the mouse
4365 is over. Set *X and *Y to the portion and whole of the mouse's
4366 position on the scroll bar.
4368 If the mouse movement started elsewhere, set *FP to the frame the
4369 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4370 the mouse is over.
4372 Set *TIME to the server time-stamp for the time at which the mouse
4373 was at this position.
4375 Don't store anything if we don't have a valid set of values to report.
4377 This clears the mouse_moved flag, so we can wait for the next mouse
4378 movement. */
4380 static void
4381 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4382 FRAME_PTR *fp;
4383 int insist;
4384 Lisp_Object *bar_window;
4385 enum scroll_bar_part *part;
4386 Lisp_Object *x, *y;
4387 unsigned long *time;
4389 FRAME_PTR f1;
4391 BLOCK_INPUT;
4393 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4394 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4395 else
4397 Lisp_Object frame, tail;
4399 /* Clear the mouse-moved flag for every frame on this display. */
4400 FOR_EACH_FRAME (tail, frame)
4401 XFRAME (frame)->mouse_moved = 0;
4403 last_mouse_scroll_bar = Qnil;
4405 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4406 && FRAME_LIVE_P (last_mouse_frame))
4407 f1 = last_mouse_frame;
4408 else
4409 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4411 if (f1)
4413 /* Ok, we found a frame. Store all the values.
4414 last_mouse_glyph is a rectangle used to reduce the
4415 generation of mouse events. To not miss any motion
4416 events, we must divide the frame into rectangles of the
4417 size of the smallest character that could be displayed
4418 on it, i.e. into the same rectangles that matrices on
4419 the frame are divided into. */
4420 Point mouse_pos;
4422 SetPortWindowPort (FRAME_MAC_WINDOW (f1));
4423 GetMouse (&mouse_pos);
4424 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4425 &last_mouse_glyph);
4426 last_mouse_glyph_frame = f1;
4428 *bar_window = Qnil;
4429 *part = 0;
4430 *fp = f1;
4431 XSETINT (*x, mouse_pos.h);
4432 XSETINT (*y, mouse_pos.v);
4433 *time = last_mouse_movement_time;
4437 UNBLOCK_INPUT;
4441 /************************************************************************
4442 Toolkit scroll bars
4443 ************************************************************************/
4445 #ifdef USE_TOOLKIT_SCROLL_BARS
4447 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4448 static OSStatus install_scroll_bar_timer P_ ((void));
4449 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4450 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4451 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4452 struct input_event *));
4453 static OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
4454 Rect *));
4455 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4456 ControlPartCode,
4457 struct input_event *));
4458 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4459 struct input_event *));
4460 static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
4461 Point, struct input_event *));
4462 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4463 int, int, int));
4465 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4467 static int last_scroll_bar_part;
4469 static EventLoopTimerRef scroll_bar_timer;
4471 static int scroll_bar_timer_event_posted_p;
4473 #define SCROLL_BAR_FIRST_DELAY 0.5
4474 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4476 static pascal void
4477 scroll_bar_timer_callback (timer, data)
4478 EventLoopTimerRef timer;
4479 void *data;
4481 OSStatus err;
4483 err = mac_post_mouse_moved_event ();
4484 if (err == noErr)
4485 scroll_bar_timer_event_posted_p = 1;
4488 static OSStatus
4489 install_scroll_bar_timer ()
4491 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4493 if (scroll_bar_timer_callbackUPP == NULL)
4494 scroll_bar_timer_callbackUPP =
4495 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4497 if (scroll_bar_timer == NULL)
4498 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4499 kEventDurationForever as delays. */
4500 return
4501 InstallEventLoopTimer (GetCurrentEventLoop (),
4502 kEventDurationForever, kEventDurationForever,
4503 scroll_bar_timer_callbackUPP, NULL,
4504 &scroll_bar_timer);
4507 static OSStatus
4508 set_scroll_bar_timer (delay)
4509 EventTimerInterval delay;
4511 if (scroll_bar_timer == NULL)
4512 install_scroll_bar_timer ();
4514 scroll_bar_timer_event_posted_p = 0;
4516 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4519 static int
4520 control_part_code_to_scroll_bar_part (part_code)
4521 ControlPartCode part_code;
4523 switch (part_code)
4525 case kControlUpButtonPart: return scroll_bar_up_arrow;
4526 case kControlDownButtonPart: return scroll_bar_down_arrow;
4527 case kControlPageUpPart: return scroll_bar_above_handle;
4528 case kControlPageDownPart: return scroll_bar_below_handle;
4529 case kControlIndicatorPart: return scroll_bar_handle;
4532 return -1;
4535 static void
4536 construct_scroll_bar_click (bar, part, bufp)
4537 struct scroll_bar *bar;
4538 int part;
4539 struct input_event *bufp;
4541 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4542 bufp->frame_or_window = bar->window;
4543 bufp->arg = Qnil;
4544 bufp->part = part;
4545 bufp->code = 0;
4546 XSETINT (bufp->x, 0);
4547 XSETINT (bufp->y, 0);
4548 bufp->modifiers = 0;
4551 static OSStatus
4552 get_control_part_bounds (ch, part_code, rect)
4553 ControlHandle ch;
4554 ControlPartCode part_code;
4555 Rect *rect;
4557 RgnHandle region = NewRgn ();
4558 OSStatus err;
4560 err = GetControlRegion (ch, part_code, region);
4561 if (err == noErr)
4562 GetRegionBounds (region, rect);
4563 DisposeRgn (region);
4565 return err;
4568 static void
4569 x_scroll_bar_handle_press (bar, part_code, bufp)
4570 struct scroll_bar *bar;
4571 ControlPartCode part_code;
4572 struct input_event *bufp;
4574 int part = control_part_code_to_scroll_bar_part (part_code);
4576 if (part < 0)
4577 return;
4579 if (part != scroll_bar_handle)
4581 construct_scroll_bar_click (bar, part, bufp);
4582 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4583 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4586 last_scroll_bar_part = part;
4587 bar->dragging = Qnil;
4588 tracked_scroll_bar = bar;
4591 static void
4592 x_scroll_bar_handle_release (bar, bufp)
4593 struct scroll_bar *bar;
4594 struct input_event *bufp;
4596 if (last_scroll_bar_part != scroll_bar_handle
4597 || !GC_NILP (bar->dragging))
4598 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4600 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4601 set_scroll_bar_timer (kEventDurationForever);
4603 last_scroll_bar_part = -1;
4604 bar->dragging = Qnil;
4605 tracked_scroll_bar = NULL;
4608 static void
4609 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4610 WindowPtr win;
4611 struct scroll_bar *bar;
4612 Point mouse_pos;
4613 struct input_event *bufp;
4615 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4617 if (last_scroll_bar_part == scroll_bar_handle)
4619 int top, top_range;
4620 Rect r;
4622 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4623 kControlIndicatorPart, &r);
4625 if (GC_NILP (bar->dragging))
4626 XSETINT (bar->dragging, mouse_pos.v - r.top);
4628 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4629 top_range = (XINT (bar->track_height) - (r.bottom - r.top)) *
4630 (1.0 + (float) GetControlViewSize (ch) / GetControl32BitMaximum (ch))
4631 + .5;
4633 if (top < 0)
4634 top = 0;
4635 if (top > top_range)
4636 top = top_range;
4638 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4639 XSETINT (bufp->x, top);
4640 XSETINT (bufp->y, top_range);
4642 else
4644 ControlPartCode part_code;
4645 int unhilite_p = 0, part;
4647 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4648 unhilite_p = 1;
4649 else
4651 part = control_part_code_to_scroll_bar_part (part_code);
4653 switch (last_scroll_bar_part)
4655 case scroll_bar_above_handle:
4656 case scroll_bar_below_handle:
4657 if (part != scroll_bar_above_handle
4658 && part != scroll_bar_below_handle)
4659 unhilite_p = 1;
4660 break;
4662 case scroll_bar_up_arrow:
4663 case scroll_bar_down_arrow:
4664 if (part != scroll_bar_up_arrow
4665 && part != scroll_bar_down_arrow)
4666 unhilite_p = 1;
4667 break;
4671 if (unhilite_p)
4672 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4673 else if (part != last_scroll_bar_part
4674 || scroll_bar_timer_event_posted_p)
4676 construct_scroll_bar_click (bar, part, bufp);
4677 last_scroll_bar_part = part;
4678 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4679 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4684 /* Set the thumb size and position of scroll bar BAR. We are currently
4685 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4687 static void
4688 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4689 struct scroll_bar *bar;
4690 int portion, position, whole;
4692 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4693 int value, viewsize, maximum;
4695 if (XINT (bar->track_height) == 0)
4696 return;
4698 if (whole == 0)
4699 value = 0, viewsize = 1, maximum = 0;
4700 else
4702 value = position;
4703 viewsize = portion;
4704 maximum = max (0, whole - portion);
4707 BLOCK_INPUT;
4709 if (GetControlViewSize (ch) != viewsize
4710 || GetControl32BitValue (ch) != value
4711 || GetControl32BitMaximum (ch) != maximum)
4713 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4714 SetControlVisibility (ch, false, false);
4716 SetControl32BitMaximum (ch, maximum);
4717 SetControl32BitValue (ch, value);
4718 SetControlViewSize (ch, viewsize);
4720 SetControlVisibility (ch, true, true);
4723 UNBLOCK_INPUT;
4726 #endif /* USE_TOOLKIT_SCROLL_BARS */
4730 /************************************************************************
4731 Scroll bars, general
4732 ************************************************************************/
4734 /* Create a scroll bar and return the scroll bar vector for it. W is
4735 the Emacs window on which to create the scroll bar. TOP, LEFT,
4736 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4737 scroll bar. */
4739 static struct scroll_bar *
4740 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4741 struct window *w;
4742 int top, left, width, height, disp_top, disp_height;
4744 struct frame *f = XFRAME (w->frame);
4745 struct scroll_bar *bar
4746 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4747 Rect r;
4748 ControlHandle ch;
4750 BLOCK_INPUT;
4752 r.left = left;
4753 r.top = disp_top;
4754 r.right = left + width;
4755 r.bottom = disp_top + disp_height;
4757 #if USE_CG_DRAWING
4758 mac_prepare_for_quickdraw (f);
4759 #endif
4760 #if TARGET_API_MAC_CARBON
4761 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p",
4762 #if USE_TOOLKIT_SCROLL_BARS
4763 false,
4764 #else
4765 width < disp_height,
4766 #endif
4767 0, 0, 0, kControlScrollBarProc, (long) bar);
4768 #else
4769 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4770 0, 0, 0, scrollBarProc, (long) bar);
4771 #endif
4772 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4774 XSETWINDOW (bar->window, w);
4775 XSETINT (bar->top, top);
4776 XSETINT (bar->left, left);
4777 XSETINT (bar->width, width);
4778 XSETINT (bar->height, height);
4779 XSETINT (bar->start, 0);
4780 XSETINT (bar->end, 0);
4781 bar->dragging = Qnil;
4782 #ifdef USE_TOOLKIT_SCROLL_BARS
4783 bar->track_top = Qnil;
4784 bar->track_height = Qnil;
4785 #endif
4787 /* Add bar to its frame's list of scroll bars. */
4788 bar->next = FRAME_SCROLL_BARS (f);
4789 bar->prev = Qnil;
4790 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4791 if (!NILP (bar->next))
4792 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4794 UNBLOCK_INPUT;
4795 return bar;
4799 /* Draw BAR's handle in the proper position.
4801 If the handle is already drawn from START to END, don't bother
4802 redrawing it, unless REBUILD is non-zero; in that case, always
4803 redraw it. (REBUILD is handy for drawing the handle after expose
4804 events.)
4806 Normally, we want to constrain the start and end of the handle to
4807 fit inside its rectangle, but if the user is dragging the scroll
4808 bar handle, we want to let them drag it down all the way, so that
4809 the bar's top is as far down as it goes; otherwise, there's no way
4810 to move to the very end of the buffer. */
4812 #ifndef USE_TOOLKIT_SCROLL_BARS
4814 static void
4815 x_scroll_bar_set_handle (bar, start, end, rebuild)
4816 struct scroll_bar *bar;
4817 int start, end;
4818 int rebuild;
4820 int dragging = ! NILP (bar->dragging);
4821 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4822 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4823 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4824 int length = end - start;
4826 /* If the display is already accurate, do nothing. */
4827 if (! rebuild
4828 && start == XINT (bar->start)
4829 && end == XINT (bar->end))
4830 return;
4832 BLOCK_INPUT;
4834 /* Make sure the values are reasonable, and try to preserve the
4835 distance between start and end. */
4836 if (start < 0)
4837 start = 0;
4838 else if (start > top_range)
4839 start = top_range;
4840 end = start + length;
4842 if (end < start)
4843 end = start;
4844 else if (end > top_range && ! dragging)
4845 end = top_range;
4847 /* Store the adjusted setting in the scroll bar. */
4848 XSETINT (bar->start, start);
4849 XSETINT (bar->end, end);
4851 /* Clip the end position, just for display. */
4852 if (end > top_range)
4853 end = top_range;
4855 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4856 top positions, to make sure the handle is always at least that
4857 many pixels tall. */
4858 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4860 SetControlMinimum (ch, 0);
4861 /* Don't inadvertently activate deactivated scroll bars */
4862 if (GetControlMaximum (ch) != -1)
4863 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4864 - (end - start));
4865 SetControlValue (ch, start);
4866 #if TARGET_API_MAC_CARBON
4867 SetControlViewSize (ch, end - start);
4868 #endif
4870 UNBLOCK_INPUT;
4873 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4875 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4876 nil. */
4878 static void
4879 x_scroll_bar_remove (bar)
4880 struct scroll_bar *bar;
4882 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4884 BLOCK_INPUT;
4886 #if USE_CG_DRAWING
4887 mac_prepare_for_quickdraw (f);
4888 #endif
4889 /* Destroy the Mac scroll bar control */
4890 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4892 /* Disassociate this scroll bar from its window. */
4893 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4895 UNBLOCK_INPUT;
4899 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4900 that we are displaying PORTION characters out of a total of WHOLE
4901 characters, starting at POSITION. If WINDOW has no scroll bar,
4902 create one. */
4904 static void
4905 XTset_vertical_scroll_bar (w, portion, whole, position)
4906 struct window *w;
4907 int portion, whole, position;
4909 struct frame *f = XFRAME (w->frame);
4910 struct scroll_bar *bar;
4911 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4912 int window_y, window_height;
4914 /* Get window dimensions. */
4915 window_box (w, -1, 0, &window_y, 0, &window_height);
4916 top = window_y;
4917 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4918 height = window_height;
4920 /* Compute the left edge of the scroll bar area. */
4921 left = WINDOW_SCROLL_BAR_AREA_X (w);
4923 /* Compute the width of the scroll bar which might be less than
4924 the width of the area reserved for the scroll bar. */
4925 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4926 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4927 else
4928 sb_width = width;
4930 /* Compute the left edge of the scroll bar. */
4931 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4932 sb_left = left;
4933 else
4934 sb_left = left + width - sb_width;
4936 /* Adjustments according to Inside Macintosh to make it look nice */
4937 disp_top = top;
4938 disp_height = height;
4939 #ifdef MAC_OS8
4940 if (disp_top == 0)
4942 disp_top = -1;
4943 disp_height++;
4945 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4947 disp_top++;
4948 disp_height--;
4951 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4952 sb_left++;
4953 #endif
4955 /* Does the scroll bar exist yet? */
4956 if (NILP (w->vertical_scroll_bar))
4958 BLOCK_INPUT;
4959 mac_clear_area (f, left, top, width, height);
4960 UNBLOCK_INPUT;
4961 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4962 disp_height);
4963 XSETVECTOR (w->vertical_scroll_bar, bar);
4965 else
4967 /* It may just need to be moved and resized. */
4968 ControlHandle ch;
4970 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4971 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4973 BLOCK_INPUT;
4975 /* If already correctly positioned, do nothing. */
4976 if (!(XINT (bar->left) == sb_left
4977 && XINT (bar->top) == top
4978 && XINT (bar->width) == sb_width
4979 && XINT (bar->height) == height))
4981 /* Since toolkit scroll bars are smaller than the space reserved
4982 for them on the frame, we have to clear "under" them. */
4983 mac_clear_area (f, left, top, width, height);
4985 #if USE_CG_DRAWING
4986 mac_prepare_for_quickdraw (f);
4987 #endif
4988 HideControl (ch);
4989 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4990 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4991 disp_height);
4992 #ifndef USE_TOOLKIT_SCROLL_BARS
4993 if (sb_width < disp_height)
4994 ShowControl (ch);
4995 #endif
4997 /* Remember new settings. */
4998 XSETINT (bar->left, sb_left);
4999 XSETINT (bar->top, top);
5000 XSETINT (bar->width, sb_width);
5001 XSETINT (bar->height, height);
5002 #ifdef USE_TOOLKIT_SCROLL_BARS
5003 bar->track_top = Qnil;
5004 bar->track_height = Qnil;
5005 #endif
5008 UNBLOCK_INPUT;
5011 #ifdef USE_TOOLKIT_SCROLL_BARS
5012 if (NILP (bar->track_top))
5014 if (sb_width >= disp_height)
5016 XSETINT (bar->track_top, 0);
5017 XSETINT (bar->track_height, 0);
5019 else
5021 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5022 Rect r0, r1;
5024 BLOCK_INPUT;
5026 SetControl32BitMinimum (ch, 0);
5027 SetControl32BitMaximum (ch, 1);
5028 SetControlViewSize (ch, 1);
5030 /* Move the scroll bar thumb to the top. */
5031 SetControl32BitValue (ch, 0);
5032 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
5034 /* Move the scroll bar thumb to the bottom. */
5035 SetControl32BitValue (ch, 1);
5036 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
5038 UnionRect (&r0, &r1, &r0);
5039 XSETINT (bar->track_top, r0.top);
5040 XSETINT (bar->track_height, r0.bottom - r0.top);
5042 /* Don't show the scroll bar if its height is not enough to
5043 display the scroll bar thumb. */
5044 if (r0.bottom - r0.top > 0)
5045 ShowControl (ch);
5047 UNBLOCK_INPUT;
5051 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
5052 #else /* not USE_TOOLKIT_SCROLL_BARS */
5053 /* Set the scroll bar's current state, unless we're currently being
5054 dragged. */
5055 if (NILP (bar->dragging))
5057 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
5059 if (whole == 0)
5060 x_scroll_bar_set_handle (bar, 0, top_range, 0);
5061 else
5063 int start = ((double) position * top_range) / whole;
5064 int end = ((double) (position + portion) * top_range) / whole;
5065 x_scroll_bar_set_handle (bar, start, end, 0);
5068 #endif /* not USE_TOOLKIT_SCROLL_BARS */
5072 /* The following three hooks are used when we're doing a thorough
5073 redisplay of the frame. We don't explicitly know which scroll bars
5074 are going to be deleted, because keeping track of when windows go
5075 away is a real pain - "Can you say set-window-configuration, boys
5076 and girls?" Instead, we just assert at the beginning of redisplay
5077 that *all* scroll bars are to be removed, and then save a scroll bar
5078 from the fiery pit when we actually redisplay its window. */
5080 /* Arrange for all scroll bars on FRAME to be removed at the next call
5081 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
5082 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
5084 static void
5085 XTcondemn_scroll_bars (frame)
5086 FRAME_PTR frame;
5088 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
5089 while (! NILP (FRAME_SCROLL_BARS (frame)))
5091 Lisp_Object bar;
5092 bar = FRAME_SCROLL_BARS (frame);
5093 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
5094 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
5095 XSCROLL_BAR (bar)->prev = Qnil;
5096 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
5097 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
5098 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
5103 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
5104 Note that WINDOW isn't necessarily condemned at all. */
5106 static void
5107 XTredeem_scroll_bar (window)
5108 struct window *window;
5110 struct scroll_bar *bar;
5111 struct frame *f;
5113 /* We can't redeem this window's scroll bar if it doesn't have one. */
5114 if (NILP (window->vertical_scroll_bar))
5115 abort ();
5117 bar = XSCROLL_BAR (window->vertical_scroll_bar);
5119 /* Unlink it from the condemned list. */
5120 f = XFRAME (WINDOW_FRAME (window));
5121 if (NILP (bar->prev))
5123 /* If the prev pointer is nil, it must be the first in one of
5124 the lists. */
5125 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
5126 /* It's not condemned. Everything's fine. */
5127 return;
5128 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
5129 window->vertical_scroll_bar))
5130 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
5131 else
5132 /* If its prev pointer is nil, it must be at the front of
5133 one or the other! */
5134 abort ();
5136 else
5137 XSCROLL_BAR (bar->prev)->next = bar->next;
5139 if (! NILP (bar->next))
5140 XSCROLL_BAR (bar->next)->prev = bar->prev;
5142 bar->next = FRAME_SCROLL_BARS (f);
5143 bar->prev = Qnil;
5144 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
5145 if (! NILP (bar->next))
5146 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
5149 /* Remove all scroll bars on FRAME that haven't been saved since the
5150 last call to `*condemn_scroll_bars_hook'. */
5152 static void
5153 XTjudge_scroll_bars (f)
5154 FRAME_PTR f;
5156 Lisp_Object bar, next;
5158 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
5160 /* Clear out the condemned list now so we won't try to process any
5161 more events on the hapless scroll bars. */
5162 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
5164 for (; ! NILP (bar); bar = next)
5166 struct scroll_bar *b = XSCROLL_BAR (bar);
5168 x_scroll_bar_remove (b);
5170 next = b->next;
5171 b->next = b->prev = Qnil;
5174 /* Now there should be no references to the condemned scroll bars,
5175 and they should get garbage-collected. */
5179 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5180 is set to something other than NO_EVENT, it is enqueued.
5182 This may be called from a signal handler, so we have to ignore GC
5183 mark bits. */
5185 static void
5186 x_scroll_bar_handle_click (bar, part_code, er, bufp)
5187 struct scroll_bar *bar;
5188 ControlPartCode part_code;
5189 EventRecord *er;
5190 struct input_event *bufp;
5192 int win_y, top_range;
5194 if (! GC_WINDOWP (bar->window))
5195 abort ();
5197 bufp->kind = SCROLL_BAR_CLICK_EVENT;
5198 bufp->frame_or_window = bar->window;
5199 bufp->arg = Qnil;
5201 bar->dragging = Qnil;
5203 switch (part_code)
5205 case kControlUpButtonPart:
5206 bufp->part = scroll_bar_up_arrow;
5207 break;
5208 case kControlDownButtonPart:
5209 bufp->part = scroll_bar_down_arrow;
5210 break;
5211 case kControlPageUpPart:
5212 bufp->part = scroll_bar_above_handle;
5213 break;
5214 case kControlPageDownPart:
5215 bufp->part = scroll_bar_below_handle;
5216 break;
5217 #if TARGET_API_MAC_CARBON
5218 default:
5219 #else
5220 case kControlIndicatorPart:
5221 #endif
5222 if (er->what == mouseDown)
5223 bar->dragging = make_number (0);
5224 XSETVECTOR (last_mouse_scroll_bar, bar);
5225 bufp->part = scroll_bar_handle;
5226 break;
5229 win_y = XINT (bufp->y) - XINT (bar->top);
5230 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5232 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5234 win_y -= 24;
5236 if (! NILP (bar->dragging))
5237 win_y -= XINT (bar->dragging);
5239 if (win_y < 0)
5240 win_y = 0;
5241 if (win_y > top_range)
5242 win_y = top_range;
5244 XSETINT (bufp->x, win_y);
5245 XSETINT (bufp->y, top_range);
5248 #ifndef USE_TOOLKIT_SCROLL_BARS
5250 /* Handle some mouse motion while someone is dragging the scroll bar.
5252 This may be called from a signal handler, so we have to ignore GC
5253 mark bits. */
5255 static void
5256 x_scroll_bar_note_movement (bar, y_pos, t)
5257 struct scroll_bar *bar;
5258 int y_pos;
5259 Time t;
5261 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5263 last_mouse_movement_time = t;
5265 f->mouse_moved = 1;
5266 XSETVECTOR (last_mouse_scroll_bar, bar);
5268 /* If we're dragging the bar, display it. */
5269 if (! GC_NILP (bar->dragging))
5271 /* Where should the handle be now? */
5272 int new_start = y_pos - 24;
5274 if (new_start != XINT (bar->start))
5276 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5278 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5283 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5285 /* Return information to the user about the current position of the mouse
5286 on the scroll bar. */
5288 static void
5289 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5290 FRAME_PTR *fp;
5291 Lisp_Object *bar_window;
5292 enum scroll_bar_part *part;
5293 Lisp_Object *x, *y;
5294 unsigned long *time;
5296 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5297 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5298 #if TARGET_API_MAC_CARBON
5299 WindowPtr wp = GetControlOwner (ch);
5300 #else
5301 WindowPtr wp = (*ch)->contrlOwner;
5302 #endif
5303 Point mouse_pos;
5304 struct frame *f = mac_window_to_frame (wp);
5305 int win_y, top_range;
5307 SetPortWindowPort (wp);
5309 GetMouse (&mouse_pos);
5311 win_y = mouse_pos.v - XINT (bar->top);
5312 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5314 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5316 win_y -= 24;
5318 if (! NILP (bar->dragging))
5319 win_y -= XINT (bar->dragging);
5321 if (win_y < 0)
5322 win_y = 0;
5323 if (win_y > top_range)
5324 win_y = top_range;
5326 *fp = f;
5327 *bar_window = bar->window;
5329 if (! NILP (bar->dragging))
5330 *part = scroll_bar_handle;
5331 else if (win_y < XINT (bar->start))
5332 *part = scroll_bar_above_handle;
5333 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5334 *part = scroll_bar_handle;
5335 else
5336 *part = scroll_bar_below_handle;
5338 XSETINT (*x, win_y);
5339 XSETINT (*y, top_range);
5341 f->mouse_moved = 0;
5342 last_mouse_scroll_bar = Qnil;
5344 *time = last_mouse_movement_time;
5348 /* The screen has been cleared so we may have changed foreground or
5349 background colors, and the scroll bars may need to be redrawn.
5350 Clear out the scroll bars, and ask for expose events, so we can
5351 redraw them. */
5353 void
5354 x_scroll_bar_clear (f)
5355 FRAME_PTR f;
5357 XTcondemn_scroll_bars (f);
5358 XTjudge_scroll_bars (f);
5362 /***********************************************************************
5363 Text Cursor
5364 ***********************************************************************/
5366 /* Set clipping for output in glyph row ROW. W is the window in which
5367 we operate. GC is the graphics context to set clipping in.
5369 ROW may be a text row or, e.g., a mode line. Text rows must be
5370 clipped to the interior of the window dedicated to text display,
5371 mode lines must be clipped to the whole window. */
5373 static void
5374 x_clip_to_row (w, row, area, gc)
5375 struct window *w;
5376 struct glyph_row *row;
5377 int area;
5378 GC gc;
5380 struct frame *f = XFRAME (WINDOW_FRAME (w));
5381 Rect clip_rect;
5382 int window_x, window_y, window_width;
5384 window_box (w, area, &window_x, &window_y, &window_width, 0);
5386 clip_rect.left = window_x;
5387 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5388 clip_rect.top = max (clip_rect.top, window_y);
5389 clip_rect.right = clip_rect.left + window_width;
5390 clip_rect.bottom = clip_rect.top + row->visible_height;
5392 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
5396 /* Draw a hollow box cursor on window W in glyph row ROW. */
5398 static void
5399 x_draw_hollow_cursor (w, row)
5400 struct window *w;
5401 struct glyph_row *row;
5403 struct frame *f = XFRAME (WINDOW_FRAME (w));
5404 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5405 Display *dpy = FRAME_MAC_DISPLAY (f);
5406 int x, y, wd, h;
5407 XGCValues xgcv;
5408 struct glyph *cursor_glyph;
5409 GC gc;
5411 /* Get the glyph the cursor is on. If we can't tell because
5412 the current matrix is invalid or such, give up. */
5413 cursor_glyph = get_phys_cursor_glyph (w);
5414 if (cursor_glyph == NULL)
5415 return;
5417 /* Compute frame-relative coordinates for phys cursor. */
5418 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h);
5419 wd = w->phys_cursor_width;
5421 /* The foreground of cursor_gc is typically the same as the normal
5422 background color, which can cause the cursor box to be invisible. */
5423 xgcv.foreground = f->output_data.mac->cursor_pixel;
5424 if (dpyinfo->scratch_cursor_gc)
5425 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5426 else
5427 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5428 GCForeground, &xgcv);
5429 gc = dpyinfo->scratch_cursor_gc;
5431 /* Set clipping, draw the rectangle, and reset clipping again. */
5432 x_clip_to_row (w, row, TEXT_AREA, gc);
5433 mac_draw_rectangle (f, gc, x, y, wd, h - 1);
5434 mac_reset_clip_rectangles (dpy, gc);
5438 /* Draw a bar cursor on window W in glyph row ROW.
5440 Implementation note: One would like to draw a bar cursor with an
5441 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5442 Unfortunately, I didn't find a font yet that has this property set.
5443 --gerd. */
5445 static void
5446 x_draw_bar_cursor (w, row, width, kind)
5447 struct window *w;
5448 struct glyph_row *row;
5449 int width;
5450 enum text_cursor_kinds kind;
5452 struct frame *f = XFRAME (w->frame);
5453 struct glyph *cursor_glyph;
5455 /* If cursor is out of bounds, don't draw garbage. This can happen
5456 in mini-buffer windows when switching between echo area glyphs
5457 and mini-buffer. */
5458 cursor_glyph = get_phys_cursor_glyph (w);
5459 if (cursor_glyph == NULL)
5460 return;
5462 /* If on an image, draw like a normal cursor. That's usually better
5463 visible than drawing a bar, esp. if the image is large so that
5464 the bar might not be in the window. */
5465 if (cursor_glyph->type == IMAGE_GLYPH)
5467 struct glyph_row *row;
5468 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5469 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5471 else
5473 Display *dpy = FRAME_MAC_DISPLAY (f);
5474 Window window = FRAME_MAC_WINDOW (f);
5475 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5476 unsigned long mask = GCForeground | GCBackground;
5477 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5478 XGCValues xgcv;
5480 /* If the glyph's background equals the color we normally draw
5481 the bar cursor in, the bar cursor in its normal color is
5482 invisible. Use the glyph's foreground color instead in this
5483 case, on the assumption that the glyph's colors are chosen so
5484 that the glyph is legible. */
5485 if (face->background == f->output_data.mac->cursor_pixel)
5486 xgcv.background = xgcv.foreground = face->foreground;
5487 else
5488 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5490 if (gc)
5491 XChangeGC (dpy, gc, mask, &xgcv);
5492 else
5494 gc = XCreateGC (dpy, window, mask, &xgcv);
5495 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5498 if (width < 0)
5499 width = FRAME_CURSOR_WIDTH (f);
5500 width = min (cursor_glyph->pixel_width, width);
5502 w->phys_cursor_width = width;
5503 x_clip_to_row (w, row, TEXT_AREA, gc);
5505 if (kind == BAR_CURSOR)
5506 mac_fill_rectangle (f, gc,
5507 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5508 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5509 width, row->height);
5510 else
5511 mac_fill_rectangle (f, gc,
5512 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5513 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5514 row->height - width),
5515 cursor_glyph->pixel_width,
5516 width);
5518 mac_reset_clip_rectangles (dpy, gc);
5523 /* RIF: Define cursor CURSOR on frame F. */
5525 static void
5526 mac_define_frame_cursor (f, cursor)
5527 struct frame *f;
5528 Cursor cursor;
5530 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5532 if (dpyinfo->x_focus_frame == f)
5533 SetThemeCursor (cursor);
5537 /* RIF: Clear area on frame F. */
5539 static void
5540 mac_clear_frame_area (f, x, y, width, height)
5541 struct frame *f;
5542 int x, y, width, height;
5544 mac_clear_area (f, x, y, width, height);
5548 /* RIF: Draw cursor on window W. */
5550 static void
5551 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5552 struct window *w;
5553 struct glyph_row *glyph_row;
5554 int x, y;
5555 int cursor_type, cursor_width;
5556 int on_p, active_p;
5558 if (on_p)
5560 w->phys_cursor_type = cursor_type;
5561 w->phys_cursor_on_p = 1;
5563 if (glyph_row->exact_window_width_line_p
5564 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5566 glyph_row->cursor_in_fringe_p = 1;
5567 draw_fringe_bitmap (w, glyph_row, 0);
5569 else
5570 switch (cursor_type)
5572 case HOLLOW_BOX_CURSOR:
5573 x_draw_hollow_cursor (w, glyph_row);
5574 break;
5576 case FILLED_BOX_CURSOR:
5577 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5578 break;
5580 case BAR_CURSOR:
5581 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5582 break;
5584 case HBAR_CURSOR:
5585 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5586 break;
5588 case NO_CURSOR:
5589 w->phys_cursor_width = 0;
5590 break;
5592 default:
5593 abort ();
5599 /* Icons. */
5601 #if 0 /* MAC_TODO: no icon support yet. */
5603 x_bitmap_icon (f, icon)
5604 struct frame *f;
5605 Lisp_Object icon;
5607 HANDLE hicon;
5609 if (FRAME_W32_WINDOW (f) == 0)
5610 return 1;
5612 if (NILP (icon))
5613 hicon = LoadIcon (hinst, EMACS_CLASS);
5614 else if (STRINGP (icon))
5615 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5616 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5617 else if (SYMBOLP (icon))
5619 LPCTSTR name;
5621 if (EQ (icon, intern ("application")))
5622 name = (LPCTSTR) IDI_APPLICATION;
5623 else if (EQ (icon, intern ("hand")))
5624 name = (LPCTSTR) IDI_HAND;
5625 else if (EQ (icon, intern ("question")))
5626 name = (LPCTSTR) IDI_QUESTION;
5627 else if (EQ (icon, intern ("exclamation")))
5628 name = (LPCTSTR) IDI_EXCLAMATION;
5629 else if (EQ (icon, intern ("asterisk")))
5630 name = (LPCTSTR) IDI_ASTERISK;
5631 else if (EQ (icon, intern ("winlogo")))
5632 name = (LPCTSTR) IDI_WINLOGO;
5633 else
5634 return 1;
5636 hicon = LoadIcon (NULL, name);
5638 else
5639 return 1;
5641 if (hicon == NULL)
5642 return 1;
5644 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5645 (LPARAM) hicon);
5647 return 0;
5649 #endif /* MAC_TODO */
5651 /************************************************************************
5652 Handling X errors
5653 ************************************************************************/
5655 /* Display Error Handling functions not used on W32. Listing them here
5656 helps diff stay in step when comparing w32term.c with xterm.c.
5658 x_error_catcher (display, error)
5659 x_catch_errors (dpy)
5660 x_catch_errors_unwind (old_val)
5661 x_check_errors (dpy, format)
5662 x_had_errors_p (dpy)
5663 x_clear_errors (dpy)
5664 x_uncatch_errors (dpy, count)
5665 x_trace_wire ()
5666 x_connection_signal (signalnum)
5667 x_connection_closed (dpy, error_message)
5668 x_error_quitter (display, error)
5669 x_error_handler (display, error)
5670 x_io_error_quitter (display)
5675 /* Changing the font of the frame. */
5677 /* Give frame F the font named FONTNAME as its default font, and
5678 return the full name of that font. FONTNAME may be a wildcard
5679 pattern; in that case, we choose some font that fits the pattern.
5680 The return value shows which font we chose. */
5682 Lisp_Object
5683 x_new_font (f, fontname)
5684 struct frame *f;
5685 register char *fontname;
5687 struct font_info *fontp
5688 = FS_LOAD_FONT (f, 0, fontname, -1);
5690 if (!fontp)
5691 return Qnil;
5693 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5694 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5695 FRAME_FONTSET (f) = -1;
5697 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5698 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5699 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5701 compute_fringe_widths (f, 1);
5703 /* Compute the scroll bar width in character columns. */
5704 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5706 int wid = FRAME_COLUMN_WIDTH (f);
5707 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5708 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5710 else
5712 int wid = FRAME_COLUMN_WIDTH (f);
5713 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5716 /* Now make the frame display the given font. */
5717 if (FRAME_MAC_WINDOW (f) != 0)
5719 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5720 FRAME_FONT (f));
5721 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5722 FRAME_FONT (f));
5723 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5724 FRAME_FONT (f));
5726 /* Don't change the size of a tip frame; there's no point in
5727 doing it because it's done in Fx_show_tip, and it leads to
5728 problems because the tip frame has no widget. */
5729 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5730 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5733 return build_string (fontp->full_name);
5736 /* Give frame F the fontset named FONTSETNAME as its default font, and
5737 return the full name of that fontset. FONTSETNAME may be a wildcard
5738 pattern; in that case, we choose some fontset that fits the pattern.
5739 The return value shows which fontset we chose. */
5741 Lisp_Object
5742 x_new_fontset (f, fontsetname)
5743 struct frame *f;
5744 char *fontsetname;
5746 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5747 Lisp_Object result;
5749 if (fontset < 0)
5750 return Qnil;
5752 if (FRAME_FONTSET (f) == fontset)
5753 /* This fontset is already set in frame F. There's nothing more
5754 to do. */
5755 return fontset_name (fontset);
5757 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5759 if (!STRINGP (result))
5760 /* Can't load ASCII font. */
5761 return Qnil;
5763 /* Since x_new_font doesn't update any fontset information, do it now. */
5764 FRAME_FONTSET (f) = fontset;
5766 return build_string (fontsetname);
5770 /***********************************************************************
5771 TODO: W32 Input Methods
5772 ***********************************************************************/
5773 /* Listing missing functions from xterm.c helps diff stay in step.
5775 xim_destroy_callback (xim, client_data, call_data)
5776 xim_open_dpy (dpyinfo, resource_name)
5777 struct xim_inst_t
5778 xim_instantiate_callback (display, client_data, call_data)
5779 xim_initialize (dpyinfo, resource_name)
5780 xim_close_dpy (dpyinfo)
5785 void
5786 mac_get_window_bounds (f, inner, outer)
5787 struct frame *f;
5788 Rect *inner, *outer;
5790 #if TARGET_API_MAC_CARBON
5791 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5792 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5793 #else /* not TARGET_API_MAC_CARBON */
5794 RgnHandle region = NewRgn ();
5796 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5797 *inner = (*region)->rgnBBox;
5798 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5799 *outer = (*region)->rgnBBox;
5800 DisposeRgn (region);
5801 #endif /* not TARGET_API_MAC_CARBON */
5806 /* Calculate the absolute position in frame F
5807 from its current recorded position values and gravity. */
5809 void
5810 x_calc_absolute_position (f)
5811 struct frame *f;
5813 int width_diff = 0, height_diff = 0;
5814 int flags = f->size_hint_flags;
5815 Rect inner, outer;
5817 /* We have nothing to do if the current position
5818 is already for the top-left corner. */
5819 if (! ((flags & XNegative) || (flags & YNegative)))
5820 return;
5822 /* Find the offsets of the outside upper-left corner of
5823 the inner window, with respect to the outer window. */
5824 mac_get_window_bounds (f, &inner, &outer);
5826 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5827 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5829 /* Treat negative positions as relative to the leftmost bottommost
5830 position that fits on the screen. */
5831 if (flags & XNegative)
5832 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5833 - width_diff
5834 - FRAME_PIXEL_WIDTH (f)
5835 + f->left_pos);
5837 if (flags & YNegative)
5838 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5839 - height_diff
5840 - FRAME_PIXEL_HEIGHT (f)
5841 + f->top_pos);
5843 /* The left_pos and top_pos
5844 are now relative to the top and left screen edges,
5845 so the flags should correspond. */
5846 f->size_hint_flags &= ~ (XNegative | YNegative);
5849 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5850 to really change the position, and 0 when calling from
5851 x_make_frame_visible (in that case, XOFF and YOFF are the current
5852 position values). It is -1 when calling from x_set_frame_parameters,
5853 which means, do adjust for borders but don't change the gravity. */
5855 void
5856 x_set_offset (f, xoff, yoff, change_gravity)
5857 struct frame *f;
5858 register int xoff, yoff;
5859 int change_gravity;
5861 if (change_gravity > 0)
5863 f->top_pos = yoff;
5864 f->left_pos = xoff;
5865 f->size_hint_flags &= ~ (XNegative | YNegative);
5866 if (xoff < 0)
5867 f->size_hint_flags |= XNegative;
5868 if (yoff < 0)
5869 f->size_hint_flags |= YNegative;
5870 f->win_gravity = NorthWestGravity;
5872 x_calc_absolute_position (f);
5874 BLOCK_INPUT;
5875 x_wm_set_size_hint (f, (long) 0, 0);
5877 #if TARGET_API_MAC_CARBON
5878 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5879 /* If the title bar is completely outside the screen, adjust the
5880 position. */
5881 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5882 kWindowConstrainMoveRegardlessOfFit
5883 | kWindowConstrainAllowPartial, NULL, NULL);
5884 x_real_positions (f, &f->left_pos, &f->top_pos);
5885 #else
5887 Rect inner, outer, screen_rect, dummy;
5888 RgnHandle region = NewRgn ();
5890 mac_get_window_bounds (f, &inner, &outer);
5891 f->x_pixels_diff = inner.left - outer.left;
5892 f->y_pixels_diff = inner.top - outer.top;
5893 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5894 f->top_pos + f->y_pixels_diff, false);
5896 /* If the title bar is completely outside the screen, adjust the
5897 position. The variable `outer' holds the title bar rectangle.
5898 The variable `inner' holds slightly smaller one than `outer',
5899 so that the calculation of overlapping may not become too
5900 strict. */
5901 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5902 outer = (*region)->rgnBBox;
5903 DisposeRgn (region);
5904 inner = outer;
5905 InsetRect (&inner, 8, 8);
5906 screen_rect = qd.screenBits.bounds;
5907 screen_rect.top += GetMBarHeight ();
5909 if (!SectRect (&inner, &screen_rect, &dummy))
5911 if (inner.right <= screen_rect.left)
5912 f->left_pos = screen_rect.left;
5913 else if (inner.left >= screen_rect.right)
5914 f->left_pos = screen_rect.right - (outer.right - outer.left);
5916 if (inner.bottom <= screen_rect.top)
5917 f->top_pos = screen_rect.top;
5918 else if (inner.top >= screen_rect.bottom)
5919 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5921 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5922 f->top_pos + f->y_pixels_diff, false);
5925 #endif
5927 UNBLOCK_INPUT;
5930 /* Call this to change the size of frame F's x-window.
5931 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5932 for this size change and subsequent size changes.
5933 Otherwise we leave the window gravity unchanged. */
5935 void
5936 x_set_window_size (f, change_gravity, cols, rows)
5937 struct frame *f;
5938 int change_gravity;
5939 int cols, rows;
5941 int pixelwidth, pixelheight;
5943 BLOCK_INPUT;
5945 check_frame_size (f, &rows, &cols);
5946 f->scroll_bar_actual_width
5947 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5949 compute_fringe_widths (f, 0);
5951 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5952 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5954 f->win_gravity = NorthWestGravity;
5955 x_wm_set_size_hint (f, (long) 0, 0);
5957 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5958 #if TARGET_API_MAC_CARBON
5959 if (f->output_data.mac->hourglass_control)
5961 #if USE_CG_DRAWING
5962 mac_prepare_for_quickdraw (f);
5963 #endif
5964 MoveControl (f->output_data.mac->hourglass_control,
5965 pixelwidth - HOURGLASS_WIDTH, 0);
5967 #endif
5969 /* Now, strictly speaking, we can't be sure that this is accurate,
5970 but the window manager will get around to dealing with the size
5971 change request eventually, and we'll hear how it went when the
5972 ConfigureNotify event gets here.
5974 We could just not bother storing any of this information here,
5975 and let the ConfigureNotify event set everything up, but that
5976 might be kind of confusing to the Lisp code, since size changes
5977 wouldn't be reported in the frame parameters until some random
5978 point in the future when the ConfigureNotify event arrives.
5980 We pass 1 for DELAY since we can't run Lisp code inside of
5981 a BLOCK_INPUT. */
5982 change_frame_size (f, rows, cols, 0, 1, 0);
5983 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5984 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5986 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5987 receive in the ConfigureNotify event; if we get what we asked
5988 for, then the event won't cause the screen to become garbaged, so
5989 we have to make sure to do it here. */
5990 SET_FRAME_GARBAGED (f);
5992 XFlush (FRAME_X_DISPLAY (f));
5994 /* If cursor was outside the new size, mark it as off. */
5995 mark_window_cursors_off (XWINDOW (f->root_window));
5997 /* Clear out any recollection of where the mouse highlighting was,
5998 since it might be in a place that's outside the new frame size.
5999 Actually checking whether it is outside is a pain in the neck,
6000 so don't try--just let the highlighting be done afresh with new size. */
6001 cancel_mouse_face (f);
6003 UNBLOCK_INPUT;
6006 /* Mouse warping. */
6008 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
6010 void
6011 x_set_mouse_position (f, x, y)
6012 struct frame *f;
6013 int x, y;
6015 int pix_x, pix_y;
6017 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
6018 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
6020 if (pix_x < 0) pix_x = 0;
6021 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
6023 if (pix_y < 0) pix_y = 0;
6024 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
6026 x_set_mouse_pixel_position (f, pix_x, pix_y);
6029 void
6030 x_set_mouse_pixel_position (f, pix_x, pix_y)
6031 struct frame *f;
6032 int pix_x, pix_y;
6034 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
6035 BLOCK_INPUT;
6037 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
6038 0, 0, 0, 0, pix_x, pix_y);
6039 UNBLOCK_INPUT;
6040 #endif
6043 /* focus shifting, raising and lowering. */
6045 void
6046 x_focus_on_frame (f)
6047 struct frame *f;
6049 #if 0 /* This proves to be unpleasant. */
6050 x_raise_frame (f);
6051 #endif
6052 #if 0
6053 /* I don't think that the ICCCM allows programs to do things like this
6054 without the interaction of the window manager. Whatever you end up
6055 doing with this code, do it to x_unfocus_frame too. */
6056 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6057 RevertToPointerRoot, CurrentTime);
6058 #endif /* ! 0 */
6061 void
6062 x_unfocus_frame (f)
6063 struct frame *f;
6067 /* Raise frame F. */
6069 void
6070 x_raise_frame (f)
6071 struct frame *f;
6073 if (f->async_visible)
6075 BLOCK_INPUT;
6076 BringToFront (FRAME_MAC_WINDOW (f));
6077 UNBLOCK_INPUT;
6081 /* Lower frame F. */
6083 void
6084 x_lower_frame (f)
6085 struct frame *f;
6087 if (f->async_visible)
6089 BLOCK_INPUT;
6090 SendBehind (FRAME_MAC_WINDOW (f), NULL);
6091 UNBLOCK_INPUT;
6095 static void
6096 XTframe_raise_lower (f, raise_flag)
6097 FRAME_PTR f;
6098 int raise_flag;
6100 if (raise_flag)
6101 x_raise_frame (f);
6102 else
6103 x_lower_frame (f);
6106 /* Change of visibility. */
6108 static void
6109 mac_handle_visibility_change (f)
6110 struct frame *f;
6112 WindowPtr wp = FRAME_MAC_WINDOW (f);
6113 int visible = 0, iconified = 0;
6114 struct input_event buf;
6116 if (IsWindowVisible (wp))
6118 if (IsWindowCollapsed (wp))
6119 iconified = 1;
6120 else
6121 visible = 1;
6124 if (!f->async_visible && visible)
6126 if (f->iconified)
6128 /* wait_reading_process_output will notice this and update
6129 the frame's display structures. If we were made
6130 invisible, we should not set garbaged, because that stops
6131 redrawing on Update events. */
6132 SET_FRAME_GARBAGED (f);
6134 EVENT_INIT (buf);
6135 buf.kind = DEICONIFY_EVENT;
6136 XSETFRAME (buf.frame_or_window, f);
6137 buf.arg = Qnil;
6138 kbd_buffer_store_event (&buf);
6140 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
6141 /* Force a redisplay sooner or later to update the
6142 frame titles in case this is the second frame. */
6143 record_asynch_buffer_change ();
6145 else if (f->async_visible && !visible)
6146 if (iconified)
6148 EVENT_INIT (buf);
6149 buf.kind = ICONIFY_EVENT;
6150 XSETFRAME (buf.frame_or_window, f);
6151 buf.arg = Qnil;
6152 kbd_buffer_store_event (&buf);
6155 f->async_visible = visible;
6156 f->async_iconified = iconified;
6159 /* This tries to wait until the frame is really visible.
6160 However, if the window manager asks the user where to position
6161 the frame, this will return before the user finishes doing that.
6162 The frame will not actually be visible at that time,
6163 but it will become visible later when the window manager
6164 finishes with it. */
6166 void
6167 x_make_frame_visible (f)
6168 struct frame *f;
6170 BLOCK_INPUT;
6172 if (! FRAME_VISIBLE_P (f))
6174 /* We test FRAME_GARBAGED_P here to make sure we don't
6175 call x_set_offset a second time
6176 if we get to x_make_frame_visible a second time
6177 before the window gets really visible. */
6178 if (! FRAME_ICONIFIED_P (f)
6179 && ! f->output_data.mac->asked_for_visible)
6181 #if TARGET_API_MAC_CARBON
6182 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
6184 struct frame *sf = SELECTED_FRAME ();
6185 if (!FRAME_MAC_P (sf))
6186 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
6187 kWindowCenterOnMainScreen);
6188 else
6189 RepositionWindow (FRAME_MAC_WINDOW (f),
6190 FRAME_MAC_WINDOW (sf),
6191 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6192 kWindowCascadeStartAtParentWindowScreen
6193 #else
6194 kWindowCascadeOnParentWindowScreen
6195 #endif
6197 x_real_positions (f, &f->left_pos, &f->top_pos);
6199 else
6200 #endif
6201 x_set_offset (f, f->left_pos, f->top_pos, 0);
6204 f->output_data.mac->asked_for_visible = 1;
6206 CollapseWindow (FRAME_MAC_WINDOW (f), false);
6207 ShowWindow (FRAME_MAC_WINDOW (f));
6210 XFlush (FRAME_MAC_DISPLAY (f));
6212 /* Synchronize to ensure Emacs knows the frame is visible
6213 before we do anything else. We do this loop with input not blocked
6214 so that incoming events are handled. */
6216 Lisp_Object frame;
6217 int count;
6219 /* This must come after we set COUNT. */
6220 UNBLOCK_INPUT;
6222 XSETFRAME (frame, f);
6224 /* Wait until the frame is visible. Process X events until a
6225 MapNotify event has been seen, or until we think we won't get a
6226 MapNotify at all.. */
6227 for (count = input_signal_count + 10;
6228 input_signal_count < count && !FRAME_VISIBLE_P (f);)
6230 /* Force processing of queued events. */
6231 x_sync (f);
6233 /* Machines that do polling rather than SIGIO have been
6234 observed to go into a busy-wait here. So we'll fake an
6235 alarm signal to let the handler know that there's something
6236 to be read. We used to raise a real alarm, but it seems
6237 that the handler isn't always enabled here. This is
6238 probably a bug. */
6239 if (input_polling_used ())
6241 /* It could be confusing if a real alarm arrives while
6242 processing the fake one. Turn it off and let the
6243 handler reset it. */
6244 extern void poll_for_input_1 P_ ((void));
6245 int old_poll_suppress_count = poll_suppress_count;
6246 poll_suppress_count = 1;
6247 poll_for_input_1 ();
6248 poll_suppress_count = old_poll_suppress_count;
6251 /* See if a MapNotify event has been processed. */
6252 FRAME_SAMPLE_VISIBILITY (f);
6257 /* Change from mapped state to withdrawn state. */
6259 /* Make the frame visible (mapped and not iconified). */
6261 void
6262 x_make_frame_invisible (f)
6263 struct frame *f;
6265 /* A deactivate event does not occur when the last visible frame is
6266 made invisible. So if we clear the highlight here, it will not
6267 be rehighlighted when it is made visible. */
6268 #if 0
6269 /* Don't keep the highlight on an invisible frame. */
6270 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6271 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6272 #endif
6274 BLOCK_INPUT;
6276 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6277 that the current position of the window is user-specified, rather than
6278 program-specified, so that when the window is mapped again, it will be
6279 placed at the same location, without forcing the user to position it
6280 by hand again (they have already done that once for this window.) */
6281 x_wm_set_size_hint (f, (long) 0, 1);
6283 HideWindow (FRAME_MAC_WINDOW (f));
6285 UNBLOCK_INPUT;
6287 #if !USE_CARBON_EVENTS
6288 mac_handle_visibility_change (f);
6289 #endif
6292 /* Change window state from mapped to iconified. */
6294 void
6295 x_iconify_frame (f)
6296 struct frame *f;
6298 OSErr err;
6300 /* A deactivate event does not occur when the last visible frame is
6301 iconified. So if we clear the highlight here, it will not be
6302 rehighlighted when it is deiconified. */
6303 #if 0
6304 /* Don't keep the highlight on an invisible frame. */
6305 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6306 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6307 #endif
6309 if (f->async_iconified)
6310 return;
6312 BLOCK_INPUT;
6314 FRAME_SAMPLE_VISIBILITY (f);
6316 if (! FRAME_VISIBLE_P (f))
6317 ShowWindow (FRAME_MAC_WINDOW (f));
6319 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
6321 UNBLOCK_INPUT;
6323 if (err != noErr)
6324 error ("Can't notify window manager of iconification");
6326 #if !USE_CARBON_EVENTS
6327 mac_handle_visibility_change (f);
6328 #endif
6332 /* Free X resources of frame F. */
6334 void
6335 x_free_frame_resources (f)
6336 struct frame *f;
6338 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6339 WindowPtr wp = FRAME_MAC_WINDOW (f);
6341 BLOCK_INPUT;
6343 if (wp != tip_window)
6344 remove_window_handler (wp);
6346 DisposeWindow (wp);
6347 if (wp == tip_window)
6348 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6349 closed' event. So we reset tip_window here. */
6350 tip_window = NULL;
6352 free_frame_menubar (f);
6354 if (FRAME_FACE_CACHE (f))
6355 free_frame_faces (f);
6357 x_free_gcs (f);
6359 if (FRAME_SIZE_HINTS (f))
6360 xfree (FRAME_SIZE_HINTS (f));
6362 #if TARGET_API_MAC_CARBON
6363 if (FRAME_FILE_NAME (f))
6364 xfree (FRAME_FILE_NAME (f));
6365 #endif
6367 xfree (f->output_data.mac);
6368 f->output_data.mac = NULL;
6370 if (f == dpyinfo->x_focus_frame)
6372 dpyinfo->x_focus_frame = 0;
6373 #if USE_MAC_FONT_PANEL
6374 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0);
6375 #endif
6377 if (f == dpyinfo->x_focus_event_frame)
6378 dpyinfo->x_focus_event_frame = 0;
6379 if (f == dpyinfo->x_highlight_frame)
6380 dpyinfo->x_highlight_frame = 0;
6382 if (f == dpyinfo->mouse_face_mouse_frame)
6384 dpyinfo->mouse_face_beg_row
6385 = dpyinfo->mouse_face_beg_col = -1;
6386 dpyinfo->mouse_face_end_row
6387 = dpyinfo->mouse_face_end_col = -1;
6388 dpyinfo->mouse_face_window = Qnil;
6389 dpyinfo->mouse_face_deferred_gc = 0;
6390 dpyinfo->mouse_face_mouse_frame = 0;
6393 UNBLOCK_INPUT;
6397 /* Destroy the X window of frame F. */
6399 void
6400 x_destroy_window (f)
6401 struct frame *f;
6403 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6405 x_free_frame_resources (f);
6407 dpyinfo->reference_count--;
6411 /* Setting window manager hints. */
6413 /* Set the normal size hints for the window manager, for frame F.
6414 FLAGS is the flags word to use--or 0 meaning preserve the flags
6415 that the window now has.
6416 If USER_POSITION is nonzero, we set the USPosition
6417 flag (this is useful when FLAGS is 0). */
6418 void
6419 x_wm_set_size_hint (f, flags, user_position)
6420 struct frame *f;
6421 long flags;
6422 int user_position;
6424 int base_width, base_height, width_inc, height_inc;
6425 int min_rows = 0, min_cols = 0;
6426 XSizeHints *size_hints;
6428 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6429 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6430 width_inc = FRAME_COLUMN_WIDTH (f);
6431 height_inc = FRAME_LINE_HEIGHT (f);
6433 check_frame_size (f, &min_rows, &min_cols);
6435 size_hints = FRAME_SIZE_HINTS (f);
6436 if (size_hints == NULL)
6438 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6439 bzero (size_hints, sizeof (XSizeHints));
6442 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6443 size_hints->width_inc = width_inc;
6444 size_hints->height_inc = height_inc;
6445 size_hints->min_width = base_width + min_cols * width_inc;
6446 size_hints->min_height = base_height + min_rows * height_inc;
6447 size_hints->base_width = base_width;
6448 size_hints->base_height = base_height;
6450 if (flags)
6451 size_hints->flags = flags;
6452 else if (user_position)
6454 size_hints->flags &= ~ PPosition;
6455 size_hints->flags |= USPosition;
6459 #if 0 /* MAC_TODO: hide application instead of iconify? */
6460 /* Used for IconicState or NormalState */
6462 void
6463 x_wm_set_window_state (f, state)
6464 struct frame *f;
6465 int state;
6467 #ifdef USE_X_TOOLKIT
6468 Arg al[1];
6470 XtSetArg (al[0], XtNinitialState, state);
6471 XtSetValues (f->output_data.x->widget, al, 1);
6472 #else /* not USE_X_TOOLKIT */
6473 Window window = FRAME_X_WINDOW (f);
6475 f->output_data.x->wm_hints.flags |= StateHint;
6476 f->output_data.x->wm_hints.initial_state = state;
6478 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6479 #endif /* not USE_X_TOOLKIT */
6482 void
6483 x_wm_set_icon_pixmap (f, pixmap_id)
6484 struct frame *f;
6485 int pixmap_id;
6487 Pixmap icon_pixmap;
6489 #ifndef USE_X_TOOLKIT
6490 Window window = FRAME_X_WINDOW (f);
6491 #endif
6493 if (pixmap_id > 0)
6495 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6496 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6498 else
6500 /* It seems there is no way to turn off use of an icon pixmap.
6501 The following line does it, only if no icon has yet been created,
6502 for some window managers. But with mwm it crashes.
6503 Some people say it should clear the IconPixmapHint bit in this case,
6504 but that doesn't work, and the X consortium said it isn't the
6505 right thing at all. Since there is no way to win,
6506 best to explicitly give up. */
6507 #if 0
6508 f->output_data.x->wm_hints.icon_pixmap = None;
6509 #else
6510 return;
6511 #endif
6514 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6517 Arg al[1];
6518 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6519 XtSetValues (f->output_data.x->widget, al, 1);
6522 #else /* not USE_X_TOOLKIT */
6524 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6525 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6527 #endif /* not USE_X_TOOLKIT */
6530 #endif /* MAC_TODO */
6532 void
6533 x_wm_set_icon_position (f, icon_x, icon_y)
6534 struct frame *f;
6535 int icon_x, icon_y;
6537 #if 0 /* MAC_TODO: no icons on Mac */
6538 #ifdef USE_X_TOOLKIT
6539 Window window = XtWindow (f->output_data.x->widget);
6540 #else
6541 Window window = FRAME_X_WINDOW (f);
6542 #endif
6544 f->output_data.x->wm_hints.flags |= IconPositionHint;
6545 f->output_data.x->wm_hints.icon_x = icon_x;
6546 f->output_data.x->wm_hints.icon_y = icon_y;
6548 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6549 #endif /* MAC_TODO */
6553 /***********************************************************************
6554 XLFD Pattern Match
6555 ***********************************************************************/
6557 /* An XLFD pattern is divided into blocks delimited by '*'. This
6558 structure holds information for each block. */
6559 struct xlfdpat_block
6561 /* Length of the pattern string in this block. Non-zero except for
6562 the first and the last blocks. */
6563 int len;
6565 /* Pattern string except the last character in this block. The last
6566 character is replaced with NUL in order to use it as a
6567 sentinel. */
6568 unsigned char *pattern;
6570 /* Last character of the pattern string. Must not be '?'. */
6571 unsigned char last_char;
6573 /* One of the tables for the Boyer-Moore string search. It
6574 specifies the number of positions to proceed for each character
6575 with which the match fails. */
6576 int skip[256];
6578 /* The skip value for the last character in the above `skip' is
6579 assigned to `infinity' in order to simplify a loop condition.
6580 The original value is saved here. */
6581 int last_char_skip;
6584 struct xlfdpat
6586 /* Normalized pattern string. "Normalized" means that capital
6587 letters are lowered, blocks are not empty except the first and
6588 the last ones, and trailing '?'s in a block that is not the last
6589 one are moved to the next one. The last character in each block
6590 is replaced with NUL. */
6591 unsigned char *buf;
6593 /* Number of characters except '*'s and trailing '?'s in the
6594 normalized pattern string. */
6595 int nchars;
6597 /* Number of trailing '?'s in the normalized pattern string. */
6598 int trailing_anychars;
6600 /* Number of blocks and information for each block. The latter is
6601 NULL if the pattern is exact (no '*' or '?' in it). */
6602 int nblocks;
6603 struct xlfdpat_block *blocks;
6606 static void
6607 xlfdpat_destroy (pat)
6608 struct xlfdpat *pat;
6610 if (pat)
6612 if (pat->buf)
6614 if (pat->blocks)
6615 xfree (pat->blocks);
6616 xfree (pat->buf);
6618 xfree (pat);
6622 static struct xlfdpat *
6623 xlfdpat_create (pattern)
6624 char *pattern;
6626 struct xlfdpat *pat;
6627 int nblocks, i, skip;
6628 unsigned char last_char, *p, *q, *anychar_head;
6629 struct xlfdpat_block *blk;
6631 pat = xmalloc (sizeof (struct xlfdpat));
6632 pat->buf = xmalloc (strlen (pattern) + 1);
6634 /* Normalize the pattern string and store it to `pat->buf'. */
6635 nblocks = 0;
6636 anychar_head = NULL;
6637 q = pat->buf;
6638 last_char = '\0';
6639 for (p = pattern; *p; p++)
6641 unsigned char c = *p;
6643 if (c == '*')
6644 if (last_char == '*')
6645 /* ...a** -> ...a* */
6646 continue;
6647 else
6649 if (last_char == '?')
6651 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6652 /* ...*??* -> ...*?? */
6653 continue;
6654 else
6655 /* ...a??* -> ...a*?? */
6657 *anychar_head++ = '*';
6658 c = '?';
6661 nblocks++;
6663 else if (c == '?')
6665 if (last_char != '?')
6666 anychar_head = q;
6668 else
6669 /* On Mac OS X 10.3, tolower also converts non-ASCII
6670 characters for some locales. */
6671 if (isascii (c))
6672 c = tolower (c);
6674 *q++ = last_char = c;
6676 *q = '\0';
6677 nblocks++;
6678 pat->nblocks = nblocks;
6679 if (last_char != '?')
6680 pat->trailing_anychars = 0;
6681 else
6683 pat->trailing_anychars = q - anychar_head;
6684 q = anychar_head;
6686 pat->nchars = q - pat->buf - (nblocks - 1);
6688 if (anychar_head == NULL && nblocks == 1)
6690 /* The pattern is exact. */
6691 pat->blocks = NULL;
6692 return pat;
6695 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6697 /* Divide the normalized pattern into blocks. */
6698 p = pat->buf;
6699 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6701 blk->pattern = p;
6702 while (*p != '*')
6703 p++;
6704 blk->len = p - blk->pattern;
6705 p++;
6707 blk->pattern = p;
6708 blk->len = q - blk->pattern;
6710 /* Setup a table for the Boyer-Moore string search. */
6711 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6712 if (blk->len != 0)
6714 blk->last_char = blk->pattern[blk->len - 1];
6715 blk->pattern[blk->len - 1] = '\0';
6717 for (skip = 1; skip < blk->len; skip++)
6718 if (blk->pattern[blk->len - skip - 1] == '?')
6719 break;
6721 for (i = 0; i < 256; i++)
6722 blk->skip[i] = skip;
6724 p = blk->pattern + (blk->len - skip);
6725 while (--skip > 0)
6726 blk->skip[*p++] = skip;
6728 blk->last_char_skip = blk->skip[blk->last_char];
6731 return pat;
6734 static INLINE int
6735 xlfdpat_exact_p (pat)
6736 struct xlfdpat *pat;
6738 return pat->blocks == NULL;
6741 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6742 that the pattern in *BLK matches with its prefix. Return NULL
6743 there is no such strings. STRING must be lowered in advance. */
6745 static char *
6746 xlfdpat_block_match_1 (blk, string, start_max)
6747 struct xlfdpat_block *blk;
6748 unsigned char *string;
6749 int start_max;
6751 int start, infinity;
6752 unsigned char *p, *s;
6754 xassert (blk->len > 0);
6755 xassert (start_max + blk->len <= strlen (string));
6756 xassert (blk->last_char != '?');
6758 /* See the comments in the function `boyer_moore' (search.c) for the
6759 use of `infinity'. */
6760 infinity = start_max + blk->len + 1;
6761 blk->skip[blk->last_char] = infinity;
6763 start = 0;
6766 /* Check the last character of the pattern. */
6767 s = string + blk->len - 1;
6770 start += blk->skip[*(s + start)];
6772 while (start <= start_max);
6774 if (start < infinity)
6775 /* Couldn't find the last character. */
6776 return NULL;
6778 /* No less than `infinity' means we could find the last
6779 character at `s[start - infinity]'. */
6780 start -= infinity;
6782 /* Check the remaining characters. We prefer making no-'?'
6783 cases faster because the use of '?' is really rare. */
6784 p = blk->pattern;
6785 s = string + start;
6788 while (*p++ == *s++)
6791 while (*(p - 1) == '?');
6793 if (*(p - 1) == '\0')
6794 /* Matched. */
6795 return string + start;
6797 /* Didn't match. */
6798 start += blk->last_char_skip;
6800 while (start <= start_max);
6802 return NULL;
6805 #define xlfdpat_block_match(b, s, m) \
6806 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6807 : xlfdpat_block_match_1 (b, s, m))
6809 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6810 matches with STRING. STRING must be lowered in advance. */
6812 static int
6813 xlfdpat_match (pat, string)
6814 struct xlfdpat *pat;
6815 unsigned char *string;
6817 int str_len, nblocks, i, start_max;
6818 struct xlfdpat_block *blk;
6819 unsigned char *s;
6821 xassert (pat->nblocks > 0);
6823 if (xlfdpat_exact_p (pat))
6824 return strcmp (pat->buf, string) == 0;
6826 /* The number of the characters in the string must not be smaller
6827 than that in the pattern. */
6828 str_len = strlen (string);
6829 if (str_len < pat->nchars + pat->trailing_anychars)
6830 return 0;
6832 /* Chop off the trailing '?'s. */
6833 str_len -= pat->trailing_anychars;
6835 /* The last block. When it is non-empty, it must match at the end
6836 of the string. */
6837 nblocks = pat->nblocks;
6838 blk = pat->blocks + (nblocks - 1);
6839 if (nblocks == 1)
6840 /* The last block is also the first one. */
6841 return (str_len == blk->len
6842 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6843 else if (blk->len != 0)
6844 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6845 return 0;
6847 /* The first block. When it is non-empty, it must match at the
6848 beginning of the string. */
6849 blk = pat->blocks;
6850 if (blk->len != 0)
6852 s = xlfdpat_block_match (blk, string, 0);
6853 if (s == NULL)
6854 return 0;
6855 string = s + blk->len;
6858 /* The rest of the blocks. */
6859 start_max = str_len - pat->nchars;
6860 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6862 s = xlfdpat_block_match (blk, string, start_max);
6863 if (s == NULL)
6864 return 0;
6865 start_max -= s - string;
6866 string = s + blk->len;
6869 return 1;
6873 /***********************************************************************
6874 Fonts
6875 ***********************************************************************/
6877 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6879 struct font_info *
6880 x_get_font_info (f, font_idx)
6881 FRAME_PTR f;
6882 int font_idx;
6884 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6887 /* the global font name table */
6888 static char **font_name_table = NULL;
6889 static int font_name_table_size = 0;
6890 static int font_name_count = 0;
6892 /* Alist linking font family names to Font Manager font family
6893 references (which can also be used as QuickDraw font IDs). We use
6894 an alist because hash tables are not ready when the terminal frame
6895 for Mac OS Classic is created. */
6896 static Lisp_Object fm_font_family_alist;
6897 #if USE_ATSUI
6898 /* Hash table linking font family names to ATSU font IDs. */
6899 static Lisp_Object atsu_font_id_hash;
6900 static Lisp_Object Vmac_atsu_font_table;
6901 extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic;
6902 #endif
6904 /* Alist linking character set strings to Mac text encoding and Emacs
6905 coding system. */
6906 static Lisp_Object Vmac_charset_info_alist;
6908 static Lisp_Object
6909 create_text_encoding_info_alist ()
6911 Lisp_Object result = Qnil, rest;
6913 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6915 Lisp_Object charset_info = XCAR (rest);
6916 Lisp_Object charset, coding_system, text_encoding;
6917 Lisp_Object existing_info;
6919 if (!(CONSP (charset_info)
6920 && STRINGP (charset = XCAR (charset_info))
6921 && CONSP (XCDR (charset_info))
6922 && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
6923 && CONSP (XCDR (XCDR (charset_info)))
6924 && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
6925 continue;
6927 existing_info = assq_no_quit (text_encoding, result);
6928 if (NILP (existing_info))
6929 result = Fcons (list3 (text_encoding, coding_system, charset),
6930 result);
6931 else
6932 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6933 XSETCDR (XCDR (existing_info),
6934 Fcons (charset, XCDR (XCDR (existing_info))));
6937 return result;
6941 static void
6942 decode_mac_font_name (name, size, coding_system)
6943 char *name;
6944 int size;
6945 Lisp_Object coding_system;
6947 struct coding_system coding;
6948 char *buf, *p;
6950 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6952 for (p = name; *p; p++)
6953 if (!isascii (*p) || iscntrl (*p))
6954 break;
6956 if (*p)
6958 setup_coding_system (coding_system, &coding);
6959 coding.src_multibyte = 0;
6960 coding.dst_multibyte = 1;
6961 coding.mode |= CODING_MODE_LAST_BLOCK;
6962 coding.composing = COMPOSITION_DISABLED;
6963 buf = (char *) alloca (size);
6965 decode_coding (&coding, name, buf, strlen (name), size - 1);
6966 bcopy (buf, name, coding.produced);
6967 name[coding.produced] = '\0';
6971 /* If there's just one occurrence of '-' in the family name, it is
6972 replaced with '_'. (More than one occurrence of '-' means a
6973 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6974 p = strchr (name, '-');
6975 if (p && strchr (p + 1, '-') == NULL)
6976 *p = '_';
6978 for (p = name; *p; p++)
6979 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6980 for some locales. */
6981 if (isascii (*p))
6982 *p = tolower (*p);
6986 static char *
6987 mac_to_x_fontname (name, size, style, charset)
6988 char *name;
6989 int size;
6990 Style style;
6991 char *charset;
6993 Str31 foundry, cs;
6994 Str255 family;
6995 char xf[256], *result;
6996 unsigned char *p;
6998 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6999 charset = cs;
7000 else
7002 strcpy(foundry, "Apple");
7003 strcpy(family, name);
7006 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
7007 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
7008 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
7010 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
7011 sprintf (result, "-%s-%s-%s", foundry, family, xf);
7012 for (p = result; *p; p++)
7013 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7014 for some locales. */
7015 if (isascii (*p))
7016 *p = tolower (*p);
7017 return result;
7021 /* Parse fully-specified and instantiated X11 font spec XF, and store
7022 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
7023 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
7024 caller must allocate at least 256 and 32 bytes respectively. For
7025 ordinary Mac fonts, the value stored to FAMILY should just be their
7026 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
7027 intlfonts collection contain their charset designation in their
7028 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
7029 types of font names are handled accordingly. */
7031 const int kDefaultFontSize = 12;
7033 static int
7034 parse_x_font_name (xf, family, size, style, charset)
7035 char *xf, *family;
7036 int *size;
7037 Style *style;
7038 char *charset;
7040 Str31 foundry, weight;
7041 int point_size, avgwidth;
7042 char slant[2], *p;
7044 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7045 foundry, family, weight, slant, size,
7046 &point_size, &avgwidth, charset) != 8
7047 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
7048 foundry, family, weight, slant, size,
7049 &point_size, &avgwidth, charset) != 8)
7050 return 0;
7052 if (*size == 0)
7054 if (point_size > 0)
7055 *size = point_size / 10;
7056 else if (avgwidth > 0)
7057 *size = avgwidth / 10;
7059 if (*size == 0)
7060 *size = kDefaultFontSize;
7062 *style = normal;
7063 if (strcmp (weight, "bold") == 0)
7064 *style |= bold;
7065 if (*slant == 'i')
7066 *style |= italic;
7068 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
7070 int foundry_len = strlen (foundry), family_len = strlen (family);
7072 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
7074 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
7075 but take overlap into account. */
7076 memmove (family + foundry_len + 1, family, family_len);
7077 memcpy (family, foundry, foundry_len);
7078 family[foundry_len] = '-';
7079 family[foundry_len + 1 + family_len] = '-';
7080 strcpy (family + foundry_len + 1 + family_len + 1, charset);
7082 else
7083 return 0;
7086 for (p = family; *p; p++)
7087 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
7088 for some locales. */
7089 if (isascii (*p))
7090 *p = tolower (*p);
7092 return 1;
7096 static void
7097 add_font_name_table_entry (char *font_name)
7099 if (font_name_table_size == 0)
7101 font_name_table_size = 256;
7102 font_name_table = (char **)
7103 xmalloc (font_name_table_size * sizeof (char *));
7105 else if (font_name_count + 1 >= font_name_table_size)
7107 font_name_table_size *= 2;
7108 font_name_table = (char **)
7109 xrealloc (font_name_table,
7110 font_name_table_size * sizeof (char *));
7113 font_name_table[font_name_count++] = font_name;
7116 static void
7117 add_mac_font_name (name, size, style, charset)
7118 char *name;
7119 int size;
7120 Style style;
7121 char *charset;
7123 if (size > 0)
7124 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset));
7125 else
7127 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset));
7128 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset));
7129 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset));
7130 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold,
7131 charset));
7135 /* Sets up the table font_name_table to contain the list of all fonts
7136 in the system the first time the table is used so that the Resource
7137 Manager need not be accessed every time this information is
7138 needed. */
7140 static void
7141 init_font_name_table ()
7143 #if TARGET_API_MAC_CARBON
7144 FMFontFamilyIterator ffi;
7145 FMFontFamilyInstanceIterator ffii;
7146 FMFontFamily ff;
7147 Lisp_Object text_encoding_info_alist;
7148 struct gcpro gcpro1;
7150 text_encoding_info_alist = create_text_encoding_info_alist ();
7152 #if USE_ATSUI
7153 #if USE_CG_TEXT_DRAWING
7154 init_cg_text_anti_aliasing_threshold ();
7155 #endif
7156 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
7157 text_encoding_info_alist)))
7159 OSErr err;
7160 struct Lisp_Hash_Table *h;
7161 unsigned hash_code;
7162 ItemCount nfonts, i;
7163 ATSUFontID *font_ids = NULL;
7164 Ptr name;
7165 ByteCount name_len;
7166 Lisp_Object family;
7168 atsu_font_id_hash =
7169 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
7170 make_float (DEFAULT_REHASH_SIZE),
7171 make_float (DEFAULT_REHASH_THRESHOLD),
7172 Qnil, Qnil, Qnil);;
7173 h = XHASH_TABLE (atsu_font_id_hash);
7175 err = ATSUFontCount (&nfonts);
7176 if (err == noErr)
7178 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
7179 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
7181 if (err == noErr)
7182 for (i = 0; i < nfonts; i++)
7184 err = ATSUFindFontName (font_ids[i], kFontFamilyName,
7185 kFontMacintoshPlatform, kFontNoScript,
7186 kFontNoLanguage, 0, NULL, &name_len, NULL);
7187 if (err != noErr)
7188 continue;
7189 name = xmalloc (name_len + 1);
7190 name[name_len] = '\0';
7191 err = ATSUFindFontName (font_ids[i], kFontFamilyName,
7192 kFontMacintoshPlatform, kFontNoScript,
7193 kFontNoLanguage, name_len, name,
7194 NULL, NULL);
7195 if (err == noErr)
7197 FMFontFamily ff;
7198 FMFontStyle style = normal;
7200 decode_mac_font_name (name, name_len + 1, Qnil);
7201 family = make_unibyte_string (name, name_len);
7202 FMGetFontFamilyInstanceFromFont (font_ids[i], &ff, &style);
7203 Fputhash (make_unibyte_string ((char *)(font_ids + i),
7204 sizeof (ATSUFontID)),
7205 Fcons (QCfamily,
7206 list5 (family,
7207 QCweight,
7208 style & bold ? Qbold : Qnormal,
7209 QCslant,
7210 style & italic ? Qitalic : Qnormal)),
7211 Vmac_atsu_font_table);
7212 if (*name != '.'
7213 && hash_lookup (h, family, &hash_code) < 0)
7215 add_mac_font_name (name, 0, normal, "iso10646-1");
7216 hash_put (h, family, long_to_cons (font_ids[i]),
7217 hash_code);
7220 xfree (name);
7222 if (font_ids)
7223 xfree (font_ids);
7225 #endif
7227 /* Create a dummy instance iterator here to avoid creating and
7228 destroying it in the loop. */
7229 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
7230 return;
7231 /* Create an iterator to enumerate the font families. */
7232 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
7233 != noErr)
7235 FMDisposeFontFamilyInstanceIterator (&ffii);
7236 return;
7239 GCPRO1 (text_encoding_info_alist);
7241 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
7243 Str255 name;
7244 FMFont font;
7245 FMFontStyle style;
7246 FMFontSize size;
7247 TextEncoding encoding;
7248 TextEncodingBase sc;
7249 Lisp_Object text_encoding_info, family;
7251 if (FMGetFontFamilyName (ff, name) != noErr)
7252 continue;
7253 p2cstr (name);
7254 if (*name == '.')
7255 continue;
7257 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
7258 continue;
7259 sc = GetTextEncodingBase (encoding);
7260 text_encoding_info = assq_no_quit (make_number (sc),
7261 text_encoding_info_alist);
7262 if (NILP (text_encoding_info))
7263 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
7264 text_encoding_info_alist);
7265 decode_mac_font_name (name, sizeof (name),
7266 XCAR (XCDR (text_encoding_info)));
7267 family = build_string (name);
7268 if (!NILP (Fassoc (family, fm_font_family_alist)))
7269 continue;
7270 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)),
7271 fm_font_family_alist);
7273 /* Point the instance iterator at the current font family. */
7274 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7275 continue;
7277 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7278 == noErr)
7280 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7282 if (size > 0 || style == normal)
7283 for (; !NILP (rest); rest = XCDR (rest))
7284 add_mac_font_name (name, size, style, SDATA (XCAR (rest)));
7288 UNGCPRO;
7290 /* Dispose of the iterators. */
7291 FMDisposeFontFamilyIterator (&ffi);
7292 FMDisposeFontFamilyInstanceIterator (&ffii);
7293 #else /* !TARGET_API_MAC_CARBON */
7294 GrafPtr port;
7295 SInt16 fontnum, old_fontnum;
7296 int num_mac_fonts = CountResources('FOND');
7297 int i, j;
7298 Handle font_handle, font_handle_2;
7299 short id, scriptcode;
7300 ResType type;
7301 Str255 name;
7302 struct FontAssoc *fat;
7303 struct AsscEntry *assc_entry;
7304 Lisp_Object text_encoding_info_alist, text_encoding_info, family;
7305 struct gcpro gcpro1;
7307 GetPort (&port); /* save the current font number used */
7308 old_fontnum = port->txFont;
7310 text_encoding_info_alist = create_text_encoding_info_alist ();
7312 GCPRO1 (text_encoding_info_alist);
7314 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7316 font_handle = GetIndResource ('FOND', i);
7317 if (!font_handle)
7318 continue;
7320 GetResInfo (font_handle, &id, &type, name);
7321 GetFNum (name, &fontnum);
7322 p2cstr (name);
7323 if (fontnum == 0 || *name == '.')
7324 continue;
7326 TextFont (fontnum);
7327 scriptcode = FontToScript (fontnum);
7328 text_encoding_info = assq_no_quit (make_number (scriptcode),
7329 text_encoding_info_alist);
7330 if (NILP (text_encoding_info))
7331 text_encoding_info = assq_no_quit (make_number (smRoman),
7332 text_encoding_info_alist);
7333 decode_mac_font_name (name, sizeof (name),
7334 XCAR (XCDR (text_encoding_info)));
7335 family = build_string (name);
7336 if (!NILP (Fassoc (family, fm_font_family_alist)))
7337 continue;
7338 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)),
7339 fm_font_family_alist);
7342 HLock (font_handle);
7344 if (GetResourceSizeOnDisk (font_handle)
7345 >= sizeof (struct FamRec))
7347 fat = (struct FontAssoc *) (*font_handle
7348 + sizeof (struct FamRec));
7349 assc_entry
7350 = (struct AsscEntry *) (*font_handle
7351 + sizeof (struct FamRec)
7352 + sizeof (struct FontAssoc));
7354 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7356 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7358 for (; !NILP (rest); rest = XCDR (rest))
7359 add_mac_font_name (name, assc_entry->fontSize,
7360 assc_entry->fontStyle,
7361 SDATA (XCAR (rest)));
7365 HUnlock (font_handle);
7366 font_handle_2 = GetNextFOND (font_handle);
7367 ReleaseResource (font_handle);
7368 font_handle = font_handle_2;
7370 while (ResError () == noErr && font_handle);
7373 UNGCPRO;
7375 TextFont (old_fontnum);
7376 #endif /* !TARGET_API_MAC_CARBON */
7380 void
7381 mac_clear_font_name_table ()
7383 int i;
7385 for (i = 0; i < font_name_count; i++)
7386 xfree (font_name_table[i]);
7387 xfree (font_name_table);
7388 font_name_table = NULL;
7389 font_name_table_size = font_name_count = 0;
7390 fm_font_family_alist = Qnil;
7394 enum xlfd_scalable_field_index
7396 XLFD_SCL_PIXEL_SIZE,
7397 XLFD_SCL_POINT_SIZE,
7398 XLFD_SCL_AVGWIDTH,
7399 XLFD_SCL_LAST
7402 static int xlfd_scalable_fields[] =
7404 6, /* PIXEL_SIZE */
7405 7, /* POINT_SIZE */
7406 11, /* AVGWIDTH */
7410 static Lisp_Object
7411 mac_do_list_fonts (pattern, maxnames)
7412 char *pattern;
7413 int maxnames;
7415 int i, n_fonts = 0;
7416 Lisp_Object font_list = Qnil;
7417 struct xlfdpat *pat;
7418 char *scaled, *ptr;
7419 int scl_val[XLFD_SCL_LAST], *field, *val;
7420 int exact;
7422 if (font_name_table == NULL) /* Initialize when first used. */
7423 init_font_name_table ();
7425 for (i = 0; i < XLFD_SCL_LAST; i++)
7426 scl_val[i] = -1;
7428 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7429 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7430 fonts are scaled according to the specified size. */
7431 ptr = pattern;
7432 i = 0;
7433 field = xlfd_scalable_fields;
7434 val = scl_val;
7435 if (*ptr == '-')
7438 ptr++;
7439 if (i == *field)
7441 if ('0' <= *ptr && *ptr <= '9')
7443 *val = *ptr++ - '0';
7444 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7445 *val = *val * 10 + *ptr++ - '0';
7446 if (*ptr != '-')
7447 *val = -1;
7449 field++;
7450 val++;
7452 ptr = strchr (ptr, '-');
7453 i++;
7455 while (ptr && i < 14);
7457 if (i == 14 && ptr == NULL)
7459 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7460 scl_val[XLFD_SCL_PIXEL_SIZE] =
7461 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7462 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7463 : -1));
7464 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7465 scl_val[XLFD_SCL_POINT_SIZE] =
7466 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7467 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7468 : -1));
7469 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7470 scl_val[XLFD_SCL_AVGWIDTH] =
7471 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7472 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7473 : -1));
7475 else
7476 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7478 pat = xlfdpat_create (pattern);
7479 if (pat == NULL)
7480 return Qnil;
7482 exact = xlfdpat_exact_p (pat);
7484 for (i = 0; i < font_name_count; i++)
7486 if (xlfdpat_match (pat, font_name_table[i]))
7488 font_list = Fcons (build_string (font_name_table[i]), font_list);
7489 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7490 break;
7492 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7493 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7495 int former_len = ptr - font_name_table[i];
7497 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7498 memcpy (scaled, font_name_table[i], former_len);
7499 sprintf (scaled + former_len,
7500 "-%d-%d-72-72-m-%d-%s",
7501 scl_val[XLFD_SCL_PIXEL_SIZE],
7502 scl_val[XLFD_SCL_POINT_SIZE],
7503 scl_val[XLFD_SCL_AVGWIDTH],
7504 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7506 if (xlfdpat_match (pat, scaled))
7508 font_list = Fcons (build_string (scaled), font_list);
7509 xfree (scaled);
7510 if (exact || (maxnames > 0 && ++n_fonts >= maxnames))
7511 break;
7513 else
7514 xfree (scaled);
7518 xlfdpat_destroy (pat);
7520 return font_list;
7523 /* Return a list of names of available fonts matching PATTERN on frame F.
7525 Frame F null means we have not yet created any frame on Mac, and
7526 consult the first display in x_display_list. MAXNAMES sets a limit
7527 on how many fonts to match. */
7529 Lisp_Object
7530 x_list_fonts (f, pattern, size, maxnames)
7531 struct frame *f;
7532 Lisp_Object pattern;
7533 int size, maxnames;
7535 Lisp_Object list = Qnil, patterns, tem, key;
7536 struct mac_display_info *dpyinfo
7537 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7539 xassert (size <= 0);
7541 patterns = Fassoc (pattern, Valternate_fontname_alist);
7542 if (NILP (patterns))
7543 patterns = Fcons (pattern, Qnil);
7545 for (; CONSP (patterns); patterns = XCDR (patterns))
7547 pattern = XCAR (patterns);
7549 if (!STRINGP (pattern))
7550 continue;
7552 tem = XCAR (XCDR (dpyinfo->name_list_element));
7553 key = Fcons (pattern, make_number (maxnames));
7555 list = Fassoc (key, tem);
7556 if (!NILP (list))
7558 list = Fcdr_safe (list);
7559 /* We have a cashed list. Don't have to get the list again. */
7560 goto label_cached;
7563 BLOCK_INPUT;
7564 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7565 UNBLOCK_INPUT;
7567 /* MAC_TODO: add code for matching outline fonts here */
7569 /* Now store the result in the cache. */
7570 XSETCAR (XCDR (dpyinfo->name_list_element),
7571 Fcons (Fcons (key, list),
7572 XCAR (XCDR (dpyinfo->name_list_element))));
7574 label_cached:
7575 if (NILP (list)) continue; /* Try the remaining alternatives. */
7578 return list;
7582 #if GLYPH_DEBUG
7584 /* Check that FONT is valid on frame F. It is if it can be found in F's
7585 font table. */
7587 static void
7588 x_check_font (f, font)
7589 struct frame *f;
7590 XFontStruct *font;
7592 int i;
7593 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7595 xassert (font != NULL);
7597 for (i = 0; i < dpyinfo->n_fonts; i++)
7598 if (dpyinfo->font_table[i].name
7599 && font == dpyinfo->font_table[i].font)
7600 break;
7602 xassert (i < dpyinfo->n_fonts);
7605 #endif /* GLYPH_DEBUG != 0 */
7607 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7608 Note: There are (broken) X fonts out there with invalid XFontStruct
7609 min_bounds contents. For example, handa@etl.go.jp reports that
7610 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7611 have font->min_bounds.width == 0. */
7613 static INLINE void
7614 x_font_min_bounds (font, w, h)
7615 MacFontStruct *font;
7616 int *w, *h;
7618 *h = FONT_HEIGHT (font);
7619 *w = font->min_bounds.width;
7623 /* Compute the smallest character width and smallest font height over
7624 all fonts available on frame F. Set the members smallest_char_width
7625 and smallest_font_height in F's x_display_info structure to
7626 the values computed. Value is non-zero if smallest_font_height or
7627 smallest_char_width become smaller than they were before. */
7629 static int
7630 x_compute_min_glyph_bounds (f)
7631 struct frame *f;
7633 int i;
7634 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7635 MacFontStruct *font;
7636 int old_width = dpyinfo->smallest_char_width;
7637 int old_height = dpyinfo->smallest_font_height;
7639 dpyinfo->smallest_font_height = 100000;
7640 dpyinfo->smallest_char_width = 100000;
7642 for (i = 0; i < dpyinfo->n_fonts; ++i)
7643 if (dpyinfo->font_table[i].name)
7645 struct font_info *fontp = dpyinfo->font_table + i;
7646 int w, h;
7648 font = (MacFontStruct *) fontp->font;
7649 xassert (font != (MacFontStruct *) ~0);
7650 x_font_min_bounds (font, &w, &h);
7652 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7653 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7656 xassert (dpyinfo->smallest_char_width > 0
7657 && dpyinfo->smallest_font_height > 0);
7659 return (dpyinfo->n_fonts == 1
7660 || dpyinfo->smallest_char_width < old_width
7661 || dpyinfo->smallest_font_height < old_height);
7665 /* Determine whether given string is a fully-specified XLFD: all 14
7666 fields are present, none is '*'. */
7668 static int
7669 is_fully_specified_xlfd (char *p)
7671 int i;
7672 char *q;
7674 if (*p != '-')
7675 return 0;
7677 for (i = 0; i < 13; i++)
7679 q = strchr (p + 1, '-');
7680 if (q == NULL)
7681 return 0;
7682 if (q - p == 2 && *(p + 1) == '*')
7683 return 0;
7684 p = q;
7687 if (strchr (p + 1, '-') != NULL)
7688 return 0;
7690 if (*(p + 1) == '*' && *(p + 2) == '\0')
7691 return 0;
7693 return 1;
7697 /* XLoadQueryFont creates and returns an internal representation for a
7698 font in a MacFontStruct struct. There is really no concept
7699 corresponding to "loading" a font on the Mac. But we check its
7700 existence and find the font number and all other information for it
7701 and store them in the returned MacFontStruct. */
7703 static MacFontStruct *
7704 XLoadQueryFont (Display *dpy, char *fontname)
7706 int size;
7707 char *name;
7708 Str255 family;
7709 Str31 charset;
7710 SInt16 fontnum;
7711 #if USE_ATSUI
7712 static ATSUFontID font_id;
7713 ATSUStyle mac_style = NULL;
7714 #endif
7715 Style fontface;
7716 #if TARGET_API_MAC_CARBON
7717 TextEncoding encoding;
7718 int scriptcode;
7719 #else
7720 short scriptcode;
7721 #endif
7722 MacFontStruct *font;
7723 XCharStruct *space_bounds = NULL, *pcm;
7725 if (is_fully_specified_xlfd (fontname))
7726 name = fontname;
7727 else
7729 Lisp_Object matched_fonts;
7731 matched_fonts = mac_do_list_fonts (fontname, 1);
7732 if (NILP (matched_fonts))
7733 return NULL;
7734 name = SDATA (XCAR (matched_fonts));
7737 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7738 return NULL;
7740 #if USE_ATSUI
7741 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7743 OSErr err;
7744 ATSUAttributeTag tags[] = {kATSUFontTag, kATSUSizeTag,
7745 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7746 ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
7747 sizeof (Boolean), sizeof (Boolean)};
7748 static Fixed size_fixed;
7749 static Boolean bold_p, italic_p;
7750 ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
7751 &bold_p, &italic_p};
7752 ATSUFontFeatureType types[] = {kAllTypographicFeaturesType,
7753 kDiacriticsType};
7754 ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector,
7755 kDecomposeDiacriticsSelector};
7756 Lisp_Object font_id_cons;
7757 FMFontStyle style;
7759 font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
7760 atsu_font_id_hash, Qnil);
7761 if (NILP (font_id_cons))
7762 return NULL;
7763 font_id = cons_to_long (font_id_cons);
7764 size_fixed = Long2Fix (size);
7765 bold_p = (fontface & bold) != 0;
7766 italic_p = (fontface & italic) != 0;
7767 err = ATSUCreateStyle (&mac_style);
7768 if (err != noErr)
7769 return NULL;
7770 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7771 types, selectors);
7772 if (err != noErr)
7773 return NULL;
7774 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7775 tags, sizes, values);
7776 if (err != noErr)
7777 return NULL;
7778 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style);
7779 if (err != noErr)
7780 fontnum = -1;
7781 scriptcode = kTextEncodingMacUnicode;
7783 else
7784 #endif
7786 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7788 if (NILP (tmp))
7789 return NULL;
7790 fontnum = XINT (XCDR (tmp));
7791 #if TARGET_API_MAC_CARBON
7792 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7793 return NULL;
7794 scriptcode = GetTextEncodingBase (encoding);
7795 #else
7796 scriptcode = FontToScript (fontnum);
7797 #endif
7800 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7802 font->mac_fontnum = fontnum;
7803 font->mac_fontsize = size;
7804 font->mac_fontface = fontface;
7805 font->mac_scriptcode = scriptcode;
7806 #if USE_ATSUI
7807 font->mac_style = mac_style;
7808 #if USE_CG_TEXT_DRAWING
7809 font->cg_font = NULL;
7810 font->cg_glyphs = NULL;
7811 #endif
7812 #endif
7814 /* Apple Japanese (SJIS) font is listed as both
7815 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7816 (Roman script) in init_font_name_table (). The latter should be
7817 treated as a one-byte font. */
7818 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7819 font->mac_scriptcode = smRoman;
7821 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
7823 #if USE_ATSUI
7824 if (font->mac_style)
7826 OSErr err;
7827 UniChar c;
7829 font->min_byte1 = 0;
7830 font->max_byte1 = 0xff;
7831 font->min_char_or_byte2 = 0;
7832 font->max_char_or_byte2 = 0xff;
7834 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100);
7835 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100);
7836 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100);
7837 pcm_init (font->bounds.rows[0], 0x100);
7839 #if USE_CG_TEXT_DRAWING
7840 if (fontnum != -1)
7842 FMFontStyle style;
7843 ATSFontRef ats_font;
7845 err = FMGetFontFromFontFamilyInstance (fontnum, fontface,
7846 &font_id, &style);
7847 /* Use CG text drawing if italic/bold is not synthesized. */
7848 if (err == noErr && style == fontface)
7850 ats_font = FMGetATSFontRefFromFont (font_id);
7851 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7855 if (font->cg_font)
7857 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7858 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7860 #endif
7861 space_bounds = font->bounds.rows[0] + 0x20;
7862 err = mac_query_char_extents (font->mac_style, 0x20,
7863 &font->ascent, &font->descent,
7864 space_bounds,
7865 #if USE_CG_TEXT_DRAWING
7866 (font->cg_glyphs ? font->cg_glyphs + 0x20
7867 : NULL)
7868 #else
7869 NULL
7870 #endif
7872 if (err != noErr)
7874 mac_unload_font (&one_mac_display_info, font);
7875 return NULL;
7878 pcm = font->bounds.rows[0];
7879 for (c = 0x21; c <= 0xff; c++)
7881 if (c == 0xad)
7882 /* Soft hyphen is not supported in ATSUI. */
7883 continue;
7884 else if (c == 0x7f)
7886 c = 0x9f;
7887 continue;
7890 mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
7891 #if USE_CG_TEXT_DRAWING
7892 (font->cg_glyphs ? font->cg_glyphs + c
7893 : NULL)
7894 #else
7895 NULL
7896 #endif
7899 #if USE_CG_TEXT_DRAWING
7900 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
7902 /* Don't use CG text drawing if font substitution occurs in
7903 ASCII or Latin-1 characters. */
7904 CGFontRelease (font->cg_font);
7905 font->cg_font = NULL;
7906 xfree (font->cg_glyphs);
7907 font->cg_glyphs = NULL;
7909 #endif
7912 else
7913 #endif
7915 GrafPtr port;
7916 SInt16 old_fontnum, old_fontsize;
7917 Style old_fontface;
7918 FontInfo the_fontinfo;
7919 int is_two_byte_font;
7921 /* Save the current font number used. */
7922 GetPort (&port);
7923 #if TARGET_API_MAC_CARBON
7924 old_fontnum = GetPortTextFont (port);
7925 old_fontsize = GetPortTextSize (port);
7926 old_fontface = GetPortTextFace (port);
7927 #else
7928 old_fontnum = port->txFont;
7929 old_fontsize = port->txSize;
7930 old_fontface = port->txFace;
7931 #endif
7933 TextFont (fontnum);
7934 TextSize (size);
7935 TextFace (fontface);
7937 GetFontInfo (&the_fontinfo);
7939 font->ascent = the_fontinfo.ascent;
7940 font->descent = the_fontinfo.descent;
7942 is_two_byte_font = (font->mac_scriptcode == smJapanese
7943 || font->mac_scriptcode == smTradChinese
7944 || font->mac_scriptcode == smSimpChinese
7945 || font->mac_scriptcode == smKorean);
7947 if (is_two_byte_font)
7949 int char_width;
7951 font->min_byte1 = 0xa1;
7952 font->max_byte1 = 0xfe;
7953 font->min_char_or_byte2 = 0xa1;
7954 font->max_char_or_byte2 = 0xfe;
7956 /* Use the width of an "ideographic space" of that font
7957 because the_fontinfo.widMax returns the wrong width for
7958 some fonts. */
7959 switch (font->mac_scriptcode)
7961 case smJapanese:
7962 font->min_byte1 = 0x81;
7963 font->max_byte1 = 0xfc;
7964 font->min_char_or_byte2 = 0x40;
7965 font->max_char_or_byte2 = 0xfc;
7966 char_width = StringWidth("\p\x81\x40");
7967 break;
7968 case smTradChinese:
7969 font->min_char_or_byte2 = 0x40;
7970 char_width = StringWidth("\p\xa1\x40");
7971 break;
7972 case smSimpChinese:
7973 char_width = StringWidth("\p\xa1\xa1");
7974 break;
7975 case smKorean:
7976 char_width = StringWidth("\p\xa1\xa1");
7977 break;
7980 font->bounds.per_char = NULL;
7982 if (fontface & italic)
7983 font->max_bounds.rbearing = char_width + 1;
7984 else
7985 font->max_bounds.rbearing = char_width;
7986 font->max_bounds.lbearing = 0;
7987 font->max_bounds.width = char_width;
7988 font->max_bounds.ascent = the_fontinfo.ascent;
7989 font->max_bounds.descent = the_fontinfo.descent;
7991 font->min_bounds = font->max_bounds;
7993 else
7995 int c;
7997 font->min_byte1 = font->max_byte1 = 0;
7998 font->min_char_or_byte2 = 0x20;
7999 font->max_char_or_byte2 = 0xff;
8001 font->bounds.per_char =
8002 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
8003 bzero (font->bounds.per_char,
8004 sizeof (XCharStruct) * (0xff - 0x20 + 1));
8006 space_bounds = font->bounds.per_char;
8007 mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
8008 space_bounds, NULL);
8010 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
8011 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
8014 /* Restore previous font number, size and face. */
8015 TextFont (old_fontnum);
8016 TextSize (old_fontsize);
8017 TextFace (old_fontface);
8020 if (space_bounds)
8022 int c;
8024 font->min_bounds = font->max_bounds = *space_bounds;
8025 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
8026 if (pcm->width > 0)
8028 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
8029 pcm->lbearing);
8030 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
8031 pcm->rbearing);
8032 font->min_bounds.width = min (font->min_bounds.width,
8033 pcm->width);
8034 font->min_bounds.ascent = min (font->min_bounds.ascent,
8035 pcm->ascent);
8037 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
8038 pcm->lbearing);
8039 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
8040 pcm->rbearing);
8041 font->max_bounds.width = max (font->max_bounds.width,
8042 pcm->width);
8043 font->max_bounds.ascent = max (font->max_bounds.ascent,
8044 pcm->ascent);
8046 if (
8047 #if USE_ATSUI
8048 font->mac_style == NULL &&
8049 #endif
8050 font->max_bounds.width == font->min_bounds.width
8051 && font->min_bounds.lbearing >= 0
8052 && font->max_bounds.rbearing <= font->max_bounds.width)
8054 /* Fixed width and no overhangs. */
8055 xfree (font->bounds.per_char);
8056 font->bounds.per_char = NULL;
8060 #if !defined (MAC_OS8) || USE_ATSUI
8061 /* AppKit and WebKit do some adjustment to the heights of Courier,
8062 Helvetica, and Times. This only works on the environments where
8063 srcCopy text transfer mode is never used. */
8064 if (
8065 #ifdef MAC_OS8 /* implies USE_ATSUI */
8066 font->mac_style &&
8067 #endif
8068 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
8069 || strcmp (family, "times") == 0))
8070 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
8071 #endif
8073 return font;
8077 void
8078 mac_unload_font (dpyinfo, font)
8079 struct mac_display_info *dpyinfo;
8080 XFontStruct *font;
8082 xfree (font->full_name);
8083 #if USE_ATSUI
8084 if (font->mac_style)
8086 int i;
8088 for (i = font->min_byte1; i <= font->max_byte1; i++)
8089 if (font->bounds.rows[i])
8090 xfree (font->bounds.rows[i]);
8091 xfree (font->bounds.rows);
8092 ATSUDisposeStyle (font->mac_style);
8094 else
8095 #endif
8096 if (font->bounds.per_char)
8097 xfree (font->bounds.per_char);
8098 #if USE_CG_TEXT_DRAWING
8099 if (font->cg_font)
8100 CGFontRelease (font->cg_font);
8101 if (font->cg_glyphs)
8102 xfree (font->cg_glyphs);
8103 #endif
8104 xfree (font);
8108 /* Load font named FONTNAME of the size SIZE for frame F, and return a
8109 pointer to the structure font_info while allocating it dynamically.
8110 If SIZE is 0, load any size of font.
8111 If loading is failed, return NULL. */
8113 struct font_info *
8114 x_load_font (f, fontname, size)
8115 struct frame *f;
8116 register char *fontname;
8117 int size;
8119 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8120 Lisp_Object font_names;
8122 /* Get a list of all the fonts that match this name. Once we
8123 have a list of matching fonts, we compare them against the fonts
8124 we already have by comparing names. */
8125 font_names = x_list_fonts (f, build_string (fontname), size, 1);
8127 if (!NILP (font_names))
8129 Lisp_Object tail;
8130 int i;
8132 for (i = 0; i < dpyinfo->n_fonts; i++)
8133 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
8134 if (dpyinfo->font_table[i].name
8135 && (!strcmp (dpyinfo->font_table[i].name,
8136 SDATA (XCAR (tail)))
8137 || !strcmp (dpyinfo->font_table[i].full_name,
8138 SDATA (XCAR (tail)))))
8139 return (dpyinfo->font_table + i);
8141 else
8142 return NULL;
8144 /* Load the font and add it to the table. */
8146 struct MacFontStruct *font;
8147 struct font_info *fontp;
8148 int i;
8150 fontname = (char *) SDATA (XCAR (font_names));
8152 BLOCK_INPUT;
8153 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
8154 UNBLOCK_INPUT;
8155 if (!font)
8156 return NULL;
8158 /* Find a free slot in the font table. */
8159 for (i = 0; i < dpyinfo->n_fonts; ++i)
8160 if (dpyinfo->font_table[i].name == NULL)
8161 break;
8163 /* If no free slot found, maybe enlarge the font table. */
8164 if (i == dpyinfo->n_fonts
8165 && dpyinfo->n_fonts == dpyinfo->font_table_size)
8167 int sz;
8168 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
8169 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
8170 dpyinfo->font_table
8171 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
8174 fontp = dpyinfo->font_table + i;
8175 if (i == dpyinfo->n_fonts)
8176 ++dpyinfo->n_fonts;
8178 /* Now fill in the slots of *FONTP. */
8179 BLOCK_INPUT;
8180 bzero (fontp, sizeof (*fontp));
8181 fontp->font = font;
8182 fontp->font_idx = i;
8183 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
8184 bcopy (fontname, fontp->name, strlen (fontname) + 1);
8186 if (font->min_bounds.width == font->max_bounds.width)
8188 /* Fixed width font. */
8189 fontp->average_width = fontp->space_width = font->min_bounds.width;
8191 else
8193 XChar2b char2b;
8194 XCharStruct *pcm;
8196 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
8197 pcm = mac_per_char_metric (font, &char2b, 0);
8198 if (pcm)
8199 fontp->space_width = pcm->width;
8200 else
8201 fontp->space_width = FONT_WIDTH (font);
8203 if (pcm)
8205 int width = pcm->width;
8206 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
8207 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
8208 width += pcm->width;
8209 fontp->average_width = width / 95;
8211 else
8212 fontp->average_width = FONT_WIDTH (font);
8215 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
8216 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
8218 fontp->size = font->max_bounds.width;
8219 fontp->height = FONT_HEIGHT (font);
8221 /* For some font, ascent and descent in max_bounds field is
8222 larger than the above value. */
8223 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
8224 if (max_height > fontp->height)
8225 fontp->height = max_height;
8228 /* The slot `encoding' specifies how to map a character
8229 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8230 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8231 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8232 2:0xA020..0xFF7F). For the moment, we don't know which charset
8233 uses this font. So, we set information in fontp->encoding[1]
8234 which is never used by any charset. If mapping can't be
8235 decided, set FONT_ENCODING_NOT_DECIDED. */
8236 if (font->mac_scriptcode == smJapanese)
8237 fontp->encoding[1] = 4;
8238 else
8240 fontp->encoding[1]
8241 = (font->max_byte1 == 0
8242 /* 1-byte font */
8243 ? (font->min_char_or_byte2 < 0x80
8244 ? (font->max_char_or_byte2 < 0x80
8245 ? 0 /* 0x20..0x7F */
8246 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8247 : 1) /* 0xA0..0xFF */
8248 /* 2-byte font */
8249 : (font->min_byte1 < 0x80
8250 ? (font->max_byte1 < 0x80
8251 ? (font->min_char_or_byte2 < 0x80
8252 ? (font->max_char_or_byte2 < 0x80
8253 ? 0 /* 0x2020..0x7F7F */
8254 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8255 : 3) /* 0x20A0..0x7FFF */
8256 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8257 : (font->min_char_or_byte2 < 0x80
8258 ? (font->max_char_or_byte2 < 0x80
8259 ? 2 /* 0xA020..0xFF7F */
8260 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8261 : 1))); /* 0xA0A0..0xFFFF */
8264 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8265 fontp->baseline_offset
8266 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8267 ? (long) value : 0);
8268 fontp->relative_compose
8269 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8270 ? (long) value : 0);
8271 fontp->default_ascent
8272 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8273 ? (long) value : 0);
8274 #else
8275 fontp->baseline_offset = 0;
8276 fontp->relative_compose = 0;
8277 fontp->default_ascent = 0;
8278 #endif
8280 /* Set global flag fonts_changed_p to non-zero if the font loaded
8281 has a character with a smaller width than any other character
8282 before, or if the font loaded has a smaller height than any
8283 other font loaded before. If this happens, it will make a
8284 glyph matrix reallocation necessary. */
8285 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8286 UNBLOCK_INPUT;
8287 return fontp;
8292 /* Return a pointer to struct font_info of a font named FONTNAME for
8293 frame F. If no such font is loaded, return NULL. */
8295 struct font_info *
8296 x_query_font (f, fontname)
8297 struct frame *f;
8298 register char *fontname;
8300 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8301 int i;
8303 for (i = 0; i < dpyinfo->n_fonts; i++)
8304 if (dpyinfo->font_table[i].name
8305 && (!strcmp (dpyinfo->font_table[i].name, fontname)
8306 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
8307 return (dpyinfo->font_table + i);
8308 return NULL;
8312 /* Find a CCL program for a font specified by FONTP, and set the member
8313 `encoder' of the structure. */
8315 void
8316 x_find_ccl_program (fontp)
8317 struct font_info *fontp;
8319 Lisp_Object list, elt;
8321 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8323 elt = XCAR (list);
8324 if (CONSP (elt)
8325 && STRINGP (XCAR (elt))
8326 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8327 >= 0))
8328 break;
8330 if (! NILP (list))
8332 struct ccl_program *ccl
8333 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8335 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8336 xfree (ccl);
8337 else
8338 fontp->font_encoder = ccl;
8342 #if USE_MAC_FONT_PANEL
8343 /* Whether Font Panel has been shown before. The first call to font
8344 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
8345 slow. This variable is used for deferring such a call as much as
8346 possible. */
8347 static int font_panel_shown_p = 0;
8350 mac_font_panel_visible_p ()
8352 return font_panel_shown_p && FPIsFontPanelVisible ();
8355 OSStatus
8356 mac_show_hide_font_panel ()
8358 font_panel_shown_p = 1;
8360 return FPShowHideFontPanel ();
8363 OSStatus
8364 mac_set_font_info_for_selection (f, face_id, c)
8365 struct frame *f;
8366 int face_id, c;
8368 OSStatus err;
8369 EventTargetRef target = NULL;
8370 XFontStruct *font = NULL;
8372 if (!mac_font_panel_visible_p ())
8373 return noErr;
8375 if (f)
8377 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f));
8379 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0))
8381 struct face *face;
8383 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c);
8384 face = FACE_FROM_ID (f, face_id);
8385 font = face->font;
8389 if (font == NULL)
8390 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target);
8391 else
8393 if (font->mac_fontnum != -1)
8395 FontSelectionQDStyle qd_style;
8397 qd_style.version = kFontSelectionQDStyleVersionZero;
8398 qd_style.instance.fontFamily = font->mac_fontnum;
8399 qd_style.instance.fontStyle = font->mac_fontface;
8400 qd_style.size = font->mac_fontsize;
8401 qd_style.hasColor = false;
8403 err = SetFontInfoForSelection (kFontSelectionQDType,
8404 1, &qd_style, target);
8406 else
8407 err = SetFontInfoForSelection (kFontSelectionATSUIType,
8408 1, &font->mac_style, target);
8411 return err;
8413 #endif
8416 /* The Mac Event loop code */
8418 #if !TARGET_API_MAC_CARBON
8419 #include <Events.h>
8420 #include <Quickdraw.h>
8421 #include <Balloons.h>
8422 #include <Devices.h>
8423 #include <Fonts.h>
8424 #include <Gestalt.h>
8425 #include <Menus.h>
8426 #include <Processes.h>
8427 #include <Sound.h>
8428 #include <ToolUtils.h>
8429 #include <TextUtils.h>
8430 #include <Dialogs.h>
8431 #include <Script.h>
8432 #include <Types.h>
8433 #include <Resources.h>
8435 #if __MWERKS__
8436 #include <unix.h>
8437 #endif
8438 #endif /* ! TARGET_API_MAC_CARBON */
8440 #define M_APPLE 128
8441 #define I_ABOUT 1
8443 #define WINDOW_RESOURCE 128
8444 #define TERM_WINDOW_RESOURCE 129
8446 #define DEFAULT_NUM_COLS 80
8448 #define MIN_DOC_SIZE 64
8449 #define MAX_DOC_SIZE 32767
8451 #define EXTRA_STACK_ALLOC (256 * 1024)
8453 #define ARGV_STRING_LIST_ID 129
8454 #define ABOUT_ALERT_ID 128
8455 #define RAM_TOO_LARGE_ALERT_ID 129
8457 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8458 Lisp_Object Qreverse;
8461 /* Modifier associated with the control key, or nil to ignore. */
8462 Lisp_Object Vmac_control_modifier;
8464 /* Modifier associated with the option key, or nil to ignore. */
8465 Lisp_Object Vmac_option_modifier;
8467 /* Modifier associated with the command key, or nil to ignore. */
8468 Lisp_Object Vmac_command_modifier;
8470 /* Modifier associated with the function key, or nil to ignore. */
8471 Lisp_Object Vmac_function_modifier;
8473 /* True if the option and command modifiers should be used to emulate
8474 a three button mouse */
8475 Lisp_Object Vmac_emulate_three_button_mouse;
8477 #if USE_CARBON_EVENTS
8478 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8479 mouse-2, instead of mouse-3. */
8480 int mac_wheel_button_is_mouse_2;
8482 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8483 for processing before Emacs sees it. */
8484 int mac_pass_command_to_system;
8486 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8487 for processing before Emacs sees it. */
8488 int mac_pass_control_to_system;
8489 #endif
8491 /* Points to the variable `inev' in the function XTread_socket. It is
8492 used for passing an input event to the function back from
8493 Carbon/Apple event handlers. */
8494 static struct input_event *read_socket_inev = NULL;
8496 Point saved_menu_event_location;
8498 /* Apple Events */
8499 #if USE_CARBON_EVENTS
8500 static Lisp_Object Qhicommand;
8501 #ifdef MAC_OSX
8502 extern Lisp_Object Qwindow;
8503 static Lisp_Object Qtoolbar_switch_mode;
8504 #endif
8505 #if USE_MAC_FONT_PANEL
8506 extern Lisp_Object Qfont;
8507 static Lisp_Object Qpanel_closed, Qselection;
8508 #endif
8509 #if USE_MAC_TSM
8510 static TSMDocumentID tsm_document_id;
8511 static Lisp_Object Qtext_input;
8512 static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event;
8513 static Lisp_Object Vmac_ts_active_input_overlay;
8514 extern Lisp_Object Qbefore_string;
8515 #endif
8516 #endif
8517 extern int mac_ready_for_apple_events;
8518 extern Lisp_Object Qundefined;
8519 extern void init_apple_event_handler P_ ((void));
8520 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8521 Lisp_Object *, Lisp_Object *,
8522 Lisp_Object *));
8523 extern OSErr init_coercion_handler P_ ((void));
8525 /* Drag and Drop */
8526 OSErr install_drag_handler P_ ((WindowRef));
8527 void remove_drag_handler P_ ((WindowRef));
8529 #if USE_CARBON_EVENTS
8530 #ifdef MAC_OSX
8531 extern void init_service_handler ();
8532 static Lisp_Object Qservice, Qpaste, Qperform;
8533 #endif
8534 /* Window Event Handler */
8535 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
8536 EventRef, void *);
8537 #endif
8538 OSErr install_window_handler (WindowPtr);
8540 extern void init_emacs_passwd_dir ();
8541 extern int emacs_main (int, char **, char **);
8543 extern void initialize_applescript();
8544 extern void terminate_applescript();
8546 static unsigned int
8547 #if USE_CARBON_EVENTS
8548 mac_to_emacs_modifiers (UInt32 mods)
8549 #else
8550 mac_to_emacs_modifiers (EventModifiers mods)
8551 #endif
8553 unsigned int result = 0;
8554 if (mods & shiftKey)
8555 result |= shift_modifier;
8557 /* Deactivated to simplify configuration:
8558 if Vmac_option_modifier is non-NIL, we fully process the Option
8559 key. Otherwise, we only process it if an additional Ctrl or Command
8560 is pressed. That way the system may convert the character to a
8561 composed one.
8562 if ((mods & optionKey) &&
8563 (( !NILP(Vmac_option_modifier) ||
8564 ((mods & cmdKey) || (mods & controlKey))))) */
8566 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
8567 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8568 if (INTEGERP(val))
8569 result |= XUINT(val);
8571 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8572 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8573 if (INTEGERP(val))
8574 result |= XUINT(val);
8576 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8577 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8578 if (INTEGERP(val))
8579 result |= XUINT(val);
8582 #ifdef MAC_OSX
8583 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8584 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8585 if (INTEGERP(val))
8586 result |= XUINT(val);
8588 #endif
8590 return result;
8593 static int
8594 mac_get_emulated_btn ( UInt32 modifiers )
8596 int result = 0;
8597 if (!NILP (Vmac_emulate_three_button_mouse)) {
8598 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
8599 if (modifiers & cmdKey)
8600 result = cmdIs3 ? 2 : 1;
8601 else if (modifiers & optionKey)
8602 result = cmdIs3 ? 1 : 2;
8604 return result;
8607 #if USE_CARBON_EVENTS
8608 /* Obtains the event modifiers from the event ref and then calls
8609 mac_to_emacs_modifiers. */
8610 static UInt32
8611 mac_event_to_emacs_modifiers (EventRef eventRef)
8613 UInt32 mods = 0;
8614 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
8615 sizeof (UInt32), NULL, &mods);
8616 if (!NILP (Vmac_emulate_three_button_mouse) &&
8617 GetEventClass(eventRef) == kEventClassMouse)
8619 mods &= ~(optionKey | cmdKey);
8621 return mac_to_emacs_modifiers (mods);
8624 /* Given an event ref, return the code to use for the mouse button
8625 code in the emacs input_event. */
8626 static int
8627 mac_get_mouse_btn (EventRef ref)
8629 EventMouseButton result = kEventMouseButtonPrimary;
8630 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
8631 sizeof (EventMouseButton), NULL, &result);
8632 switch (result)
8634 case kEventMouseButtonPrimary:
8635 if (NILP (Vmac_emulate_three_button_mouse))
8636 return 0;
8637 else {
8638 UInt32 mods = 0;
8639 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
8640 sizeof (UInt32), NULL, &mods);
8641 return mac_get_emulated_btn(mods);
8643 case kEventMouseButtonSecondary:
8644 return mac_wheel_button_is_mouse_2 ? 2 : 1;
8645 case kEventMouseButtonTertiary:
8646 case 4: /* 4 is the number for the mouse wheel button */
8647 return mac_wheel_button_is_mouse_2 ? 1 : 2;
8648 default:
8649 return 0;
8653 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8654 events. However the click of the mouse wheel is not converted to a
8655 mouseDown or mouseUp event. Likewise for dead key down events.
8656 This calls ConvertEventRef, but then checks to see if it is a mouse
8657 up/down, or a dead key down carbon event that has not been
8658 converted, and if so, converts it by hand (to be picked up in the
8659 XTread_socket loop). */
8660 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
8662 OSStatus err;
8663 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
8665 if (result)
8666 return result;
8668 switch (GetEventClass (eventRef))
8670 case kEventClassMouse:
8671 switch (GetEventKind (eventRef))
8673 case kEventMouseDown:
8674 eventRec->what = mouseDown;
8675 result = 1;
8676 break;
8678 case kEventMouseUp:
8679 eventRec->what = mouseUp;
8680 result = 1;
8681 break;
8683 default:
8684 break;
8686 break;
8688 case kEventClassKeyboard:
8689 switch (GetEventKind (eventRef))
8691 case kEventRawKeyDown:
8693 unsigned char char_codes;
8694 UInt32 key_code;
8696 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes,
8697 typeChar, NULL, sizeof (char),
8698 NULL, &char_codes);
8699 if (err == noErr)
8700 err = GetEventParameter (eventRef, kEventParamKeyCode,
8701 typeUInt32, NULL, sizeof (UInt32),
8702 NULL, &key_code);
8703 if (err == noErr)
8705 eventRec->what = keyDown;
8706 eventRec->message = char_codes | ((key_code & 0xff) << 8);
8707 result = 1;
8710 break;
8712 default:
8713 break;
8715 break;
8717 default:
8718 break;
8721 if (result)
8723 /* Need where and when. */
8724 UInt32 mods = 0;
8726 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
8727 NULL, sizeof (Point), NULL, &eventRec->where);
8728 /* Use two step process because new event modifiers are 32-bit
8729 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8730 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
8731 NULL, sizeof (UInt32), NULL, &mods);
8732 eventRec->modifiers = mods;
8734 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
8737 return result;
8740 #endif
8742 #ifdef MAC_OS8
8743 static void
8744 do_get_menus (void)
8746 Handle menubar_handle;
8747 MenuHandle menu_handle;
8749 menubar_handle = GetNewMBar (128);
8750 if(menubar_handle == NULL)
8751 abort ();
8752 SetMenuBar (menubar_handle);
8753 DrawMenuBar ();
8755 #if !TARGET_API_MAC_CARBON
8756 menu_handle = GetMenuHandle (M_APPLE);
8757 if(menu_handle != NULL)
8758 AppendResMenu (menu_handle,'DRVR');
8759 else
8760 abort ();
8761 #endif
8765 static void
8766 do_init_managers (void)
8768 #if !TARGET_API_MAC_CARBON
8769 InitGraf (&qd.thePort);
8770 InitFonts ();
8771 FlushEvents (everyEvent, 0);
8772 InitWindows ();
8773 InitMenus ();
8774 TEInit ();
8775 InitDialogs (NULL);
8776 #endif /* !TARGET_API_MAC_CARBON */
8777 InitCursor ();
8779 #if !TARGET_API_MAC_CARBON
8780 /* set up some extra stack space for use by emacs */
8781 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
8783 /* MaxApplZone must be called for AppleScript to execute more
8784 complicated scripts */
8785 MaxApplZone ();
8786 MoreMasters ();
8787 #endif /* !TARGET_API_MAC_CARBON */
8790 static void
8791 do_check_ram_size (void)
8793 SInt32 physical_ram_size, logical_ram_size;
8795 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
8796 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
8797 || physical_ram_size > (1 << VALBITS)
8798 || logical_ram_size > (1 << VALBITS))
8800 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
8801 exit (1);
8804 #endif /* MAC_OS8 */
8806 static void
8807 do_window_update (WindowPtr win)
8809 struct frame *f = mac_window_to_frame (win);
8811 BeginUpdate (win);
8813 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8814 below. */
8815 if (win != tip_window)
8817 if (f->async_visible == 0)
8819 /* Update events may occur when a frame gets iconified. */
8820 #if 0
8821 f->async_visible = 1;
8822 f->async_iconified = 0;
8823 SET_FRAME_GARBAGED (f);
8824 #endif
8826 else
8828 Rect r;
8829 #if TARGET_API_MAC_CARBON
8830 RgnHandle region = NewRgn ();
8832 GetPortVisibleRegion (GetWindowPort (win), region);
8833 GetRegionBounds (region, &r);
8834 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
8835 UpdateControls (win, region);
8836 DisposeRgn (region);
8837 #else
8838 r = (*win->visRgn)->rgnBBox;
8839 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
8840 UpdateControls (win, win->visRgn);
8841 #endif
8845 EndUpdate (win);
8848 static int
8849 is_emacs_window (WindowPtr win)
8851 Lisp_Object tail, frame;
8853 if (!win)
8854 return 0;
8856 FOR_EACH_FRAME (tail, frame)
8857 if (FRAME_MAC_P (XFRAME (frame)))
8858 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
8859 return 1;
8861 return 0;
8864 static void
8865 do_app_resume ()
8867 #if USE_MAC_TSM
8868 ActivateTSMDocument (tsm_document_id);
8869 #endif
8872 static void
8873 do_app_suspend ()
8875 #if USE_MAC_TSM
8876 DeactivateTSMDocument (tsm_document_id);
8877 #endif
8881 static void
8882 do_apple_menu (SInt16 menu_item)
8884 #if !TARGET_API_MAC_CARBON
8885 Str255 item_name;
8886 SInt16 da_driver_refnum;
8888 if (menu_item == I_ABOUT)
8889 NoteAlert (ABOUT_ALERT_ID, NULL);
8890 else
8892 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
8893 da_driver_refnum = OpenDeskAcc (item_name);
8895 #endif /* !TARGET_API_MAC_CARBON */
8898 void
8899 do_menu_choice (SInt32 menu_choice)
8901 SInt16 menu_id, menu_item;
8903 menu_id = HiWord (menu_choice);
8904 menu_item = LoWord (menu_choice);
8906 switch (menu_id)
8908 case 0:
8909 break;
8911 case M_APPLE:
8912 do_apple_menu (menu_item);
8913 break;
8915 default:
8917 struct frame *f = mac_focus_frame (&one_mac_display_info);
8918 MenuHandle menu = GetMenuHandle (menu_id);
8919 if (menu)
8921 UInt32 refcon;
8923 GetMenuItemRefCon (menu, menu_item, &refcon);
8924 menubar_selection_callback (f, refcon);
8929 HiliteMenu (0);
8933 /* Handle drags in size box. Based on code contributed by Ben
8934 Mesander and IM - Window Manager A. */
8936 static void
8937 do_grow_window (WindowPtr w, EventRecord *e)
8939 Rect limit_rect;
8940 int rows, columns, width, height;
8941 struct frame *f = mac_window_to_frame (w);
8942 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
8943 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
8944 #if TARGET_API_MAC_CARBON
8945 Rect new_rect;
8946 #else
8947 long grow_size;
8948 #endif
8950 if (size_hints->flags & PMinSize)
8952 min_width = size_hints->min_width;
8953 min_height = size_hints->min_height;
8955 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
8957 #if TARGET_API_MAC_CARBON
8958 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
8959 return;
8960 height = new_rect.bottom - new_rect.top;
8961 width = new_rect.right - new_rect.left;
8962 #else
8963 grow_size = GrowWindow (w, e->where, &limit_rect);
8964 /* see if it really changed size */
8965 if (grow_size == 0)
8966 return;
8967 height = HiWord (grow_size);
8968 width = LoWord (grow_size);
8969 #endif
8971 if (width != FRAME_PIXEL_WIDTH (f)
8972 || height != FRAME_PIXEL_HEIGHT (f))
8974 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
8975 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
8977 x_set_window_size (f, 0, columns, rows);
8982 /* Handle clicks in zoom box. Calculation of "standard state" based
8983 on code in IM - Window Manager A and code contributed by Ben
8984 Mesander. The standard state of an Emacs window is 80-characters
8985 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8987 static void
8988 do_zoom_window (WindowPtr w, int zoom_in_or_out)
8990 Rect zoom_rect, port_rect;
8991 int columns, rows, width, height;
8992 struct frame *f = mac_window_to_frame (w);
8993 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8994 #if TARGET_API_MAC_CARBON
8995 Point standard_size;
8997 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
8998 standard_size.v = dpyinfo->height;
9000 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
9001 zoom_in_or_out = inZoomIn;
9002 else
9004 /* Adjust the standard size according to character boundaries. */
9006 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
9007 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
9008 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
9009 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9010 GetWindowBounds (w, kWindowContentRgn, &port_rect);
9011 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
9012 && port_rect.left == zoom_rect.left
9013 && port_rect.top == zoom_rect.top)
9014 zoom_in_or_out = inZoomIn;
9015 else
9016 zoom_in_or_out = inZoomOut;
9019 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
9020 #else /* not TARGET_API_MAC_CARBON */
9021 GrafPtr save_port;
9022 Point top_left;
9023 int w_title_height;
9025 GetPort (&save_port);
9027 SetPortWindowPort (w);
9029 /* Clear window to avoid flicker. */
9030 EraseRect (&(w->portRect));
9031 if (zoom_in_or_out == inZoomOut)
9033 SetPt (&top_left, w->portRect.left, w->portRect.top);
9034 LocalToGlobal (&top_left);
9036 /* calculate height of window's title bar */
9037 w_title_height = top_left.v - 1
9038 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
9040 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
9041 zoom_rect = qd.screenBits.bounds;
9042 zoom_rect.top += w_title_height;
9043 InsetRect (&zoom_rect, 8, 4); /* not too tight */
9045 zoom_rect.right = zoom_rect.left
9046 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
9048 /* Adjust the standard size according to character boundaries. */
9049 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
9050 zoom_rect.bottom =
9051 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
9053 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
9054 = zoom_rect;
9057 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
9059 SetPort (save_port);
9060 #endif /* not TARGET_API_MAC_CARBON */
9062 /* retrieve window size and update application values */
9063 #if TARGET_API_MAC_CARBON
9064 GetWindowPortBounds (w, &port_rect);
9065 #else
9066 port_rect = w->portRect;
9067 #endif
9068 height = port_rect.bottom - port_rect.top;
9069 width = port_rect.right - port_rect.left;
9071 if (width != FRAME_PIXEL_WIDTH (f)
9072 || height != FRAME_PIXEL_HEIGHT (f))
9074 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
9075 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
9077 change_frame_size (f, rows, columns, 0, 1, 0);
9078 SET_FRAME_GARBAGED (f);
9079 cancel_mouse_face (f);
9081 FRAME_PIXEL_WIDTH (f) = width;
9082 FRAME_PIXEL_HEIGHT (f) = height;
9084 x_real_positions (f, &f->left_pos, &f->top_pos);
9087 void
9088 mac_store_apple_event (class, id, desc)
9089 Lisp_Object class, id;
9090 const AEDesc *desc;
9092 struct input_event buf;
9094 EVENT_INIT (buf);
9096 buf.kind = MAC_APPLE_EVENT;
9097 buf.x = class;
9098 buf.y = id;
9099 XSETFRAME (buf.frame_or_window,
9100 mac_focus_frame (&one_mac_display_info));
9101 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it
9102 is safe to use them during read_socket_hook. */
9103 buf.arg = mac_aedesc_to_lisp (desc);
9104 kbd_buffer_store_event (&buf);
9107 #if TARGET_API_MAC_CARBON
9108 static OSStatus
9109 mac_store_event_ref_as_apple_event (class, id, class_key, id_key,
9110 event, num_params, names, types)
9111 AEEventClass class;
9112 AEEventID id;
9113 Lisp_Object class_key, id_key;
9114 EventRef event;
9115 UInt32 num_params;
9116 EventParamName *names;
9117 EventParamType *types;
9119 OSStatus err = eventNotHandledErr;
9120 Lisp_Object binding;
9122 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding);
9123 if (!NILP (binding) && !EQ (binding, Qundefined))
9125 if (INTEGERP (binding))
9126 err = XINT (binding);
9127 else
9129 AppleEvent apple_event;
9130 err = create_apple_event_from_event_ref (event, num_params,
9131 names, types,
9132 &apple_event);
9133 if (err == noErr)
9135 mac_store_apple_event (class_key, id_key, &apple_event);
9136 AEDisposeDesc (&apple_event);
9137 /* Post a harmless event so as to wake up from
9138 ReceiveNextEvent. */
9139 mac_post_mouse_moved_event ();
9144 return err;
9147 void
9148 mac_store_drag_event (window, mouse_pos, modifiers, desc)
9149 WindowRef window;
9150 Point mouse_pos;
9151 SInt16 modifiers;
9152 const AEDesc *desc;
9154 struct input_event buf;
9156 EVENT_INIT (buf);
9158 buf.kind = DRAG_N_DROP_EVENT;
9159 buf.modifiers = mac_to_emacs_modifiers (modifiers);
9160 buf.timestamp = TickCount () * (1000 / 60);
9161 XSETINT (buf.x, mouse_pos.h);
9162 XSETINT (buf.y, mouse_pos.v);
9163 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window));
9164 buf.arg = mac_aedesc_to_lisp (desc);
9165 kbd_buffer_store_event (&buf);
9167 #endif
9169 #if USE_CARBON_EVENTS
9170 static pascal OSStatus
9171 mac_handle_command_event (next_handler, event, data)
9172 EventHandlerCallRef next_handler;
9173 EventRef event;
9174 void *data;
9176 OSStatus result, err;
9177 HICommand command;
9178 static EventParamName names[] = {kEventParamDirectObject,
9179 kEventParamKeyModifiers};
9180 static EventParamType types[] = {typeHICommand,
9181 typeUInt32};
9182 int num_params = sizeof (names) / sizeof (names[0]);
9184 result = CallNextEventHandler (next_handler, event);
9185 if (result != eventNotHandledErr)
9186 return result;
9188 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand,
9189 NULL, sizeof (HICommand), NULL, &command);
9191 if (err != noErr || command.commandID == 0)
9192 return eventNotHandledErr;
9194 /* A HICommand event is mapped to an Apple event whose event class
9195 symbol is `hicommand' and event ID is its command ID. */
9196 err = mac_store_event_ref_as_apple_event (0, command.commandID,
9197 Qhicommand, Qnil,
9198 event, num_params, names, types);
9199 return err == noErr ? noErr : eventNotHandledErr;
9202 static OSErr
9203 init_command_handler ()
9205 EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
9206 static EventHandlerUPP handle_command_eventUPP = NULL;
9208 if (handle_command_eventUPP == NULL)
9209 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
9210 return InstallApplicationEventHandler (handle_command_eventUPP,
9211 GetEventTypeCount (specs), specs,
9212 NULL, NULL);
9215 static pascal OSStatus
9216 mac_handle_window_event (next_handler, event, data)
9217 EventHandlerCallRef next_handler;
9218 EventRef event;
9219 void *data;
9221 WindowPtr wp;
9222 OSStatus result, err;
9223 UInt32 attributes;
9224 XSizeHints *size_hints;
9226 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
9227 NULL, sizeof (WindowPtr), NULL, &wp);
9228 if (err != noErr)
9229 return eventNotHandledErr;
9231 switch (GetEventKind (event))
9233 case kEventWindowUpdate:
9234 result = CallNextEventHandler (next_handler, event);
9235 if (result != eventNotHandledErr)
9236 return result;
9238 do_window_update (wp);
9239 return noErr;
9241 case kEventWindowBoundsChanging:
9242 result = CallNextEventHandler (next_handler, event);
9243 if (result != eventNotHandledErr)
9244 return result;
9246 err = GetEventParameter (event, kEventParamAttributes, typeUInt32,
9247 NULL, sizeof (UInt32), NULL, &attributes);
9248 if (err != noErr)
9249 break;
9251 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
9252 if ((attributes & kWindowBoundsChangeUserResize)
9253 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
9254 == (PResizeInc | PBaseSize | PMinSize)))
9256 Rect bounds;
9257 int width, height;
9259 err = GetEventParameter (event, kEventParamCurrentBounds,
9260 typeQDRectangle, NULL, sizeof (Rect),
9261 NULL, &bounds);
9262 if (err != noErr)
9263 break;
9265 width = bounds.right - bounds.left;
9266 height = bounds.bottom - bounds.top;
9268 if (width < size_hints->min_width)
9269 width = size_hints->min_width;
9270 else
9271 width = size_hints->base_width
9272 + (int) ((width - size_hints->base_width)
9273 / (float) size_hints->width_inc + .5)
9274 * size_hints->width_inc;
9276 if (height < size_hints->min_height)
9277 height = size_hints->min_height;
9278 else
9279 height = size_hints->base_height
9280 + (int) ((height - size_hints->base_height)
9281 / (float) size_hints->height_inc + .5)
9282 * size_hints->height_inc;
9284 bounds.right = bounds.left + width;
9285 bounds.bottom = bounds.top + height;
9286 SetEventParameter (event, kEventParamCurrentBounds,
9287 typeQDRectangle, sizeof (Rect), &bounds);
9288 return noErr;
9290 break;
9292 case kEventWindowShown:
9293 case kEventWindowHidden:
9294 case kEventWindowExpanded:
9295 case kEventWindowCollapsed:
9296 result = CallNextEventHandler (next_handler, event);
9298 mac_handle_visibility_change (mac_window_to_frame (wp));
9299 return noErr;
9301 break;
9303 #ifdef MAC_OSX
9304 case kEventWindowToolbarSwitchMode:
9305 result = CallNextEventHandler (next_handler, event);
9307 static EventParamName names[] = {kEventParamDirectObject,
9308 kEventParamWindowMouseLocation,
9309 kEventParamKeyModifiers,
9310 kEventParamMouseButton,
9311 kEventParamClickCount,
9312 kEventParamMouseChord};
9313 static EventParamType types[] = {typeWindowRef,
9314 typeQDPoint,
9315 typeUInt32,
9316 typeMouseButton,
9317 typeUInt32,
9318 typeUInt32};
9319 int num_params = sizeof (names) / sizeof (names[0]);
9321 err = mac_store_event_ref_as_apple_event (0, 0,
9322 Qwindow,
9323 Qtoolbar_switch_mode,
9324 event, num_params,
9325 names, types);
9327 return err == noErr ? noErr : result;
9328 #endif
9330 #if USE_MAC_TSM
9331 case kEventWindowFocusAcquired:
9332 result = CallNextEventHandler (next_handler, event);
9333 err = ActivateTSMDocument (tsm_document_id);
9334 return err == noErr ? noErr : result;
9336 case kEventWindowFocusRelinquish:
9337 result = CallNextEventHandler (next_handler, event);
9338 err = DeactivateTSMDocument (tsm_document_id);
9339 return err == noErr ? noErr : result;
9340 #endif
9343 return eventNotHandledErr;
9346 static pascal OSStatus
9347 mac_handle_mouse_event (next_handler, event, data)
9348 EventHandlerCallRef next_handler;
9349 EventRef event;
9350 void *data;
9352 OSStatus result, err;
9354 switch (GetEventKind (event))
9356 case kEventMouseWheelMoved:
9358 WindowPtr wp;
9359 struct frame *f;
9360 EventMouseWheelAxis axis;
9361 SInt32 delta;
9362 Point point;
9364 result = CallNextEventHandler (next_handler, event);
9365 if (result != eventNotHandledErr || read_socket_inev == NULL)
9366 return result;
9368 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
9369 NULL, sizeof (WindowRef), NULL, &wp);
9370 if (err != noErr)
9371 break;
9373 f = mac_window_to_frame (wp);
9374 if (f != mac_focus_frame (&one_mac_display_info))
9375 break;
9377 err = GetEventParameter (event, kEventParamMouseWheelAxis,
9378 typeMouseWheelAxis, NULL,
9379 sizeof (EventMouseWheelAxis), NULL, &axis);
9380 if (err != noErr || axis != kEventMouseWheelAxisY)
9381 break;
9383 err = GetEventParameter (event, kEventParamMouseWheelDelta,
9384 typeSInt32, NULL, sizeof (SInt32),
9385 NULL, &delta);
9386 if (err != noErr)
9387 break;
9388 err = GetEventParameter (event, kEventParamMouseLocation,
9389 typeQDPoint, NULL, sizeof (Point),
9390 NULL, &point);
9391 if (err != noErr)
9392 break;
9393 read_socket_inev->kind = WHEEL_EVENT;
9394 read_socket_inev->code = 0;
9395 read_socket_inev->modifiers =
9396 (mac_event_to_emacs_modifiers (event)
9397 | ((delta < 0) ? down_modifier : up_modifier));
9398 SetPortWindowPort (wp);
9399 GlobalToLocal (&point);
9400 XSETINT (read_socket_inev->x, point.h);
9401 XSETINT (read_socket_inev->y, point.v);
9402 XSETFRAME (read_socket_inev->frame_or_window, f);
9404 return noErr;
9406 break;
9408 default:
9409 break;
9412 return eventNotHandledErr;
9415 #if USE_MAC_FONT_PANEL
9416 static pascal OSStatus
9417 mac_handle_font_event (next_handler, event, data)
9418 EventHandlerCallRef next_handler;
9419 EventRef event;
9420 void *data;
9422 OSStatus result, err;
9423 Lisp_Object id_key;
9424 int num_params;
9425 EventParamName *names;
9426 EventParamType *types;
9427 static EventParamName names_sel[] = {kEventParamATSUFontID,
9428 kEventParamATSUFontSize,
9429 kEventParamFMFontFamily,
9430 kEventParamFMFontSize,
9431 kEventParamFontColor};
9432 static EventParamType types_sel[] = {typeATSUFontID,
9433 typeATSUSize,
9434 typeFMFontFamily,
9435 typeFMFontSize,
9436 typeFontColor};
9438 result = CallNextEventHandler (next_handler, event);
9439 if (result != eventNotHandledErr)
9440 return result;
9442 switch (GetEventKind (event))
9444 case kEventFontPanelClosed:
9445 id_key = Qpanel_closed;
9446 num_params = 0;
9447 names = NULL;
9448 types = NULL;
9449 break;
9451 case kEventFontSelection:
9452 id_key = Qselection;
9453 num_params = sizeof (names_sel) / sizeof (names_sel[0]);
9454 names = names_sel;
9455 types = types_sel;
9456 break;
9459 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key,
9460 event, num_params,
9461 names, types);
9463 return err == noErr ? noErr : eventNotHandledErr;
9465 #endif
9467 #if USE_MAC_TSM
9468 static pascal OSStatus
9469 mac_handle_text_input_event (next_handler, event, data)
9470 EventHandlerCallRef next_handler;
9471 EventRef event;
9472 void *data;
9474 OSStatus result, err = noErr;
9475 Lisp_Object id_key = Qnil;
9476 int num_params;
9477 EventParamName *names;
9478 EventParamType *types;
9479 static UInt32 seqno_uaia = 0;
9480 static EventParamName names_uaia[] =
9481 {kEventParamTextInputSendComponentInstance,
9482 kEventParamTextInputSendRefCon,
9483 kEventParamTextInputSendSLRec,
9484 kEventParamTextInputSendFixLen,
9485 kEventParamTextInputSendText,
9486 kEventParamTextInputSendUpdateRng,
9487 kEventParamTextInputSendHiliteRng,
9488 kEventParamTextInputSendClauseRng,
9489 kEventParamTextInputSendPinRng,
9490 kEventParamTextInputSendTextServiceEncoding,
9491 kEventParamTextInputSendTextServiceMacEncoding,
9492 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER};
9493 static EventParamType types_uaia[] =
9494 {typeComponentInstance,
9495 typeLongInteger,
9496 typeIntlWritingCode,
9497 typeLongInteger,
9498 typeUnicodeText,
9499 typeTextRangeArray,
9500 typeTextRangeArray,
9501 typeOffsetArray,
9502 typeTextRange,
9503 typeUInt32,
9504 typeUInt32,
9505 typeUInt32};
9506 static EventParamName names_ufke[] =
9507 {kEventParamTextInputSendComponentInstance,
9508 kEventParamTextInputSendRefCon,
9509 kEventParamTextInputSendSLRec,
9510 kEventParamTextInputSendText};
9511 static EventParamType types_ufke[] =
9512 {typeComponentInstance,
9513 typeLongInteger,
9514 typeIntlWritingCode,
9515 typeUnicodeText};
9517 result = CallNextEventHandler (next_handler, event);
9519 switch (GetEventKind (event))
9521 case kEventTextInputUpdateActiveInputArea:
9522 id_key = Qupdate_active_input_area;
9523 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]);
9524 names = names_uaia;
9525 types = types_uaia;
9526 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER,
9527 typeUInt32, sizeof (UInt32), &seqno_uaia);
9528 seqno_uaia++;
9529 break;
9531 case kEventTextInputUnicodeForKeyEvent:
9533 EventRef kbd_event;
9534 UInt32 actual_size, modifiers, mapped_modifiers;
9535 UniChar code;
9537 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent,
9538 typeEventRef, NULL, sizeof (EventRef), NULL,
9539 &kbd_event);
9540 if (err == noErr)
9541 err = GetEventParameter (kbd_event, kEventParamKeyModifiers,
9542 typeUInt32, NULL,
9543 sizeof (UInt32), NULL, &modifiers);
9544 if (err == noErr)
9546 mapped_modifiers =
9547 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9548 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9549 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9550 #ifdef MAC_OSX
9551 mapped_modifiers |=
9552 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
9553 #endif
9554 if (modifiers & mapped_modifiers)
9555 /* There're mapped modifier keys. Process it in
9556 XTread_socket. */
9557 return eventNotHandledErr;
9559 if (err == noErr)
9560 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
9561 typeUnicodeText, NULL, 0, &actual_size,
9562 NULL);
9563 if (err == noErr)
9565 if (actual_size == sizeof (UniChar))
9566 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes,
9567 typeUnicodeText, NULL,
9568 sizeof (UniChar), NULL, &code);
9569 if (err == noErr && code < 0x80)
9571 /* ASCII character. Process it in XTread_socket. */
9572 if (read_socket_inev && code >= 0x20)
9574 struct frame *f = mac_focus_frame (&one_mac_display_info);
9576 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT;
9577 read_socket_inev->code = code;
9578 read_socket_inev->modifiers =
9579 (extra_keyboard_modifiers
9580 & (meta_modifier | alt_modifier
9581 | hyper_modifier | super_modifier));
9582 XSETFRAME (read_socket_inev->frame_or_window, f);
9584 return eventNotHandledErr;
9588 /* Non-ASCII keystrokes without mapped modifiers are processed
9589 at the Lisp level. */
9590 id_key = Qunicode_for_key_event;
9591 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]);
9592 names = names_ufke;
9593 types = types_ufke;
9594 break;
9596 case kEventTextInputOffsetToPos:
9598 struct frame *f;
9599 struct window *w;
9600 Point p;
9602 if (!OVERLAYP (Vmac_ts_active_input_overlay))
9603 return eventNotHandledErr;
9605 /* Strictly speaking, this is not always correct because
9606 previous events may change some states about display. */
9607 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string)))
9609 /* Active input area is displayed in the echo area. */
9610 w = XWINDOW (echo_area_window);
9611 f = WINDOW_XFRAME (w);
9613 else
9615 /* Active input area is displayed around the current point. */
9616 f = SELECTED_FRAME ();
9617 w = XWINDOW (f->selected_window);
9620 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x)
9621 + WINDOW_LEFT_FRINGE_WIDTH (w));
9622 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y)
9623 + FONT_BASE (FRAME_FONT (f)));
9624 SetPortWindowPort (FRAME_MAC_WINDOW (f));
9625 LocalToGlobal (&p);
9626 err = SetEventParameter (event, kEventParamTextInputReplyPoint,
9627 typeQDPoint, sizeof (typeQDPoint), &p);
9629 break;
9631 default:
9632 abort ();
9635 if (!NILP (id_key))
9636 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key,
9637 event, num_params,
9638 names, types);
9640 return err == noErr ? noErr : result;
9642 #endif
9644 #ifdef MAC_OSX
9645 OSStatus
9646 mac_store_service_event (event)
9647 EventRef event;
9649 OSStatus err;
9650 Lisp_Object id_key;
9651 int num_params;
9652 EventParamName *names;
9653 EventParamType *types;
9654 static EventParamName names_pfm[] = {kEventParamServiceMessageName,
9655 kEventParamServiceUserData};
9656 static EventParamType types_pfm[] = {typeCFStringRef,
9657 typeCFStringRef};
9659 switch (GetEventKind (event))
9661 case kEventServicePaste:
9662 id_key = Qpaste;
9663 num_params = 0;
9664 names = NULL;
9665 types = NULL;
9666 break;
9668 case kEventServicePerform:
9669 id_key = Qperform;
9670 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]);
9671 names = names_pfm;
9672 types = types_pfm;
9673 break;
9675 default:
9676 abort ();
9679 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key,
9680 event, num_params,
9681 names, types);
9683 return err;
9685 #endif /* MAC_OSX */
9686 #endif /* USE_CARBON_EVENTS */
9689 OSErr
9690 install_window_handler (window)
9691 WindowPtr window;
9693 OSErr err = noErr;
9694 #if USE_CARBON_EVENTS
9695 EventTypeSpec specs_window[] =
9696 {{kEventClassWindow, kEventWindowUpdate},
9697 {kEventClassWindow, kEventWindowBoundsChanging},
9698 {kEventClassWindow, kEventWindowShown},
9699 {kEventClassWindow, kEventWindowHidden},
9700 {kEventClassWindow, kEventWindowExpanded},
9701 {kEventClassWindow, kEventWindowCollapsed},
9702 #ifdef MAC_OSX
9703 {kEventClassWindow, kEventWindowToolbarSwitchMode},
9704 #endif
9705 #if USE_MAC_TSM
9706 {kEventClassWindow, kEventWindowFocusAcquired},
9707 {kEventClassWindow, kEventWindowFocusRelinquish},
9708 #endif
9710 EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
9711 static EventHandlerUPP handle_window_eventUPP = NULL;
9712 static EventHandlerUPP handle_mouse_eventUPP = NULL;
9713 #if USE_MAC_FONT_PANEL
9714 EventTypeSpec specs_font[] = {{kEventClassFont, kEventFontPanelClosed},
9715 {kEventClassFont, kEventFontSelection}};
9716 static EventHandlerUPP handle_font_eventUPP = NULL;
9717 #endif
9718 #if USE_MAC_TSM
9719 EventTypeSpec specs_text_input[] =
9720 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea},
9721 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent},
9722 {kEventClassTextInput, kEventTextInputOffsetToPos}};
9723 static EventHandlerUPP handle_text_input_eventUPP = NULL;
9724 #endif
9726 if (handle_window_eventUPP == NULL)
9727 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
9728 if (handle_mouse_eventUPP == NULL)
9729 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
9730 #if USE_MAC_FONT_PANEL
9731 if (handle_font_eventUPP == NULL)
9732 handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event);
9733 #endif
9734 #if USE_MAC_TSM
9735 if (handle_text_input_eventUPP == NULL)
9736 handle_text_input_eventUPP =
9737 NewEventHandlerUPP (mac_handle_text_input_event);
9738 #endif
9739 err = InstallWindowEventHandler (window, handle_window_eventUPP,
9740 GetEventTypeCount (specs_window),
9741 specs_window, NULL, NULL);
9742 if (err == noErr)
9743 err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
9744 GetEventTypeCount (specs_mouse),
9745 specs_mouse, NULL, NULL);
9746 #if USE_MAC_FONT_PANEL
9747 if (err == noErr)
9748 err = InstallWindowEventHandler (window, handle_font_eventUPP,
9749 GetEventTypeCount (specs_font),
9750 specs_font, NULL, NULL);
9751 #endif
9752 #if USE_MAC_TSM
9753 if (err == noErr)
9754 err = InstallWindowEventHandler (window, handle_text_input_eventUPP,
9755 GetEventTypeCount (specs_text_input),
9756 specs_text_input, window, NULL);
9757 #endif
9758 #endif
9759 if (err == noErr)
9760 err = install_drag_handler (window);
9762 return err;
9765 void
9766 remove_window_handler (window)
9767 WindowPtr window;
9769 remove_drag_handler (window);
9773 #if __profile__
9774 void
9775 profiler_exit_proc ()
9777 ProfilerDump ("\pEmacs.prof");
9778 ProfilerTerm ();
9780 #endif
9782 /* These few functions implement Emacs as a normal Mac application
9783 (almost): set up the heap and the Toolbox, handle necessary system
9784 events plus a few simple menu events. They also set up Emacs's
9785 access to functions defined in the rest of this file. Emacs uses
9786 function hooks to perform all its terminal I/O. A complete list of
9787 these functions appear in termhooks.h. For what they do, read the
9788 comments there and see also w32term.c and xterm.c. What's
9789 noticeably missing here is the event loop, which is normally
9790 present in most Mac application. After performing the necessary
9791 Mac initializations, main passes off control to emacs_main
9792 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9793 (defined further below) to read input. This is where
9794 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9796 #ifdef MAC_OS8
9797 #undef main
9799 main (void)
9801 #if __profile__ /* is the profiler on? */
9802 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
9803 exit(1);
9804 #endif
9806 #if __MWERKS__
9807 /* set creator and type for files created by MSL */
9808 _fcreator = 'EMAx';
9809 _ftype = 'TEXT';
9810 #endif
9812 do_init_managers ();
9814 do_get_menus ();
9816 #ifndef USE_LSB_TAG
9817 do_check_ram_size ();
9818 #endif
9820 init_emacs_passwd_dir ();
9822 init_environ ();
9824 init_coercion_handler ();
9826 initialize_applescript ();
9828 init_apple_event_handler ();
9831 char **argv;
9832 int argc = 0;
9834 /* set up argv array from STR# resource */
9835 get_string_list (&argv, ARGV_STRING_LIST_ID);
9836 while (argv[argc])
9837 argc++;
9839 /* free up AppleScript resources on exit */
9840 atexit (terminate_applescript);
9842 #if __profile__ /* is the profiler on? */
9843 atexit (profiler_exit_proc);
9844 #endif
9846 /* 3rd param "envp" never used in emacs_main */
9847 (void) emacs_main (argc, argv, 0);
9850 /* Never reached - real exit in Fkill_emacs */
9851 return 0;
9853 #endif
9855 /* Table for translating Mac keycode to X keysym values. Contributed
9856 by Sudhir Shenoy.
9857 Mapping for special keys is now identical to that in Apple X11
9858 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9859 on the right of the Cmd key on laptops, and fn + `enter' (->
9860 <linefeed>). */
9861 static unsigned char keycode_to_xkeysym_table[] = {
9862 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9863 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9864 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9866 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9867 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9868 /*0x38*/ 0, 0, 0, 0,
9869 /*0x3C*/ 0, 0, 0, 0,
9871 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9872 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9873 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9874 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9876 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9877 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9878 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9879 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9881 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9882 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9883 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/,
9884 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9886 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9887 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9888 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9889 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9893 static int
9894 keycode_to_xkeysym (int keyCode, int *xKeySym)
9896 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
9897 return *xKeySym != 0;
9900 #ifdef MAC_OSX
9901 /* Table for translating Mac keycode with the laptop `fn' key to that
9902 without it. Destination symbols in comments are keys on US
9903 keyboard, and they may not be the same on other types of keyboards.
9904 If the destination is identical to the source (f1 ... f12), it
9905 doesn't map `fn' key to a modifier. */
9906 static unsigned char fn_keycode_to_keycode_table[] = {
9907 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9908 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9909 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9911 /*0x30*/ 0, 0, 0, 0,
9912 /*0x34*/ 0, 0, 0, 0,
9913 /*0x38*/ 0, 0, 0, 0,
9914 /*0x3C*/ 0, 0, 0, 0,
9916 /*0x40*/ 0, 0x2f /*kp-. -> '.'*/, 0, 0x23 /*kp-* -> 'p'*/,
9917 /*0x44*/ 0, 0x2c /*kp-+ -> '/'*/, 0, 0x16 /*clear -> '6'*/,
9918 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/,
9919 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-- -> ';'*/, 0,
9921 /*0x50*/ 0, 0x1b /*kp-= -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/,
9922 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/,
9923 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/,
9924 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0,
9926 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/,
9927 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/,
9928 /*0x68*/ 0, 0, 0, 0,
9929 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/,
9931 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/,
9932 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/,
9933 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0,
9934 /*0x7C*/ 0, 0, 0, 0
9936 #endif /* MAC_OSX */
9938 #if !USE_CARBON_EVENTS
9939 static RgnHandle mouse_region = NULL;
9941 Boolean
9942 mac_wait_next_event (er, sleep_time, dequeue)
9943 EventRecord *er;
9944 UInt32 sleep_time;
9945 Boolean dequeue;
9947 static EventRecord er_buf = {nullEvent};
9948 UInt32 target_tick, current_tick;
9949 EventMask event_mask;
9951 if (mouse_region == NULL)
9952 mouse_region = NewRgn ();
9954 event_mask = everyEvent;
9955 if (!mac_ready_for_apple_events)
9956 event_mask -= highLevelEventMask;
9958 current_tick = TickCount ();
9959 target_tick = current_tick + sleep_time;
9961 if (er_buf.what == nullEvent)
9962 while (!WaitNextEvent (event_mask, &er_buf,
9963 target_tick - current_tick, mouse_region))
9965 current_tick = TickCount ();
9966 if (target_tick <= current_tick)
9967 return false;
9970 *er = er_buf;
9971 if (dequeue)
9972 er_buf.what = nullEvent;
9973 return true;
9975 #endif /* not USE_CARBON_EVENTS */
9977 #if TARGET_API_MAC_CARBON
9978 OSStatus
9979 mac_post_mouse_moved_event ()
9981 EventRef event = NULL;
9982 OSStatus err;
9984 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
9985 kEventAttributeNone, &event);
9986 if (err == noErr)
9988 Point mouse_pos;
9990 GetMouse (&mouse_pos);
9991 LocalToGlobal (&mouse_pos);
9992 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
9993 sizeof (Point), &mouse_pos);
9995 if (err == noErr)
9997 UInt32 modifiers = GetCurrentKeyModifiers ();
9999 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
10000 sizeof (UInt32), &modifiers);
10002 if (err == noErr)
10003 err = PostEventToQueue (GetCurrentEventQueue (), event,
10004 kEventPriorityStandard);
10005 if (event)
10006 ReleaseEvent (event);
10008 return err;
10011 static void
10012 mac_set_unicode_keystroke_event (code, buf)
10013 UniChar code;
10014 struct input_event *buf;
10016 int charset_id, c1, c2;
10018 if (code < 0x80)
10020 buf->kind = ASCII_KEYSTROKE_EVENT;
10021 buf->code = code;
10023 else if (code < 0x100)
10025 if (code < 0xA0)
10026 charset_id = CHARSET_8_BIT_CONTROL;
10027 else
10028 charset_id = charset_latin_iso8859_1;
10029 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10030 buf->code = MAKE_CHAR (charset_id, code, 0);
10032 else
10034 if (code < 0x2500)
10035 charset_id = charset_mule_unicode_0100_24ff,
10036 code -= 0x100;
10037 else if (code < 0x33FF)
10038 charset_id = charset_mule_unicode_2500_33ff,
10039 code -= 0x2500;
10040 else if (code >= 0xE000)
10041 charset_id = charset_mule_unicode_e000_ffff,
10042 code -= 0xE000;
10043 c1 = (code / 96) + 32, c2 = (code % 96) + 32;
10044 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
10045 buf->code = MAKE_CHAR (charset_id, c1, c2);
10048 #endif
10050 /* Emacs calls this whenever it wants to read an input event from the
10051 user. */
10053 XTread_socket (sd, expected, hold_quit)
10054 int sd, expected;
10055 struct input_event *hold_quit;
10057 struct input_event inev;
10058 int count = 0;
10059 #if USE_CARBON_EVENTS
10060 EventRef eventRef;
10061 EventTargetRef toolbox_dispatcher;
10062 #endif
10063 EventRecord er;
10064 struct mac_display_info *dpyinfo = &one_mac_display_info;
10066 if (interrupt_input_blocked)
10068 interrupt_input_pending = 1;
10069 return -1;
10072 interrupt_input_pending = 0;
10073 BLOCK_INPUT;
10075 /* So people can tell when we have read the available input. */
10076 input_signal_count++;
10078 ++handling_signal;
10080 #if USE_CARBON_EVENTS
10081 toolbox_dispatcher = GetEventDispatcherTarget ();
10083 while (
10084 #if USE_CG_DRAWING
10085 mac_prepare_for_quickdraw (NULL),
10086 #endif
10087 !ReceiveNextEvent (0, NULL, kEventDurationNoWait,
10088 kEventRemoveFromQueue, &eventRef))
10089 #else /* !USE_CARBON_EVENTS */
10090 while (mac_wait_next_event (&er, 0, true))
10091 #endif /* !USE_CARBON_EVENTS */
10093 int do_help = 0;
10094 struct frame *f;
10095 unsigned long timestamp;
10097 EVENT_INIT (inev);
10098 inev.kind = NO_EVENT;
10099 inev.arg = Qnil;
10101 #if USE_CARBON_EVENTS
10102 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
10103 #else
10104 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
10105 #endif
10107 #if USE_CARBON_EVENTS
10108 /* Handle new events */
10109 if (!mac_convert_event_ref (eventRef, &er))
10111 /* There used to be a handler for the kEventMouseWheelMoved
10112 event here. But as of Mac OS X 10.4, this kind of event
10113 is not directly posted to the main event queue by
10114 two-finger scrolling on the trackpad. Instead, some
10115 private event is posted and it is converted to a wheel
10116 event by the default handler for the application target.
10117 The converted one can be received by a Carbon event
10118 handler installed on a window target. */
10119 read_socket_inev = &inev;
10120 SendEventToEventTarget (eventRef, toolbox_dispatcher);
10121 read_socket_inev = NULL;
10123 else
10124 #endif /* USE_CARBON_EVENTS */
10125 switch (er.what)
10127 case mouseDown:
10128 case mouseUp:
10130 WindowPtr window_ptr;
10131 ControlPartCode part_code;
10132 int tool_bar_p = 0;
10134 #if USE_CARBON_EVENTS
10135 /* This is needed to send mouse events like aqua window
10136 buttons to the correct handler. */
10137 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10138 != eventNotHandledErr)
10139 break;
10140 #endif
10141 last_mouse_glyph_frame = 0;
10143 if (dpyinfo->grabbed && last_mouse_frame
10144 && FRAME_LIVE_P (last_mouse_frame))
10146 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
10147 part_code = inContent;
10149 else
10151 part_code = FindWindow (er.where, &window_ptr);
10152 if (tip_window && window_ptr == tip_window)
10154 HideWindow (tip_window);
10155 part_code = FindWindow (er.where, &window_ptr);
10159 if (er.what != mouseDown &&
10160 (part_code != inContent || dpyinfo->grabbed == 0))
10161 break;
10163 switch (part_code)
10165 case inMenuBar:
10166 f = mac_focus_frame (dpyinfo);
10167 saved_menu_event_location = er.where;
10168 inev.kind = MENU_BAR_ACTIVATE_EVENT;
10169 XSETFRAME (inev.frame_or_window, f);
10170 break;
10172 case inContent:
10173 if (
10174 #if TARGET_API_MAC_CARBON
10175 FrontNonFloatingWindow ()
10176 #else
10177 FrontWindow ()
10178 #endif
10179 != window_ptr)
10180 SelectWindow (window_ptr);
10181 else
10183 ControlPartCode control_part_code;
10184 ControlHandle ch;
10185 Point mouse_loc = er.where;
10186 #ifdef MAC_OSX
10187 ControlKind control_kind;
10188 #endif
10190 f = mac_window_to_frame (window_ptr);
10191 /* convert to local coordinates of new window */
10192 SetPortWindowPort (window_ptr);
10194 GlobalToLocal (&mouse_loc);
10195 #if TARGET_API_MAC_CARBON
10196 ch = FindControlUnderMouse (mouse_loc, window_ptr,
10197 &control_part_code);
10198 #ifdef MAC_OSX
10199 if (ch)
10200 GetControlKind (ch, &control_kind);
10201 #endif
10202 #else
10203 control_part_code = FindControl (mouse_loc, window_ptr,
10204 &ch);
10205 #endif
10207 #if USE_CARBON_EVENTS
10208 inev.code = mac_get_mouse_btn (eventRef);
10209 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10210 #else
10211 inev.code = mac_get_emulated_btn (er.modifiers);
10212 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
10213 #endif
10214 XSETINT (inev.x, mouse_loc.h);
10215 XSETINT (inev.y, mouse_loc.v);
10217 if ((dpyinfo->grabbed && tracked_scroll_bar)
10218 || (ch != 0
10219 #ifndef USE_TOOLKIT_SCROLL_BARS
10220 /* control_part_code becomes kControlNoPart if
10221 a progress indicator is clicked. */
10222 && control_part_code != kControlNoPart
10223 #else /* USE_TOOLKIT_SCROLL_BARS */
10224 #ifdef MAC_OSX
10225 && control_kind.kind == kControlKindScrollBar
10226 #endif /* MAC_OSX */
10227 #endif /* USE_TOOLKIT_SCROLL_BARS */
10230 struct scroll_bar *bar;
10232 if (dpyinfo->grabbed && tracked_scroll_bar)
10234 bar = tracked_scroll_bar;
10235 #ifndef USE_TOOLKIT_SCROLL_BARS
10236 control_part_code = kControlIndicatorPart;
10237 #endif
10239 else
10240 bar = (struct scroll_bar *) GetControlReference (ch);
10241 #ifdef USE_TOOLKIT_SCROLL_BARS
10242 /* Make the "Ctrl-Mouse-2 splits window" work
10243 for toolkit scroll bars. */
10244 if (er.modifiers & controlKey)
10245 x_scroll_bar_handle_click (bar, control_part_code,
10246 &er, &inev);
10247 else if (er.what == mouseDown)
10248 x_scroll_bar_handle_press (bar, control_part_code,
10249 &inev);
10250 else
10251 x_scroll_bar_handle_release (bar, &inev);
10252 #else /* not USE_TOOLKIT_SCROLL_BARS */
10253 x_scroll_bar_handle_click (bar, control_part_code,
10254 &er, &inev);
10255 if (er.what == mouseDown
10256 && control_part_code == kControlIndicatorPart)
10257 tracked_scroll_bar = bar;
10258 else
10259 tracked_scroll_bar = NULL;
10260 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10262 else
10264 Lisp_Object window;
10265 int x = mouse_loc.h;
10266 int y = mouse_loc.v;
10268 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
10269 if (EQ (window, f->tool_bar_window))
10271 if (er.what == mouseDown)
10272 handle_tool_bar_click (f, x, y, 1, 0);
10273 else
10274 handle_tool_bar_click (f, x, y, 0,
10275 inev.modifiers);
10276 tool_bar_p = 1;
10278 else
10280 XSETFRAME (inev.frame_or_window, f);
10281 inev.kind = MOUSE_CLICK_EVENT;
10285 if (er.what == mouseDown)
10287 dpyinfo->grabbed |= (1 << inev.code);
10288 last_mouse_frame = f;
10290 if (!tool_bar_p)
10291 last_tool_bar_item = -1;
10293 else
10295 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
10296 /* If a button is released though it was not
10297 previously pressed, that would be because
10298 of multi-button emulation. */
10299 dpyinfo->grabbed = 0;
10300 else
10301 dpyinfo->grabbed &= ~(1 << inev.code);
10304 /* Ignore any mouse motion that happened before
10305 this event; any subsequent mouse-movement Emacs
10306 events should reflect only motion after the
10307 ButtonPress. */
10308 if (f != 0)
10309 f->mouse_moved = 0;
10311 #ifdef USE_TOOLKIT_SCROLL_BARS
10312 if (inev.kind == MOUSE_CLICK_EVENT)
10313 #endif
10314 switch (er.what)
10316 case mouseDown:
10317 inev.modifiers |= down_modifier;
10318 break;
10319 case mouseUp:
10320 inev.modifiers |= up_modifier;
10321 break;
10324 break;
10326 case inDrag:
10327 #if TARGET_API_MAC_CARBON
10328 case inProxyIcon:
10329 if (IsWindowPathSelectClick (window_ptr, &er))
10331 WindowPathSelect (window_ptr, NULL, NULL);
10332 break;
10334 if (part_code == inProxyIcon
10335 && (TrackWindowProxyDrag (window_ptr, er.where)
10336 != errUserWantsToDragWindow))
10337 break;
10338 DragWindow (window_ptr, er.where, NULL);
10339 #else /* not TARGET_API_MAC_CARBON */
10340 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
10341 #endif /* not TARGET_API_MAC_CARBON */
10342 /* Update the frame parameters. */
10344 struct frame *f = mac_window_to_frame (window_ptr);
10346 if (f && !f->async_iconified)
10347 x_real_positions (f, &f->left_pos, &f->top_pos);
10349 break;
10351 case inGoAway:
10352 if (TrackGoAway (window_ptr, er.where))
10354 inev.kind = DELETE_WINDOW_EVENT;
10355 XSETFRAME (inev.frame_or_window,
10356 mac_window_to_frame (window_ptr));
10358 break;
10360 /* window resize handling added --ben */
10361 case inGrow:
10362 do_grow_window (window_ptr, &er);
10363 break;
10365 /* window zoom handling added --ben */
10366 case inZoomIn:
10367 case inZoomOut:
10368 if (TrackBox (window_ptr, er.where, part_code))
10369 do_zoom_window (window_ptr, part_code);
10370 break;
10372 default:
10373 break;
10376 break;
10378 case updateEvt:
10379 #if USE_CARBON_EVENTS
10380 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10381 != eventNotHandledErr)
10382 break;
10383 #else
10384 do_window_update ((WindowPtr) er.message);
10385 #endif
10386 break;
10388 case osEvt:
10389 #if USE_CARBON_EVENTS
10390 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10391 != eventNotHandledErr)
10392 break;
10393 #endif
10394 switch ((er.message >> 24) & 0x000000FF)
10396 case suspendResumeMessage:
10397 if ((er.message & resumeFlag) == 1)
10398 do_app_resume ();
10399 else
10400 do_app_suspend ();
10401 break;
10403 case mouseMovedMessage:
10404 #if !USE_CARBON_EVENTS
10405 SetRectRgn (mouse_region, er.where.h, er.where.v,
10406 er.where.h + 1, er.where.v + 1);
10407 #endif
10408 previous_help_echo_string = help_echo_string;
10409 help_echo_string = Qnil;
10411 if (dpyinfo->grabbed && last_mouse_frame
10412 && FRAME_LIVE_P (last_mouse_frame))
10413 f = last_mouse_frame;
10414 else
10415 f = dpyinfo->x_focus_frame;
10417 if (dpyinfo->mouse_face_hidden)
10419 dpyinfo->mouse_face_hidden = 0;
10420 clear_mouse_face (dpyinfo);
10423 if (f)
10425 WindowPtr wp = FRAME_MAC_WINDOW (f);
10426 Point mouse_pos = er.where;
10428 SetPortWindowPort (wp);
10430 GlobalToLocal (&mouse_pos);
10432 if (dpyinfo->grabbed && tracked_scroll_bar)
10433 #ifdef USE_TOOLKIT_SCROLL_BARS
10434 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
10435 mouse_pos, &inev);
10436 #else /* not USE_TOOLKIT_SCROLL_BARS */
10437 x_scroll_bar_note_movement (tracked_scroll_bar,
10438 mouse_pos.v
10439 - XINT (tracked_scroll_bar->top),
10440 er.when * (1000 / 60));
10441 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10442 else
10444 /* Generate SELECT_WINDOW_EVENTs when needed. */
10445 if (mouse_autoselect_window)
10447 Lisp_Object window;
10449 window = window_from_coordinates (f,
10450 mouse_pos.h,
10451 mouse_pos.v,
10452 0, 0, 0, 0);
10454 /* Window will be selected only when it is
10455 not selected now and last mouse movement
10456 event was not in it. Minibuffer window
10457 will be selected iff it is active. */
10458 if (WINDOWP (window)
10459 && !EQ (window, last_window)
10460 && !EQ (window, selected_window))
10462 inev.kind = SELECT_WINDOW_EVENT;
10463 inev.frame_or_window = window;
10466 last_window=window;
10468 if (!note_mouse_movement (f, &mouse_pos))
10469 help_echo_string = previous_help_echo_string;
10473 /* If the contents of the global variable
10474 help_echo_string has changed, generate a
10475 HELP_EVENT. */
10476 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
10477 do_help = 1;
10478 break;
10480 break;
10482 case activateEvt:
10484 WindowPtr window_ptr = (WindowPtr) er.message;
10486 #if USE_CARBON_EVENTS
10487 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10488 != eventNotHandledErr)
10489 break;
10490 #endif
10491 if (window_ptr == tip_window)
10493 HideWindow (tip_window);
10494 break;
10497 if (!is_emacs_window (window_ptr))
10498 break;
10500 if ((er.modifiers & activeFlag) != 0)
10502 /* A window has been activated */
10503 Point mouse_loc = er.where;
10505 x_detect_focus_change (dpyinfo, &er, &inev);
10507 SetPortWindowPort (window_ptr);
10508 GlobalToLocal (&mouse_loc);
10509 /* Window-activated event counts as mouse movement,
10510 so update things that depend on mouse position. */
10511 note_mouse_movement (mac_window_to_frame (window_ptr),
10512 &mouse_loc);
10514 else
10516 /* A window has been deactivated */
10517 #if USE_TOOLKIT_SCROLL_BARS
10518 if (dpyinfo->grabbed && tracked_scroll_bar)
10520 struct input_event event;
10522 EVENT_INIT (event);
10523 event.kind = NO_EVENT;
10524 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
10525 if (event.kind != NO_EVENT)
10527 event.timestamp = timestamp;
10528 kbd_buffer_store_event_hold (&event, hold_quit);
10529 count++;
10532 #endif
10533 dpyinfo->grabbed = 0;
10535 x_detect_focus_change (dpyinfo, &er, &inev);
10537 f = mac_window_to_frame (window_ptr);
10538 if (f == dpyinfo->mouse_face_mouse_frame)
10540 /* If we move outside the frame, then we're
10541 certainly no longer on any text in the
10542 frame. */
10543 clear_mouse_face (dpyinfo);
10544 dpyinfo->mouse_face_mouse_frame = 0;
10547 /* Generate a nil HELP_EVENT to cancel a help-echo.
10548 Do it only if there's something to cancel.
10549 Otherwise, the startup message is cleared when the
10550 mouse leaves the frame. */
10551 if (any_help_event_p)
10552 do_help = -1;
10555 break;
10557 case keyDown:
10558 case keyUp:
10559 case autoKey:
10561 int keycode = (er.message & keyCodeMask) >> 8;
10562 int xkeysym;
10563 static SInt16 last_key_script = -1;
10564 SInt16 current_key_script;
10565 UInt32 modifiers = er.modifiers, mapped_modifiers;
10567 mapped_modifiers =
10568 (NILP (Vmac_control_modifier) ? 0 : controlKey)
10569 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
10570 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
10572 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10573 mapped_modifiers |=
10574 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask);
10576 GetEventParameter (eventRef, kEventParamKeyModifiers,
10577 typeUInt32, NULL,
10578 sizeof (UInt32), NULL, &modifiers);
10579 #endif
10580 mapped_modifiers &= modifiers;
10582 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10583 /* When using Carbon Events, we need to pass raw keyboard
10584 events to the TSM ourselves. If TSM handles it, it
10585 will pass back noErr, otherwise it will pass back
10586 "eventNotHandledErr" and we can process it
10587 normally. */
10588 if (!(mapped_modifiers
10589 & ~(mac_pass_command_to_system ? cmdKey : 0)
10590 & ~(mac_pass_control_to_system ? controlKey : 0)))
10592 OSStatus err;
10594 read_socket_inev = &inev;
10595 err = SendEventToEventTarget (eventRef, toolbox_dispatcher);
10596 read_socket_inev = NULL;
10597 if (err != eventNotHandledErr)
10598 break;
10600 #endif
10601 if (er.what == keyUp)
10602 break;
10604 ObscureCursor ();
10606 f = mac_focus_frame (dpyinfo);
10608 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
10609 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
10611 clear_mouse_face (dpyinfo);
10612 dpyinfo->mouse_face_hidden = 1;
10615 current_key_script = GetScriptManagerVariable (smKeyScript);
10616 if (last_key_script != current_key_script)
10618 struct input_event event;
10620 EVENT_INIT (event);
10621 event.kind = LANGUAGE_CHANGE_EVENT;
10622 event.arg = Qnil;
10623 event.code = current_key_script;
10624 event.timestamp = timestamp;
10625 kbd_buffer_store_event (&event);
10626 count++;
10627 last_key_script = current_key_script;
10630 #if USE_MAC_TSM
10631 if (inev.kind != NO_EVENT)
10632 break;
10633 #endif
10635 #ifdef MAC_OSX
10636 if (mapped_modifiers & kEventKeyModifierFnMask
10637 && keycode <= 0x7f
10638 && fn_keycode_to_keycode_table[keycode])
10639 keycode = fn_keycode_to_keycode_table[keycode];
10640 #endif
10641 if (keycode_to_xkeysym (keycode, &xkeysym))
10643 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
10644 inev.code = 0xff00 | xkeysym;
10645 #ifdef MAC_OSX
10646 if (modifiers & kEventKeyModifierFnMask
10647 && keycode <= 0x7f
10648 && fn_keycode_to_keycode_table[keycode] == keycode)
10649 modifiers &= ~kEventKeyModifierFnMask;
10650 #endif
10652 else if (mapped_modifiers)
10654 /* translate the keycode back to determine the
10655 original key */
10656 #ifdef MAC_OSX
10657 static SInt16 last_key_layout_id = 0;
10658 static Handle uchr_handle = (Handle)-1;
10659 SInt16 current_key_layout_id =
10660 GetScriptVariable (current_key_script, smScriptKeys);
10662 if (uchr_handle == (Handle)-1
10663 || last_key_layout_id != current_key_layout_id)
10665 uchr_handle = GetResource ('uchr', current_key_layout_id);
10666 last_key_layout_id = current_key_layout_id;
10669 if (uchr_handle)
10671 OSStatus status;
10672 UInt16 key_action = er.what - keyDown;
10673 UInt32 modifier_key_state =
10674 (modifiers & ~mapped_modifiers) >> 8;
10675 UInt32 keyboard_type = LMGetKbdType ();
10676 SInt32 dead_key_state = 0;
10677 UniChar code;
10678 UniCharCount actual_length;
10680 status = UCKeyTranslate ((UCKeyboardLayout *)*uchr_handle,
10681 keycode, key_action,
10682 modifier_key_state,
10683 keyboard_type,
10684 kUCKeyTranslateNoDeadKeysMask,
10685 &dead_key_state,
10686 1, &actual_length, &code);
10687 if (status == noErr && actual_length == 1)
10688 mac_set_unicode_keystroke_event (code, &inev);
10690 #endif /* MAC_OSX */
10692 if (inev.kind == NO_EVENT)
10694 /* This code comes from Keyboard Resource,
10695 Appendix C of IM - Text. This is necessary
10696 since shift is ignored in KCHR table
10697 translation when option or command is pressed.
10698 It also does not translate correctly
10699 control-shift chars like C-% so mask off shift
10700 here also. */
10701 /* Mask off modifier keys that are mapped to some
10702 Emacs modifiers. */
10703 int new_modifiers = er.modifiers & ~mapped_modifiers;
10704 /* set high byte of keycode to modifier high byte*/
10705 int new_keycode = keycode | new_modifiers;
10706 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
10707 unsigned long some_state = 0;
10708 UInt32 new_char_code;
10710 new_char_code = KeyTranslate (kchr_ptr, new_keycode,
10711 &some_state);
10712 if (new_char_code == 0)
10713 /* Seems like a dead key. Append up-stroke. */
10714 new_char_code = KeyTranslate (kchr_ptr,
10715 new_keycode | 0x80,
10716 &some_state);
10717 if (new_char_code)
10719 inev.kind = ASCII_KEYSTROKE_EVENT;
10720 inev.code = new_char_code & 0xff;
10725 if (inev.kind == NO_EVENT)
10727 inev.kind = ASCII_KEYSTROKE_EVENT;
10728 inev.code = er.message & charCodeMask;
10731 inev.modifiers = mac_to_emacs_modifiers (modifiers);
10732 inev.modifiers |= (extra_keyboard_modifiers
10733 & (meta_modifier | alt_modifier
10734 | hyper_modifier | super_modifier));
10735 XSETFRAME (inev.frame_or_window, f);
10737 #if TARGET_API_MAC_CARBON
10738 if (inev.kind == ASCII_KEYSTROKE_EVENT
10739 && inev.code >= 0x80 && inev.modifiers)
10741 OSStatus err;
10742 TextEncoding encoding = kTextEncodingMacRoman;
10743 TextToUnicodeInfo ttu_info;
10745 UpgradeScriptInfoToTextEncoding (current_key_script,
10746 kTextLanguageDontCare,
10747 kTextRegionDontCare,
10748 NULL, &encoding);
10749 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info);
10750 if (err == noErr)
10752 UniChar code;
10753 Str255 pstr;
10754 ByteCount unicode_len;
10756 pstr[0] = 1;
10757 pstr[1] = inev.code;
10758 err = ConvertFromPStringToUnicode (ttu_info, pstr,
10759 sizeof (UniChar),
10760 &unicode_len, &code);
10761 if (err == noErr && unicode_len == sizeof (UniChar))
10762 mac_set_unicode_keystroke_event (code, &inev);
10763 DisposeTextToUnicodeInfo (&ttu_info);
10766 #endif
10768 break;
10770 case kHighLevelEvent:
10771 AEProcessAppleEvent (&er);
10772 break;
10774 default:
10775 break;
10777 #if USE_CARBON_EVENTS
10778 ReleaseEvent (eventRef);
10779 #endif
10781 if (inev.kind != NO_EVENT)
10783 inev.timestamp = timestamp;
10784 kbd_buffer_store_event_hold (&inev, hold_quit);
10785 count++;
10788 if (do_help
10789 && !(hold_quit && hold_quit->kind != NO_EVENT))
10791 Lisp_Object frame;
10793 if (f)
10794 XSETFRAME (frame, f);
10795 else
10796 frame = Qnil;
10798 if (do_help > 0)
10800 any_help_event_p = 1;
10801 gen_help_event (help_echo_string, frame, help_echo_window,
10802 help_echo_object, help_echo_pos);
10804 else
10806 help_echo_string = Qnil;
10807 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
10809 count++;
10814 /* If the focus was just given to an autoraising frame,
10815 raise it now. */
10816 /* ??? This ought to be able to handle more than one such frame. */
10817 if (pending_autoraise_frame)
10819 x_raise_frame (pending_autoraise_frame);
10820 pending_autoraise_frame = 0;
10823 #if !USE_CARBON_EVENTS
10824 /* Check which frames are still visible. We do this here because
10825 there doesn't seem to be any direct notification from the Window
10826 Manager that the visibility of a window has changed (at least,
10827 not in all cases). */
10829 Lisp_Object tail, frame;
10831 FOR_EACH_FRAME (tail, frame)
10833 struct frame *f = XFRAME (frame);
10835 /* The tooltip has been drawn already. Avoid the
10836 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10837 if (EQ (frame, tip_frame))
10838 continue;
10840 if (FRAME_MAC_P (f))
10841 mac_handle_visibility_change (f);
10844 #endif
10846 --handling_signal;
10847 UNBLOCK_INPUT;
10848 return count;
10852 /* Need to override CodeWarrior's input function so no conversion is
10853 done on newlines Otherwise compiled functions in .elc files will be
10854 read incorrectly. Defined in ...:MSL C:MSL
10855 Common:Source:buffer_io.c. */
10856 #ifdef __MWERKS__
10857 void
10858 __convert_to_newlines (unsigned char * p, size_t * n)
10860 #pragma unused(p,n)
10863 void
10864 __convert_from_newlines (unsigned char * p, size_t * n)
10866 #pragma unused(p,n)
10868 #endif
10870 #ifdef MAC_OS8
10871 void
10872 make_mac_terminal_frame (struct frame *f)
10874 Lisp_Object frame;
10875 Rect r;
10877 XSETFRAME (frame, f);
10879 f->output_method = output_mac;
10880 f->output_data.mac = (struct mac_output *)
10881 xmalloc (sizeof (struct mac_output));
10882 bzero (f->output_data.mac, sizeof (struct mac_output));
10884 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
10886 FRAME_COLS (f) = 96;
10887 FRAME_LINES (f) = 4;
10889 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
10890 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
10892 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
10894 f->output_data.mac->cursor_pixel = 0;
10895 f->output_data.mac->border_pixel = 0x00ff00;
10896 f->output_data.mac->mouse_pixel = 0xff00ff;
10897 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
10899 f->output_data.mac->text_cursor = kThemeIBeamCursor;
10900 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
10901 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
10902 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
10903 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
10904 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
10906 FRAME_FONTSET (f) = -1;
10907 f->output_data.mac->explicit_parent = 0;
10908 f->left_pos = 8;
10909 f->top_pos = 32;
10910 f->border_width = 0;
10912 f->internal_border_width = 0;
10914 f->auto_raise = 1;
10915 f->auto_lower = 1;
10917 f->new_text_cols = 0;
10918 f->new_text_lines = 0;
10920 SetRect (&r, f->left_pos, f->top_pos,
10921 f->left_pos + FRAME_PIXEL_WIDTH (f),
10922 f->top_pos + FRAME_PIXEL_HEIGHT (f));
10924 BLOCK_INPUT;
10926 if (!(FRAME_MAC_WINDOW (f) =
10927 NewCWindow (NULL, &r, "\p", true, dBoxProc,
10928 (WindowPtr) -1, 1, (long) f->output_data.mac)))
10929 abort ();
10930 /* so that update events can find this mac_output struct */
10931 f->output_data.mac->mFP = f; /* point back to emacs frame */
10933 UNBLOCK_INPUT;
10935 x_make_gc (f);
10937 /* Need to be initialized for unshow_buffer in window.c. */
10938 selected_window = f->selected_window;
10940 Fmodify_frame_parameters (frame,
10941 Fcons (Fcons (Qfont,
10942 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
10943 Fmodify_frame_parameters (frame,
10944 Fcons (Fcons (Qforeground_color,
10945 build_string ("black")), Qnil));
10946 Fmodify_frame_parameters (frame,
10947 Fcons (Fcons (Qbackground_color,
10948 build_string ("white")), Qnil));
10950 #endif
10953 /***********************************************************************
10954 Initialization
10955 ***********************************************************************/
10957 int mac_initialized = 0;
10959 void
10960 mac_initialize_display_info ()
10962 struct mac_display_info *dpyinfo = &one_mac_display_info;
10963 GDHandle main_device_handle;
10965 bzero (dpyinfo, sizeof (*dpyinfo));
10967 #ifdef MAC_OSX
10968 dpyinfo->mac_id_name
10969 = (char *) xmalloc (SCHARS (Vinvocation_name)
10970 + SCHARS (Vsystem_name)
10971 + 2);
10972 sprintf (dpyinfo->mac_id_name, "%s@%s",
10973 SDATA (Vinvocation_name), SDATA (Vsystem_name));
10974 #else
10975 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
10976 strcpy (dpyinfo->mac_id_name, "Mac Display");
10977 #endif
10979 main_device_handle = LMGetMainDevice();
10981 dpyinfo->reference_count = 0;
10982 dpyinfo->resx = 72.0;
10983 dpyinfo->resy = 72.0;
10984 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
10985 #ifdef MAC_OSX
10986 /* HasDepth returns true if it is possible to have a 32 bit display,
10987 but this may not be what is actually used. Mac OSX can do better.
10988 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10989 header for CGGetActiveDisplayList says that the first display returned
10990 is the active one, so we use that. */
10992 CGDirectDisplayID disp_id[1];
10993 CGDisplayCount disp_count;
10994 CGDisplayErr error_code;
10996 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
10997 if (error_code != 0)
10998 error ("No display found, CGGetActiveDisplayList error %d", error_code);
11000 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
11002 #else
11003 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
11004 if (HasDepth (main_device_handle, dpyinfo->n_planes,
11005 gdDevType, dpyinfo->color_p))
11006 break;
11007 #endif
11008 dpyinfo->height = (**main_device_handle).gdRect.bottom;
11009 dpyinfo->width = (**main_device_handle).gdRect.right;
11010 dpyinfo->grabbed = 0;
11011 dpyinfo->root_window = NULL;
11012 dpyinfo->image_cache = make_image_cache ();
11014 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
11015 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
11016 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
11017 dpyinfo->mouse_face_window = Qnil;
11018 dpyinfo->mouse_face_overlay = Qnil;
11019 dpyinfo->mouse_face_hidden = 0;
11023 static XrmDatabase
11024 mac_make_rdb (xrm_option)
11025 char *xrm_option;
11027 XrmDatabase database;
11029 database = xrm_get_preference_database (NULL);
11030 if (xrm_option)
11031 xrm_merge_string_database (database, xrm_option);
11033 return database;
11036 struct mac_display_info *
11037 mac_term_init (display_name, xrm_option, resource_name)
11038 Lisp_Object display_name;
11039 char *xrm_option;
11040 char *resource_name;
11042 struct mac_display_info *dpyinfo;
11044 BLOCK_INPUT;
11046 if (!mac_initialized)
11048 mac_initialize ();
11049 mac_initialized = 1;
11052 if (x_display_list)
11053 error ("Sorry, this version can only handle one display");
11055 mac_initialize_display_info ();
11057 dpyinfo = &one_mac_display_info;
11059 dpyinfo->xrdb = mac_make_rdb (xrm_option);
11061 /* Put this display on the chain. */
11062 dpyinfo->next = x_display_list;
11063 x_display_list = dpyinfo;
11065 /* Put it on x_display_name_list. */
11066 x_display_name_list = Fcons (Fcons (display_name,
11067 Fcons (Qnil, dpyinfo->xrdb)),
11068 x_display_name_list);
11069 dpyinfo->name_list_element = XCAR (x_display_name_list);
11071 UNBLOCK_INPUT;
11073 return dpyinfo;
11075 /* Get rid of display DPYINFO, assuming all frames are already gone. */
11077 void
11078 x_delete_display (dpyinfo)
11079 struct mac_display_info *dpyinfo;
11081 int i;
11083 /* Discard this display from x_display_name_list and x_display_list.
11084 We can't use Fdelq because that can quit. */
11085 if (! NILP (x_display_name_list)
11086 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
11087 x_display_name_list = XCDR (x_display_name_list);
11088 else
11090 Lisp_Object tail;
11092 tail = x_display_name_list;
11093 while (CONSP (tail) && CONSP (XCDR (tail)))
11095 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
11097 XSETCDR (tail, XCDR (XCDR (tail)));
11098 break;
11100 tail = XCDR (tail);
11104 if (x_display_list == dpyinfo)
11105 x_display_list = dpyinfo->next;
11106 else
11108 struct x_display_info *tail;
11110 for (tail = x_display_list; tail; tail = tail->next)
11111 if (tail->next == dpyinfo)
11112 tail->next = tail->next->next;
11115 /* Free the font names in the font table. */
11116 for (i = 0; i < dpyinfo->n_fonts; i++)
11117 if (dpyinfo->font_table[i].name)
11119 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
11120 xfree (dpyinfo->font_table[i].full_name);
11121 xfree (dpyinfo->font_table[i].name);
11124 if (dpyinfo->font_table->font_encoder)
11125 xfree (dpyinfo->font_table->font_encoder);
11127 xfree (dpyinfo->font_table);
11128 xfree (dpyinfo->mac_id_name);
11130 if (x_display_list == 0)
11132 mac_clear_font_name_table ();
11133 bzero (dpyinfo, sizeof (*dpyinfo));
11138 #ifdef MAC_OSX
11139 void
11140 mac_check_bundle()
11142 extern int inhibit_window_system;
11143 extern int noninteractive;
11144 CFBundleRef appsBundle;
11146 /* No need to test if already -nw*/
11147 if (inhibit_window_system || noninteractive)
11148 return;
11150 appsBundle = CFBundleGetMainBundle();
11151 if (appsBundle != NULL)
11153 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
11154 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
11155 /* We found the bundle identifier, now we know we are valid. */
11156 if (res != NULL)
11158 CFRelease(res);
11159 return;
11162 /* MAC_TODO: Have this start the bundled executable */
11164 /* For now, prevent the fatal error by bringing it up in the terminal */
11165 inhibit_window_system = 1;
11168 void
11169 MakeMeTheFrontProcess ()
11171 ProcessSerialNumber psn;
11172 OSErr err;
11174 err = GetCurrentProcess (&psn);
11175 if (err == noErr)
11176 (void) SetFrontProcess (&psn);
11179 /***** Code to handle C-g testing *****/
11181 /* Contains the Mac modifier formed from quit_char */
11182 int mac_quit_char_modifiers = 0;
11183 int mac_quit_char_keycode;
11184 extern int quit_char;
11186 static void
11187 mac_determine_quit_char_modifiers()
11189 /* Todo: Determine modifiers from quit_char. */
11190 UInt32 qc_modifiers = ctrl_modifier;
11192 /* Map modifiers */
11193 mac_quit_char_modifiers = 0;
11194 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= controlKey;
11195 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
11196 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= optionKey;
11199 static void
11200 init_quit_char_handler ()
11202 /* TODO: Let this support keys other the 'g' */
11203 mac_quit_char_keycode = 5;
11204 /* Look at <architecture/adb_kb_map.h> for details */
11205 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
11207 mac_determine_quit_char_modifiers();
11209 #endif /* MAC_OSX */
11211 static void
11212 init_menu_bar ()
11214 #ifdef MAC_OSX
11215 OSErr err;
11216 MenuRef menu;
11217 MenuItemIndex menu_index;
11219 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
11220 &menu, &menu_index);
11221 if (err == noErr)
11222 SetMenuItemCommandKey (menu, menu_index, false, 0);
11223 #if USE_CARBON_EVENTS
11224 EnableMenuCommand (NULL, kHICommandPreferences);
11225 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
11226 &menu, &menu_index);
11227 if (err == noErr)
11229 SetMenuItemCommandKey (menu, menu_index, false, 0);
11230 InsertMenuItemTextWithCFString (menu, NULL,
11231 0, kMenuItemAttrSeparator, 0);
11232 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
11233 0, 0, kHICommandAbout);
11235 #endif /* USE_CARBON_EVENTS */
11236 #else /* !MAC_OSX */
11237 #if USE_CARBON_EVENTS
11238 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
11239 #endif
11240 #endif
11243 #if USE_MAC_TSM
11244 static void
11245 init_tsm ()
11247 static InterfaceTypeList types = {kUnicodeDocument};
11249 NewTSMDocument (sizeof (types) / sizeof (types[0]), types,
11250 &tsm_document_id, 0);
11252 #endif
11254 /* Set up use of X before we make the first connection. */
11256 extern frame_parm_handler mac_frame_parm_handlers[];
11258 static struct redisplay_interface x_redisplay_interface =
11260 mac_frame_parm_handlers,
11261 x_produce_glyphs,
11262 x_write_glyphs,
11263 x_insert_glyphs,
11264 x_clear_end_of_line,
11265 x_scroll_run,
11266 x_after_update_window_line,
11267 x_update_window_begin,
11268 x_update_window_end,
11269 x_cursor_to,
11270 x_flush,
11271 0, /* flush_display_optional */
11272 x_clear_window_mouse_face,
11273 x_get_glyph_overhangs,
11274 x_fix_overlapping_area,
11275 x_draw_fringe_bitmap,
11276 #if USE_CG_DRAWING
11277 mac_define_fringe_bitmap,
11278 mac_destroy_fringe_bitmap,
11279 #else
11280 0, /* define_fringe_bitmap */
11281 0, /* destroy_fringe_bitmap */
11282 #endif
11283 mac_per_char_metric,
11284 mac_encode_char,
11285 mac_compute_glyph_string_overhangs,
11286 x_draw_glyph_string,
11287 mac_define_frame_cursor,
11288 mac_clear_frame_area,
11289 mac_draw_window_cursor,
11290 mac_draw_vertical_window_border,
11291 mac_shift_glyphs_for_insert
11294 void
11295 mac_initialize ()
11297 rif = &x_redisplay_interface;
11299 clear_frame_hook = x_clear_frame;
11300 ins_del_lines_hook = x_ins_del_lines;
11301 delete_glyphs_hook = x_delete_glyphs;
11302 ring_bell_hook = XTring_bell;
11303 reset_terminal_modes_hook = XTreset_terminal_modes;
11304 set_terminal_modes_hook = XTset_terminal_modes;
11305 update_begin_hook = x_update_begin;
11306 update_end_hook = x_update_end;
11307 set_terminal_window_hook = XTset_terminal_window;
11308 read_socket_hook = XTread_socket;
11309 frame_up_to_date_hook = XTframe_up_to_date;
11310 mouse_position_hook = XTmouse_position;
11311 frame_rehighlight_hook = XTframe_rehighlight;
11312 frame_raise_lower_hook = XTframe_raise_lower;
11314 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
11315 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
11316 redeem_scroll_bar_hook = XTredeem_scroll_bar;
11317 judge_scroll_bars_hook = XTjudge_scroll_bars;
11319 scroll_region_ok = 1; /* we'll scroll partial frames */
11320 char_ins_del_ok = 1;
11321 line_ins_del_ok = 1; /* we'll just blt 'em */
11322 fast_clear_end_of_line = 1; /* X does this well */
11323 memory_below_frame = 0; /* we don't remember what scrolls
11324 off the bottom */
11325 baud_rate = 19200;
11327 last_tool_bar_item = -1;
11328 any_help_event_p = 0;
11330 /* Try to use interrupt input; if we can't, then start polling. */
11331 Fset_input_mode (Qt, Qnil, Qt, Qnil);
11333 BLOCK_INPUT;
11335 #if TARGET_API_MAC_CARBON
11337 #if USE_CARBON_EVENTS
11338 #ifdef MAC_OSX
11339 init_service_handler ();
11341 init_quit_char_handler ();
11342 #endif /* MAC_OSX */
11344 init_command_handler ();
11346 init_menu_bar ();
11348 #if USE_MAC_TSM
11349 init_tsm ();
11350 #endif
11351 #endif /* USE_CARBON_EVENTS */
11353 #ifdef MAC_OSX
11354 init_coercion_handler ();
11356 init_apple_event_handler ();
11358 if (!inhibit_window_system)
11359 MakeMeTheFrontProcess ();
11360 #endif
11361 #endif
11363 #if USE_CG_DRAWING
11364 mac_init_fringe ();
11365 #endif
11367 UNBLOCK_INPUT;
11371 void
11372 syms_of_macterm ()
11374 #if 0
11375 staticpro (&x_error_message_string);
11376 x_error_message_string = Qnil;
11377 #endif
11379 Qcontrol = intern ("control"); staticpro (&Qcontrol);
11380 Qmeta = intern ("meta"); staticpro (&Qmeta);
11381 Qalt = intern ("alt"); staticpro (&Qalt);
11382 Qhyper = intern ("hyper"); staticpro (&Qhyper);
11383 Qsuper = intern ("super"); staticpro (&Qsuper);
11384 Qmodifier_value = intern ("modifier-value");
11385 staticpro (&Qmodifier_value);
11387 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
11388 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
11389 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
11390 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
11391 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
11393 #if USE_CARBON_EVENTS
11394 Qhicommand = intern ("hicommand"); staticpro (&Qhicommand);
11395 #ifdef MAC_OSX
11396 Qtoolbar_switch_mode = intern ("toolbar-switch-mode");
11397 staticpro (&Qtoolbar_switch_mode);
11398 #if USE_MAC_FONT_PANEL
11399 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed);
11400 Qselection = intern ("selection"); staticpro (&Qselection);
11401 #endif
11403 Qservice = intern ("service"); staticpro (&Qservice);
11404 Qpaste = intern ("paste"); staticpro (&Qpaste);
11405 Qperform = intern ("perform"); staticpro (&Qperform);
11406 #endif
11407 #if USE_MAC_TSM
11408 Qtext_input = intern ("text-input"); staticpro (&Qtext_input);
11409 Qupdate_active_input_area = intern ("update-active-input-area");
11410 staticpro (&Qupdate_active_input_area);
11411 Qunicode_for_key_event = intern ("unicode-for-key-event");
11412 staticpro (&Qunicode_for_key_event);
11413 #endif
11414 #endif
11416 #ifdef MAC_OSX
11417 Fprovide (intern ("mac-carbon"), Qnil);
11418 #endif
11420 staticpro (&Qreverse);
11421 Qreverse = intern ("reverse");
11423 staticpro (&x_display_name_list);
11424 x_display_name_list = Qnil;
11426 staticpro (&last_mouse_scroll_bar);
11427 last_mouse_scroll_bar = Qnil;
11429 staticpro (&fm_font_family_alist);
11430 fm_font_family_alist = Qnil;
11432 #if USE_ATSUI
11433 staticpro (&atsu_font_id_hash);
11434 atsu_font_id_hash = Qnil;
11435 #endif
11437 /* We don't yet support this, but defining this here avoids whining
11438 from cus-start.el and other places, like "M-x set-variable". */
11439 DEFVAR_BOOL ("x-use-underline-position-properties",
11440 &x_use_underline_position_properties,
11441 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11442 nil means ignore them. If you encounter fonts with bogus
11443 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11444 to 4.1, set this to nil.
11446 NOTE: Not supported on Mac yet. */);
11447 x_use_underline_position_properties = 0;
11449 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
11450 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
11451 #ifdef USE_TOOLKIT_SCROLL_BARS
11452 Vx_toolkit_scroll_bars = Qt;
11453 #else
11454 Vx_toolkit_scroll_bars = Qnil;
11455 #endif
11457 staticpro (&last_mouse_motion_frame);
11458 last_mouse_motion_frame = Qnil;
11460 /* Variables to configure modifier key assignment. */
11462 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
11463 doc: /* *Modifier key assumed when the Mac control key is pressed.
11464 The value can be `control', `meta', `alt', `hyper', or `super' for the
11465 respective modifier. The default is `control'. */);
11466 Vmac_control_modifier = Qcontrol;
11468 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
11469 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
11470 The value can be `control', `meta', `alt', `hyper', or `super' for the
11471 respective modifier. If the value is nil then the key will act as the
11472 normal Mac control modifier, and the option key can be used to compose
11473 characters depending on the chosen Mac keyboard setting. */);
11474 Vmac_option_modifier = Qnil;
11476 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
11477 doc: /* *Modifier key assumed when the Mac command key is pressed.
11478 The value can be `control', `meta', `alt', `hyper', or `super' for the
11479 respective modifier. The default is `meta'. */);
11480 Vmac_command_modifier = Qmeta;
11482 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
11483 doc: /* *Modifier key assumed when the Mac function key is pressed.
11484 The value can be `control', `meta', `alt', `hyper', or `super' for the
11485 respective modifier. Note that remapping the function key may lead to
11486 unexpected results for some keys on non-US/GB keyboards. */);
11487 Vmac_function_modifier = Qnil;
11489 DEFVAR_LISP ("mac-emulate-three-button-mouse",
11490 &Vmac_emulate_three_button_mouse,
11491 doc: /* *Specify a way of three button mouse emulation.
11492 The value can be nil, t, or the symbol `reverse'.
11493 nil means that no emulation should be done and the modifiers should be
11494 placed on the mouse-1 event.
11495 t means that when the option-key is held down while pressing the mouse
11496 button, the click will register as mouse-2 and while the command-key
11497 is held down, the click will register as mouse-3.
11498 The symbol `reverse' means that the option-key will register for
11499 mouse-3 and the command-key will register for mouse-2. */);
11500 Vmac_emulate_three_button_mouse = Qnil;
11502 #if USE_CARBON_EVENTS
11503 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
11504 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
11505 Otherwise, the right click will be treated as mouse-2 and the wheel
11506 button will be mouse-3. */);
11507 mac_wheel_button_is_mouse_2 = 1;
11509 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
11510 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
11511 mac_pass_command_to_system = 1;
11513 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
11514 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
11515 mac_pass_control_to_system = 1;
11517 #endif
11519 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
11520 doc: /* *If non-nil, allow anti-aliasing.
11521 The text will be rendered using Core Graphics text rendering which
11522 may anti-alias the text. */);
11523 #if USE_CG_DRAWING
11524 mac_use_core_graphics = 1;
11525 #else
11526 mac_use_core_graphics = 0;
11527 #endif
11529 /* Register an entry for `mac-roman' so that it can be used when
11530 creating the terminal frame on Mac OS 9 before loading
11531 term/mac-win.elc. */
11532 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
11533 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
11534 Each entry should be of the form:
11536 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
11538 where CHARSET-NAME is a string used in font names to identify the
11539 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
11540 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
11541 Vmac_charset_info_alist =
11542 Fcons (list3 (build_string ("mac-roman"),
11543 make_number (smRoman), Qnil), Qnil);
11545 #if USE_ATSUI
11546 DEFVAR_LISP ("mac-atsu-font-table", &Vmac_atsu_font_table,
11547 doc: /* Hash table of ATSU font IDs vs plist of attributes and values.
11548 Each font ID is represented as a four-byte string in native byte
11549 order. */);
11550 Vmac_atsu_font_table =
11551 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
11552 make_float (DEFAULT_REHASH_SIZE),
11553 make_float (DEFAULT_REHASH_THRESHOLD),
11554 Qnil, Qnil, Qnil);
11555 #endif
11556 #if USE_MAC_TSM
11557 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay,
11558 doc: /* Overlay used to display Mac TSM active input area. */);
11559 Vmac_ts_active_input_overlay = Qnil;
11560 #endif
11563 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11564 (do not change this comment) */