(Fnetwork_interface_info): Correctly terminate the
[emacs.git] / src / macterm.c
blob1adbad9ddd75de5fb1ea2dae342d109974b6822b
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 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 "gnu.h"
81 #include "disptab.h"
82 #include "buffer.h"
83 #include "window.h"
84 #include "keyboard.h"
85 #include "intervals.h"
86 #include "atimer.h"
87 #include "keymap.h"
91 /* Non-nil means Emacs uses toolkit scroll bars. */
93 Lisp_Object Vx_toolkit_scroll_bars;
95 /* If non-zero, the text will be rendered using Core Graphics text
96 rendering which may anti-alias the text. */
97 int mac_use_core_graphics;
100 /* Non-zero means that a HELP_EVENT has been generated since Emacs
101 start. */
103 static int any_help_event_p;
105 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
106 static Lisp_Object last_window;
108 /* Non-zero means make use of UNDERLINE_POSITION font properties.
109 (Not yet supported.) */
110 int x_use_underline_position_properties;
112 /* This is a chain of structures for all the X displays currently in
113 use. */
115 struct x_display_info *x_display_list;
117 /* This is a list of cons cells, each of the form (NAME
118 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
119 x_display_list and in the same order. NAME is the name of the
120 frame. FONT-LIST-CACHE records previous values returned by
121 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
122 equivalent, which is implemented with a Lisp object, for the
123 display. */
125 Lisp_Object x_display_name_list;
127 /* This is display since Mac does not support multiple ones. */
128 struct mac_display_info one_mac_display_info;
130 /* Frame being updated by update_frame. This is declared in term.c.
131 This is set by update_begin and looked at by all the XT functions.
132 It is zero while not inside an update. In that case, the XT
133 functions assume that `selected_frame' is the frame to apply to. */
135 extern struct frame *updating_frame;
137 /* This is a frame waiting to be auto-raised, within XTread_socket. */
139 struct frame *pending_autoraise_frame;
141 /* Mouse movement.
143 Formerly, we used PointerMotionHintMask (in standard_event_mask)
144 so that we would have to call XQueryPointer after each MotionNotify
145 event to ask for another such event. However, this made mouse tracking
146 slow, and there was a bug that made it eventually stop.
148 Simply asking for MotionNotify all the time seems to work better.
150 In order to avoid asking for motion events and then throwing most
151 of them away or busy-polling the server for mouse positions, we ask
152 the server for pointer motion hints. This means that we get only
153 one event per group of mouse movements. "Groups" are delimited by
154 other kinds of events (focus changes and button clicks, for
155 example), or by XQueryPointer calls; when one of these happens, we
156 get another MotionNotify event the next time the mouse moves. This
157 is at least as efficient as getting motion events when mouse
158 tracking is on, and I suspect only negligibly worse when tracking
159 is off. */
161 /* Where the mouse was last time we reported a mouse event. */
163 static Rect last_mouse_glyph;
164 static FRAME_PTR last_mouse_glyph_frame;
166 /* The scroll bar in which the last X motion event occurred.
168 If the last X motion event occurred in a scroll bar, we set this so
169 XTmouse_position can know whether to report a scroll bar motion or
170 an ordinary motion.
172 If the last X motion event didn't occur in a scroll bar, we set
173 this to Qnil, to tell XTmouse_position to return an ordinary motion
174 event. */
176 static Lisp_Object last_mouse_scroll_bar;
178 /* This is a hack. We would really prefer that XTmouse_position would
179 return the time associated with the position it returns, but there
180 doesn't seem to be any way to wrest the time-stamp from the server
181 along with the position query. So, we just keep track of the time
182 of the last movement we received, and return that in hopes that
183 it's somewhat accurate. */
185 static Time last_mouse_movement_time;
187 struct scroll_bar *tracked_scroll_bar = NULL;
189 /* Incremented by XTread_socket whenever it really tries to read
190 events. */
192 #ifdef __STDC__
193 static int volatile input_signal_count;
194 #else
195 static int input_signal_count;
196 #endif
198 extern Lisp_Object Vsystem_name;
200 /* A mask of extra modifier bits to put into every keyboard char. */
202 extern EMACS_INT extra_keyboard_modifiers;
204 /* The keysyms to use for the various modifiers. */
206 static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value;
208 extern int inhibit_window_system;
210 #if __MRC__ && !TARGET_API_MAC_CARBON
211 QDGlobals qd; /* QuickDraw global information structure. */
212 #endif
214 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
216 struct mac_display_info *mac_display_info_for_display (Display *);
217 static void x_update_window_end P_ ((struct window *, int, int));
218 static int x_io_error_quitter P_ ((Display *));
219 int x_catch_errors P_ ((Display *));
220 void x_uncatch_errors P_ ((Display *, int));
221 void x_lower_frame P_ ((struct frame *));
222 void x_scroll_bar_clear P_ ((struct frame *));
223 int x_had_errors_p P_ ((Display *));
224 void x_wm_set_size_hint P_ ((struct frame *, long, int));
225 void x_raise_frame P_ ((struct frame *));
226 void x_set_window_size P_ ((struct frame *, int, int, int));
227 void x_wm_set_window_state P_ ((struct frame *, int));
228 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
229 void mac_initialize P_ ((void));
230 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
231 static int x_compute_min_glyph_bounds P_ ((struct frame *));
232 static void x_update_end P_ ((struct frame *));
233 static void XTframe_up_to_date P_ ((struct frame *));
234 static void XTset_terminal_modes P_ ((void));
235 static void XTreset_terminal_modes P_ ((void));
236 static void x_clear_frame P_ ((void));
237 static void frame_highlight P_ ((struct frame *));
238 static void frame_unhighlight P_ ((struct frame *));
239 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
240 static void mac_focus_changed P_ ((int, struct mac_display_info *,
241 struct frame *, struct input_event *));
242 static void x_detect_focus_change P_ ((struct mac_display_info *,
243 EventRecord *, struct input_event *));
244 static void XTframe_rehighlight P_ ((struct frame *));
245 static void x_frame_rehighlight P_ ((struct x_display_info *));
246 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
247 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
248 enum text_cursor_kinds));
250 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
251 static void x_flush P_ ((struct frame *f));
252 static void x_update_begin P_ ((struct frame *));
253 static void x_update_window_begin P_ ((struct window *));
254 static void x_after_update_window_line P_ ((struct glyph_row *));
255 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
256 enum scroll_bar_part *,
257 Lisp_Object *, Lisp_Object *,
258 unsigned long *));
260 static int is_emacs_window P_ ((WindowPtr));
261 static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int));
262 static void XSetFont P_ ((Display *, GC, XFontStruct *));
264 /* Defined in macmenu.h. */
265 extern void menubar_selection_callback (FRAME_PTR, int);
267 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
268 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
269 #define GC_FONT(gc) ((gc)->xgcv.font)
270 #define GC_CLIP_REGION(gc) ((gc)->clip_region)
271 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
273 static RgnHandle saved_port_clip_region = NULL;
275 static void
276 mac_begin_clip (region)
277 RgnHandle region;
279 static RgnHandle new_region = NULL;
281 if (saved_port_clip_region == NULL)
282 saved_port_clip_region = NewRgn ();
283 if (new_region == NULL)
284 new_region = NewRgn ();
286 if (region)
288 GetClip (saved_port_clip_region);
289 SectRgn (saved_port_clip_region, region, new_region);
290 SetClip (new_region);
294 static void
295 mac_end_clip (region)
296 RgnHandle region;
298 if (region)
299 SetClip (saved_port_clip_region);
303 /* X display function emulation */
305 void
306 XFreePixmap (display, pixmap)
307 Display *display; /* not used */
308 Pixmap pixmap;
310 DisposeGWorld (pixmap);
314 /* Mac version of XDrawLine. */
316 static void
317 mac_draw_line (f, gc, x1, y1, x2, y2)
318 struct frame *f;
319 GC gc;
320 int x1, y1, x2, y2;
322 SetPortWindowPort (FRAME_MAC_WINDOW (f));
324 RGBForeColor (GC_FORE_COLOR (gc));
326 mac_begin_clip (GC_CLIP_REGION (gc));
327 MoveTo (x1, y1);
328 LineTo (x2, y2);
329 mac_end_clip (GC_CLIP_REGION (gc));
332 void
333 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
334 Display *display;
335 Pixmap p;
336 GC gc;
337 int x1, y1, x2, y2;
339 CGrafPtr old_port;
340 GDHandle old_gdh;
342 GetGWorld (&old_port, &old_gdh);
343 SetGWorld (p, NULL);
345 RGBForeColor (GC_FORE_COLOR (gc));
347 LockPixels (GetGWorldPixMap (p));
348 MoveTo (x1, y1);
349 LineTo (x2, y2);
350 UnlockPixels (GetGWorldPixMap (p));
352 SetGWorld (old_port, old_gdh);
356 static void
357 mac_erase_rectangle (f, gc, x, y, width, height)
358 struct frame *f;
359 GC gc;
360 int x, y;
361 unsigned int width, height;
363 Rect r;
365 SetPortWindowPort (FRAME_MAC_WINDOW (f));
367 RGBBackColor (GC_BACK_COLOR (gc));
368 SetRect (&r, x, y, x + width, y + height);
370 mac_begin_clip (GC_CLIP_REGION (gc));
371 EraseRect (&r);
372 mac_end_clip (GC_CLIP_REGION (gc));
374 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
378 /* Mac version of XClearArea. */
380 void
381 mac_clear_area (f, x, y, width, height)
382 struct frame *f;
383 int x, y;
384 unsigned int width, height;
386 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height);
389 /* Mac version of XClearWindow. */
391 static void
392 mac_clear_window (f)
393 struct frame *f;
395 SetPortWindowPort (FRAME_MAC_WINDOW (f));
397 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
399 #if TARGET_API_MAC_CARBON
401 Rect r;
403 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
404 EraseRect (&r);
406 #else /* not TARGET_API_MAC_CARBON */
407 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect));
408 #endif /* not TARGET_API_MAC_CARBON */
412 /* Mac replacement for XCopyArea. */
414 static void
415 mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p)
416 struct frame *f;
417 GC gc;
418 int x, y, width, height;
419 unsigned short *bits;
420 int overlay_p;
422 BitMap bitmap;
423 Rect r;
425 bitmap.rowBytes = sizeof(unsigned short);
426 bitmap.baseAddr = (char *)bits;
427 SetRect (&(bitmap.bounds), 0, 0, width, height);
429 SetPortWindowPort (FRAME_MAC_WINDOW (f));
431 RGBForeColor (GC_FORE_COLOR (gc));
432 RGBBackColor (GC_BACK_COLOR (gc));
433 SetRect (&r, x, y, x + width, y + height);
435 mac_begin_clip (GC_CLIP_REGION (gc));
436 #if TARGET_API_MAC_CARBON
438 CGrafPtr port;
440 GetPort (&port);
441 LockPortBits (port);
442 CopyBits (&bitmap, GetPortBitMapForCopyBits (port),
443 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
444 UnlockPortBits (port);
446 #else /* not TARGET_API_MAC_CARBON */
447 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r,
448 overlay_p ? srcOr : srcCopy, 0);
449 #endif /* not TARGET_API_MAC_CARBON */
450 mac_end_clip (GC_CLIP_REGION (gc));
452 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
456 /* Mac replacement for XCreateBitmapFromBitmapData. */
458 static void
459 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
460 BitMap *bitmap;
461 char *bits;
462 int w, h;
464 static unsigned char swap_nibble[16]
465 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
466 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
467 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
468 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
469 int i, j, w1;
470 char *p;
472 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
473 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
474 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
475 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
476 for (i = 0; i < h; i++)
478 p = bitmap->baseAddr + i * bitmap->rowBytes;
479 for (j = 0; j < w1; j++)
481 /* Bitswap XBM bytes to match how Mac does things. */
482 unsigned char c = *bits++;
483 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
484 | (swap_nibble[(c>>4) & 0xf]));;
488 SetRect (&(bitmap->bounds), 0, 0, w, h);
492 static void
493 mac_free_bitmap (bitmap)
494 BitMap *bitmap;
496 xfree (bitmap->baseAddr);
500 Pixmap
501 XCreatePixmap (display, w, width, height, depth)
502 Display *display; /* not used */
503 WindowPtr w;
504 unsigned int width, height;
505 unsigned int depth;
507 Pixmap pixmap;
508 Rect r;
509 QDErr err;
511 SetPortWindowPort (w);
513 SetRect (&r, 0, 0, width, height);
514 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
515 if (err != noErr)
516 return NULL;
517 return pixmap;
521 Pixmap
522 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
523 Display *display; /* not used */
524 WindowPtr w;
525 char *data;
526 unsigned int width, height;
527 unsigned long fg, bg;
528 unsigned int depth;
530 Pixmap pixmap;
531 BitMap bitmap;
532 CGrafPtr old_port;
533 GDHandle old_gdh;
534 static GC gc = NULL; /* not reentrant */
536 if (gc == NULL)
537 gc = XCreateGC (display, w, 0, NULL);
539 pixmap = XCreatePixmap (display, w, width, height, depth);
540 if (pixmap == NULL)
541 return NULL;
543 GetGWorld (&old_port, &old_gdh);
544 SetGWorld (pixmap, NULL);
545 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
546 XSetForeground (display, gc, fg);
547 XSetBackground (display, gc, bg);
548 RGBForeColor (GC_FORE_COLOR (gc));
549 RGBBackColor (GC_BACK_COLOR (gc));
550 LockPixels (GetGWorldPixMap (pixmap));
551 #if TARGET_API_MAC_CARBON
552 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
553 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
554 #else /* not TARGET_API_MAC_CARBON */
555 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
556 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
557 #endif /* not TARGET_API_MAC_CARBON */
558 UnlockPixels (GetGWorldPixMap (pixmap));
559 SetGWorld (old_port, old_gdh);
560 mac_free_bitmap (&bitmap);
562 return pixmap;
566 /* Mac replacement for XFillRectangle. */
568 static void
569 mac_fill_rectangle (f, gc, x, y, width, height)
570 struct frame *f;
571 GC gc;
572 int x, y;
573 unsigned int width, height;
575 Rect r;
577 SetPortWindowPort (FRAME_MAC_WINDOW (f));
579 RGBForeColor (GC_FORE_COLOR (gc));
580 SetRect (&r, x, y, x + width, y + height);
582 mac_begin_clip (GC_CLIP_REGION (gc));
583 PaintRect (&r); /* using foreground color of gc */
584 mac_end_clip (GC_CLIP_REGION (gc));
588 /* Mac replacement for XDrawRectangle: dest is a window. */
590 static void
591 mac_draw_rectangle (f, gc, x, y, width, height)
592 struct frame *f;
593 GC gc;
594 int x, y;
595 unsigned int width, height;
597 Rect r;
599 SetPortWindowPort (FRAME_MAC_WINDOW (f));
601 RGBForeColor (GC_FORE_COLOR (gc));
602 SetRect (&r, x, y, x + width + 1, y + height + 1);
604 mac_begin_clip (GC_CLIP_REGION (gc));
605 FrameRect (&r); /* using foreground color of gc */
606 mac_end_clip (GC_CLIP_REGION (gc));
610 #if USE_ATSUI
611 static OSStatus
612 atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout)
613 ConstUniCharArrayPtr text;
614 UniCharCount text_length;
615 ATSUStyle style;
616 ATSUTextLayout *text_layout;
618 OSStatus err;
619 static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */
621 if (saved_text_layout == NULL)
623 UniCharCount lengths[] = {kATSUToTextEnd};
624 ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag};
625 ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)};
626 static ATSLineLayoutOptions line_layout =
627 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
628 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics
629 #else
630 kATSLineIsDisplayOnly | kATSLineFractDisable
631 #endif
633 ATSUAttributeValuePtr values[] = {&line_layout};
635 err = ATSUCreateTextLayoutWithTextPtr (text,
636 kATSUFromTextBeginning,
637 kATSUToTextEnd,
638 text_length,
639 1, lengths, &style,
640 &saved_text_layout);
641 if (err == noErr)
642 err = ATSUSetLayoutControls (saved_text_layout,
643 sizeof (tags) / sizeof (tags[0]),
644 tags, sizes, values);
645 /* XXX: Should we do this? */
646 if (err == noErr)
647 err = ATSUSetTransientFontMatching (saved_text_layout, true);
649 else
651 err = ATSUSetRunStyle (saved_text_layout, style,
652 kATSUFromTextBeginning, kATSUToTextEnd);
653 if (err == noErr)
654 err = ATSUSetTextPointerLocation (saved_text_layout, text,
655 kATSUFromTextBeginning,
656 kATSUToTextEnd,
657 text_length);
660 if (err == noErr)
661 *text_layout = saved_text_layout;
662 return err;
664 #endif
667 static void
668 mac_invert_rectangle (f, x, y, width, height)
669 struct frame *f;
670 int x, y;
671 unsigned int width, height;
673 Rect r;
675 SetPortWindowPort (FRAME_MAC_WINDOW (f));
677 SetRect (&r, x, y, x + width, y + height);
679 InvertRect (&r);
683 static void
684 mac_draw_string_common (f, gc, x, y, buf, nchars, mode, bytes_per_char)
685 struct frame *f;
686 GC gc;
687 int x, y;
688 char *buf;
689 int nchars, mode, bytes_per_char;
691 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
692 UInt32 textFlags, savedFlags;
693 if (mac_use_core_graphics) {
694 textFlags = kQDUseCGTextRendering;
695 savedFlags = SwapQDTextFlags(textFlags);
697 #endif
699 SetPortWindowPort (FRAME_MAC_WINDOW (f));
701 RGBForeColor (GC_FORE_COLOR (gc));
702 if (mode != srcOr)
703 RGBBackColor (GC_BACK_COLOR (gc));
705 #if USE_ATSUI
706 if (GC_FONT (gc)->mac_style)
708 OSErr err;
709 ATSUTextLayout text_layout;
711 xassert (bytes_per_char == 2);
713 #ifndef WORDS_BIG_ENDIAN
715 int i;
716 UniChar *text = (UniChar *)buf;
718 for (i = 0; i < nchars; i++)
719 text[i] = EndianU16_BtoN (text[i]);
721 #endif
722 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf,
723 nchars,
724 GC_FONT (gc)->mac_style,
725 &text_layout);
726 if (err == noErr)
728 #ifdef MAC_OSX
729 if (!mac_use_core_graphics)
731 #endif
732 mac_begin_clip (GC_CLIP_REGION (gc));
733 MoveTo (x, y);
734 ATSUDrawText (text_layout,
735 kATSUFromTextBeginning, kATSUToTextEnd,
736 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
737 mac_end_clip (GC_CLIP_REGION (gc));
738 #ifdef MAC_OSX
740 else
742 CGrafPtr port;
743 CGContextRef context;
744 float port_height = FRAME_PIXEL_HEIGHT (f);
745 ATSUAttributeTag tags[] = {kATSUCGContextTag};
746 ByteCount sizes[] = {sizeof (CGContextRef)};
747 ATSUAttributeValuePtr values[] = {&context};
749 GetPort (&port);
750 QDBeginCGContext (port, &context);
751 if (gc->n_clip_rects)
753 CGContextTranslateCTM (context, 0, port_height);
754 CGContextScaleCTM (context, 1, -1);
755 CGContextClipToRects (context, gc->clip_rects,
756 gc->n_clip_rects);
757 CGContextScaleCTM (context, 1, -1);
758 CGContextTranslateCTM (context, 0, -port_height);
760 CGContextSetRGBFillColor
761 (context,
762 RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
763 GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
764 BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
765 1.0);
766 err = ATSUSetLayoutControls (text_layout,
767 sizeof (tags) / sizeof (tags[0]),
768 tags, sizes, values);
769 if (err == noErr)
770 ATSUDrawText (text_layout,
771 kATSUFromTextBeginning, kATSUToTextEnd,
772 Long2Fix (x), Long2Fix (port_height - y));
773 CGContextSynchronize (context);
774 QDEndCGContext (port, &context);
775 #if 0
776 /* This doesn't work on Mac OS X 10.1. */
777 ATSUClearLayoutControls (text_layout,
778 sizeof (tags) / sizeof (tags[0]),
779 tags);
780 #else
781 ATSUSetLayoutControls (text_layout,
782 sizeof (tags) / sizeof (tags[0]),
783 tags, sizes, values);
784 #endif
786 #endif
789 else
791 #endif
792 TextFont (GC_FONT (gc)->mac_fontnum);
793 TextSize (GC_FONT (gc)->mac_fontsize);
794 TextFace (GC_FONT (gc)->mac_fontface);
795 TextMode (mode);
797 mac_begin_clip (GC_CLIP_REGION (gc));
798 MoveTo (x, y);
799 DrawText (buf, 0, nchars * bytes_per_char);
800 mac_end_clip (GC_CLIP_REGION (gc));
801 #if USE_ATSUI
803 #endif
805 if (mode != srcOr)
806 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
807 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
808 if (mac_use_core_graphics)
809 SwapQDTextFlags(savedFlags);
810 #endif
814 /* Mac replacement for XDrawString. */
816 static void
817 mac_draw_string (f, gc, x, y, buf, nchars)
818 struct frame *f;
819 GC gc;
820 int x, y;
821 char *buf;
822 int nchars;
824 mac_draw_string_common (f, gc, x, y, buf, nchars, srcOr, 1);
828 /* Mac replacement for XDrawString16. */
830 static void
831 mac_draw_string_16 (f, gc, x, y, buf, nchars)
832 struct frame *f;
833 GC gc;
834 int x, y;
835 XChar2b *buf;
836 int nchars;
838 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcOr, 2);
842 /* Mac replacement for XDrawImageString. */
844 static void
845 mac_draw_image_string (f, gc, x, y, buf, nchars)
846 struct frame *f;
847 GC gc;
848 int x, y;
849 char *buf;
850 int nchars;
852 mac_draw_string_common (f, gc, x, y, buf, nchars, srcCopy, 1);
856 /* Mac replacement for XDrawString16. */
858 static void
859 mac_draw_image_string_16 (f, gc, x, y, buf, nchars)
860 struct frame *f;
861 GC gc;
862 int x, y;
863 XChar2b *buf;
864 int nchars;
866 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, srcCopy, 2);
870 /* Mac replacement for XQueryTextExtents, but takes a character. If
871 STYLE is NULL, measurement is done by QuickDraw Text routines for
872 the font of the current graphics port. If CG_GLYPH is not NULL,
873 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
875 static OSErr
876 mac_query_char_extents (style, c,
877 font_ascent_return, font_descent_return,
878 overall_return, cg_glyph)
879 #if USE_ATSUI
880 ATSUStyle style;
881 #else
882 void *style;
883 #endif
884 int c;
885 int *font_ascent_return, *font_descent_return;
886 XCharStruct *overall_return;
887 #if USE_CG_TEXT_DRAWING
888 CGGlyph *cg_glyph;
889 #else
890 void *cg_glyph;
891 #endif
893 OSErr err = noErr;
894 int width;
895 Rect char_bounds;
897 #if USE_ATSUI
898 if (style)
900 ATSUTextLayout text_layout;
901 UniChar ch = c;
903 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout);
904 if (err == noErr)
906 ATSTrapezoid glyph_bounds;
908 err = ATSUGetGlyphBounds (text_layout, 0, 0,
909 kATSUFromTextBeginning, kATSUToTextEnd,
910 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
911 kATSUseFractionalOrigins,
912 #else
913 kATSUseDeviceOrigins,
914 #endif
915 1, &glyph_bounds, NULL);
916 if (err == noErr)
918 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x
919 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x);
921 width = Fix2Long (glyph_bounds.upperRight.x
922 - glyph_bounds.upperLeft.x);
923 if (font_ascent_return)
924 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y);
925 if (font_descent_return)
926 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y);
929 if (err == noErr && overall_return)
931 err = ATSUMeasureTextImage (text_layout,
932 kATSUFromTextBeginning, kATSUToTextEnd,
933 0, 0, &char_bounds);
934 if (err == noErr)
935 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
936 #if USE_CG_TEXT_DRAWING
937 if (err == noErr && cg_glyph)
939 OSErr err1;
940 ATSUGlyphInfoArray glyph_info_array;
941 ByteCount count = sizeof (ATSUGlyphInfoArray);
943 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning,
944 kATSUToTextEnd, NULL, NULL, NULL);
945 if (err1 == noErr)
946 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning,
947 kATSUToTextEnd, &count,
948 &glyph_info_array);
949 if (err1 == noErr)
951 xassert (glyph_info_array.glyphs[0].glyphID);
952 *cg_glyph = glyph_info_array.glyphs[0].glyphID;
954 else
955 *cg_glyph = 0;
957 #endif
960 else
961 #endif
963 if (font_ascent_return || font_descent_return)
965 FontInfo font_info;
967 GetFontInfo (&font_info);
968 if (font_ascent_return)
969 *font_ascent_return = font_info.ascent;
970 if (font_descent_return)
971 *font_descent_return = font_info.descent;
973 if (overall_return)
975 char ch = c;
977 width = CharWidth (ch);
978 QDTextBounds (1, &ch, &char_bounds);
979 STORE_XCHARSTRUCT (*overall_return, width, char_bounds);
983 return err;
987 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
989 static int
990 mac_text_extents_16 (font_struct, string, nchars, overall_return)
991 XFontStruct *font_struct;
992 XChar2b *string;
993 int nchars;
994 XCharStruct *overall_return;
996 int i;
997 short width = 0, lbearing = 0, rbearing = 0;
998 XCharStruct *pcm;
1000 for (i = 0; i < nchars; i++)
1002 pcm = mac_per_char_metric (font_struct, string, 0);
1003 if (pcm == NULL)
1004 width += FONT_WIDTH (font_struct);
1005 else
1007 lbearing = min (lbearing, width + pcm->lbearing);
1008 rbearing = max (rbearing, width + pcm->rbearing);
1009 width += pcm->width;
1011 string++;
1014 overall_return->lbearing = lbearing;
1015 overall_return->rbearing = rbearing;
1016 overall_return->width = width;
1018 /* What's the meaning of the return value of XTextExtents16? */
1022 #if USE_CG_TEXT_DRAWING
1023 static int cg_text_anti_aliasing_threshold = 8;
1025 static void
1026 init_cg_text_anti_aliasing_threshold ()
1028 Lisp_Object val =
1029 Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
1030 Qnil, Qnil, Qnil);
1032 if (INTEGERP (val))
1033 cg_text_anti_aliasing_threshold = XINT (val);
1036 static int
1037 mac_draw_string_cg (f, gc, x, y, buf, nchars)
1038 struct frame *f;
1039 GC gc;
1040 int x, y;
1041 XChar2b *buf;
1042 int nchars;
1044 CGrafPtr port;
1045 float port_height, gx, gy;
1046 int i;
1047 CGContextRef context;
1048 CGGlyph *glyphs;
1049 CGSize *advances;
1051 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL)
1052 return 0;
1054 port = GetWindowPort (FRAME_MAC_WINDOW (f));
1055 port_height = FRAME_PIXEL_HEIGHT (f);
1056 gx = x;
1057 gy = port_height - y;
1058 glyphs = (CGGlyph *)buf;
1059 advances = xmalloc (sizeof (CGSize) * nchars);
1060 for (i = 0; i < nchars; i++)
1062 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0);
1064 advances[i].width = pcm->width;
1065 advances[i].height = 0;
1066 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2];
1067 buf++;
1070 QDBeginCGContext (port, &context);
1071 if (gc->n_clip_rects)
1073 CGContextTranslateCTM (context, 0, port_height);
1074 CGContextScaleCTM (context, 1, -1);
1075 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects);
1076 CGContextScaleCTM (context, 1, -1);
1077 CGContextTranslateCTM (context, 0, -port_height);
1079 CGContextSetRGBFillColor (context,
1080 RED_FROM_ULONG (gc->xgcv.foreground) / 255.0,
1081 GREEN_FROM_ULONG (gc->xgcv.foreground) / 255.0,
1082 BLUE_FROM_ULONG (gc->xgcv.foreground) / 255.0,
1083 1.0);
1084 CGContextSetFont (context, GC_FONT (gc)->cg_font);
1085 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize);
1086 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold)
1087 CGContextSetShouldAntialias (context, false);
1088 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1089 CGContextSetTextPosition (context, gx, gy);
1090 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars);
1091 #else
1092 for (i = 0; i < nchars; i++)
1094 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1);
1095 gx += advances[i].width;
1097 #endif
1098 CGContextSynchronize (context);
1099 QDEndCGContext (port, &context);
1101 xfree (advances);
1103 return 1;
1105 #endif
1108 /* Mac replacement for XCopyArea: dest must be window. */
1110 static void
1111 mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y)
1112 Pixmap src;
1113 struct frame *f;
1114 GC gc;
1115 int src_x, src_y;
1116 unsigned int width, height;
1117 int dest_x, dest_y;
1119 Rect src_r, dest_r;
1121 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1123 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1124 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1126 ForeColor (blackColor);
1127 BackColor (whiteColor);
1129 mac_begin_clip (GC_CLIP_REGION (gc));
1130 LockPixels (GetGWorldPixMap (src));
1131 #if TARGET_API_MAC_CARBON
1133 CGrafPtr port;
1135 GetPort (&port);
1136 LockPortBits (port);
1137 CopyBits (GetPortBitMapForCopyBits (src),
1138 GetPortBitMapForCopyBits (port),
1139 &src_r, &dest_r, srcCopy, 0);
1140 UnlockPortBits (port);
1142 #else /* not TARGET_API_MAC_CARBON */
1143 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits),
1144 &src_r, &dest_r, srcCopy, 0);
1145 #endif /* not TARGET_API_MAC_CARBON */
1146 UnlockPixels (GetGWorldPixMap (src));
1147 mac_end_clip (GC_CLIP_REGION (gc));
1149 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1153 static void
1154 mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y,
1155 width, height, dest_x, dest_y)
1156 Pixmap src, mask;
1157 struct frame *f;
1158 GC gc;
1159 int src_x, src_y;
1160 unsigned int width, height;
1161 int dest_x, dest_y;
1163 Rect src_r, dest_r;
1165 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1167 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1168 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1170 ForeColor (blackColor);
1171 BackColor (whiteColor);
1173 mac_begin_clip (GC_CLIP_REGION (gc));
1174 LockPixels (GetGWorldPixMap (src));
1175 LockPixels (GetGWorldPixMap (mask));
1176 #if TARGET_API_MAC_CARBON
1178 CGrafPtr port;
1180 GetPort (&port);
1181 LockPortBits (port);
1182 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1183 GetPortBitMapForCopyBits (port),
1184 &src_r, &src_r, &dest_r);
1185 UnlockPortBits (port);
1187 #else /* not TARGET_API_MAC_CARBON */
1188 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1189 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r);
1190 #endif /* not TARGET_API_MAC_CARBON */
1191 UnlockPixels (GetGWorldPixMap (mask));
1192 UnlockPixels (GetGWorldPixMap (src));
1193 mac_end_clip (GC_CLIP_REGION (gc));
1195 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1199 /* Mac replacement for XCopyArea: used only for scrolling. */
1201 static void
1202 mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y)
1203 struct frame *f;
1204 GC gc;
1205 int src_x, src_y;
1206 unsigned int width, height;
1207 int dest_x, dest_y;
1209 #if TARGET_API_MAC_CARBON
1210 Rect src_r;
1211 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
1213 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1214 ScrollWindowRect (FRAME_MAC_WINDOW (f),
1215 &src_r, dest_x - src_x, dest_y - src_y,
1216 kScrollWindowNoOptions, dummy);
1217 DisposeRgn (dummy);
1218 #else /* not TARGET_API_MAC_CARBON */
1219 Rect src_r, dest_r;
1220 WindowPtr w = FRAME_MAC_WINDOW (f);
1222 SetPort (w);
1224 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1225 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1227 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1228 color mapping in CopyBits. Otherwise, it will be slow. */
1229 ForeColor (blackColor);
1230 BackColor (whiteColor);
1231 mac_begin_clip (GC_CLIP_REGION (gc));
1232 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
1233 mac_end_clip (GC_CLIP_REGION (gc));
1235 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f)));
1236 #endif /* not TARGET_API_MAC_CARBON */
1240 /* Mac replacement for XChangeGC. */
1242 static void
1243 XChangeGC (display, gc, mask, xgcv)
1244 Display *display;
1245 GC gc;
1246 unsigned long mask;
1247 XGCValues *xgcv;
1249 if (mask & GCForeground)
1250 XSetForeground (display, gc, xgcv->foreground);
1251 if (mask & GCBackground)
1252 XSetBackground (display, gc, xgcv->background);
1253 if (mask & GCFont)
1254 XSetFont (display, gc, xgcv->font);
1258 /* Mac replacement for XCreateGC. */
1261 XCreateGC (display, window, mask, xgcv)
1262 Display *display;
1263 Window window;
1264 unsigned long mask;
1265 XGCValues *xgcv;
1267 GC gc = xmalloc (sizeof (*gc));
1269 if (gc)
1271 bzero (gc, sizeof (*gc));
1272 XChangeGC (display, gc, mask, xgcv);
1275 return gc;
1279 /* Used in xfaces.c. */
1281 void
1282 XFreeGC (display, gc)
1283 Display *display;
1284 GC gc;
1286 if (gc->clip_region)
1287 DisposeRgn (gc->clip_region);
1288 xfree (gc);
1292 /* Mac replacement for XGetGCValues. */
1294 static void
1295 XGetGCValues (display, gc, mask, xgcv)
1296 Display *display;
1297 GC gc;
1298 unsigned long mask;
1299 XGCValues *xgcv;
1301 if (mask & GCForeground)
1302 xgcv->foreground = gc->xgcv.foreground;
1303 if (mask & GCBackground)
1304 xgcv->background = gc->xgcv.background;
1305 if (mask & GCFont)
1306 xgcv->font = gc->xgcv.font;
1310 /* Mac replacement for XSetForeground. */
1312 void
1313 XSetForeground (display, gc, color)
1314 Display *display;
1315 GC gc;
1316 unsigned long color;
1318 if (gc->xgcv.foreground != color)
1320 gc->xgcv.foreground = color;
1321 gc->fore_color.red = RED16_FROM_ULONG (color);
1322 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1323 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1328 /* Mac replacement for XSetBackground. */
1330 void
1331 XSetBackground (display, gc, color)
1332 Display *display;
1333 GC gc;
1334 unsigned long color;
1336 if (gc->xgcv.background != color)
1338 gc->xgcv.background = color;
1339 gc->back_color.red = RED16_FROM_ULONG (color);
1340 gc->back_color.green = GREEN16_FROM_ULONG (color);
1341 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1346 /* Mac replacement for XSetFont. */
1348 static void
1349 XSetFont (display, gc, font)
1350 Display *display;
1351 GC gc;
1352 XFontStruct *font;
1354 gc->xgcv.font = font;
1358 /* Mac replacement for XSetClipRectangles. */
1360 static void
1361 mac_set_clip_rectangles (display, gc, rectangles, n)
1362 Display *display;
1363 GC gc;
1364 Rect *rectangles;
1365 int n;
1367 int i;
1369 if (n < 0 || n > MAX_CLIP_RECTS)
1370 abort ();
1371 if (n == 0)
1373 if (gc->clip_region)
1375 DisposeRgn (gc->clip_region);
1376 gc->clip_region = NULL;
1379 else
1381 if (gc->clip_region == NULL)
1382 gc->clip_region = NewRgn ();
1383 RectRgn (gc->clip_region, rectangles);
1384 if (n > 1)
1386 RgnHandle region = NewRgn ();
1388 for (i = 1; i < n; i++)
1390 RectRgn (region, rectangles + i);
1391 UnionRgn (gc->clip_region, region, gc->clip_region);
1393 DisposeRgn (region);
1396 #if defined (MAC_OSX) && USE_ATSUI
1397 gc->n_clip_rects = n;
1399 for (i = 0; i < n; i++)
1401 Rect *rect = rectangles + i;
1403 gc->clip_rects[i] = CGRectMake (rect->left, rect->top,
1404 rect->right - rect->left,
1405 rect->bottom - rect->top);
1407 #endif
1411 /* Mac replacement for XSetClipMask. */
1413 static INLINE void
1414 mac_reset_clip_rectangles (display, gc)
1415 Display *display;
1416 GC gc;
1418 mac_set_clip_rectangles (display, gc, NULL, 0);
1422 /* Mac replacement for XSetWindowBackground. */
1424 void
1425 XSetWindowBackground (display, w, color)
1426 Display *display;
1427 WindowPtr w;
1428 unsigned long color;
1430 #if !TARGET_API_MAC_CARBON
1431 AuxWinHandle aw_handle;
1432 CTabHandle ctab_handle;
1433 ColorSpecPtr ct_table;
1434 short ct_size;
1435 #endif
1436 RGBColor bg_color;
1438 bg_color.red = RED16_FROM_ULONG (color);
1439 bg_color.green = GREEN16_FROM_ULONG (color);
1440 bg_color.blue = BLUE16_FROM_ULONG (color);
1442 #if TARGET_API_MAC_CARBON
1443 SetWindowContentColor (w, &bg_color);
1444 #else
1445 if (GetAuxWin (w, &aw_handle))
1447 ctab_handle = (*aw_handle)->awCTable;
1448 HandToHand ((Handle *) &ctab_handle);
1449 ct_table = (*ctab_handle)->ctTable;
1450 ct_size = (*ctab_handle)->ctSize;
1451 while (ct_size > -1)
1453 if (ct_table->value == 0)
1455 ct_table->rgb = bg_color;
1456 CTabChanged (ctab_handle);
1457 SetWinColor (w, (WCTabHandle) ctab_handle);
1459 ct_size--;
1462 #endif
1465 /* x_sync is a no-op on Mac. */
1466 void
1467 x_sync (f)
1468 void *f;
1473 /* Flush display of frame F, or of all frames if F is null. */
1475 static void
1476 x_flush (f)
1477 struct frame *f;
1479 #if TARGET_API_MAC_CARBON
1480 BLOCK_INPUT;
1481 if (f)
1482 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1483 else
1484 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1485 UNBLOCK_INPUT;
1486 #endif
1490 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1491 Calls to XFlush should be unnecessary because the X output buffer
1492 is flushed automatically as needed by calls to XPending,
1493 XNextEvent, or XWindowEvent according to the XFlush man page.
1494 XTread_socket calls XPending. Removing XFlush improves
1495 performance. */
1497 #define XFlush(DISPLAY) (void) 0
1500 /* Return the struct mac_display_info corresponding to DPY. There's
1501 only one. */
1503 struct mac_display_info *
1504 mac_display_info_for_display (dpy)
1505 Display *dpy;
1507 return &one_mac_display_info;
1512 /***********************************************************************
1513 Starting and ending an update
1514 ***********************************************************************/
1516 /* Start an update of frame F. This function is installed as a hook
1517 for update_begin, i.e. it is called when update_begin is called.
1518 This function is called prior to calls to x_update_window_begin for
1519 each window being updated. */
1521 static void
1522 x_update_begin (f)
1523 struct frame *f;
1525 #if TARGET_API_MAC_CARBON
1526 /* During update of a frame, availability of input events is
1527 periodically checked with ReceiveNextEvent if
1528 redisplay-dont-pause is nil. That normally flushes window buffer
1529 changes for every check, and thus screen update looks waving even
1530 if no input is available. So we disable screen updates during
1531 update of a frame. */
1532 BLOCK_INPUT;
1533 DisableScreenUpdates ();
1534 UNBLOCK_INPUT;
1535 #endif
1539 /* Start update of window W. Set the global variable updated_window
1540 to the window being updated and set output_cursor to the cursor
1541 position of W. */
1543 static void
1544 x_update_window_begin (w)
1545 struct window *w;
1547 struct frame *f = XFRAME (WINDOW_FRAME (w));
1548 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1550 updated_window = w;
1551 set_output_cursor (&w->cursor);
1553 BLOCK_INPUT;
1555 if (f == display_info->mouse_face_mouse_frame)
1557 /* Don't do highlighting for mouse motion during the update. */
1558 display_info->mouse_face_defer = 1;
1560 /* If F needs to be redrawn, simply forget about any prior mouse
1561 highlighting. */
1562 if (FRAME_GARBAGED_P (f))
1563 display_info->mouse_face_window = Qnil;
1565 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1566 their mouse_face_p flag set, which means that they are always
1567 unequal to rows in a desired matrix which never have that
1568 flag set. So, rows containing mouse-face glyphs are never
1569 scrolled, and we don't have to switch the mouse highlight off
1570 here to prevent it from being scrolled. */
1572 /* Can we tell that this update does not affect the window
1573 where the mouse highlight is? If so, no need to turn off.
1574 Likewise, don't do anything if the frame is garbaged;
1575 in that case, the frame's current matrix that we would use
1576 is all wrong, and we will redisplay that line anyway. */
1577 if (!NILP (display_info->mouse_face_window)
1578 && w == XWINDOW (display_info->mouse_face_window))
1580 int i;
1582 for (i = 0; i < w->desired_matrix->nrows; ++i)
1583 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1584 break;
1586 if (i < w->desired_matrix->nrows)
1587 clear_mouse_face (display_info);
1589 #endif /* 0 */
1592 UNBLOCK_INPUT;
1596 /* Draw a vertical window border from (x,y0) to (x,y1) */
1598 static void
1599 mac_draw_vertical_window_border (w, x, y0, y1)
1600 struct window *w;
1601 int x, y0, y1;
1603 struct frame *f = XFRAME (WINDOW_FRAME (w));
1604 struct face *face;
1606 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1607 if (face)
1608 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1609 face->foreground);
1611 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1);
1614 /* End update of window W (which is equal to updated_window).
1616 Draw vertical borders between horizontally adjacent windows, and
1617 display W's cursor if CURSOR_ON_P is non-zero.
1619 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1620 glyphs in mouse-face were overwritten. In that case we have to
1621 make sure that the mouse-highlight is properly redrawn.
1623 W may be a menu bar pseudo-window in case we don't have X toolkit
1624 support. Such windows don't have a cursor, so don't display it
1625 here. */
1627 static void
1628 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1629 struct window *w;
1630 int cursor_on_p, mouse_face_overwritten_p;
1632 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1634 if (!w->pseudo_window_p)
1636 BLOCK_INPUT;
1638 if (cursor_on_p)
1639 display_and_set_cursor (w, 1, output_cursor.hpos,
1640 output_cursor.vpos,
1641 output_cursor.x, output_cursor.y);
1643 if (draw_window_fringes (w, 1))
1644 x_draw_vertical_border (w);
1646 UNBLOCK_INPUT;
1649 /* If a row with mouse-face was overwritten, arrange for
1650 XTframe_up_to_date to redisplay the mouse highlight. */
1651 if (mouse_face_overwritten_p)
1653 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1654 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1655 dpyinfo->mouse_face_window = Qnil;
1658 updated_window = NULL;
1662 /* End update of frame F. This function is installed as a hook in
1663 update_end. */
1665 static void
1666 x_update_end (f)
1667 struct frame *f;
1669 /* Mouse highlight may be displayed again. */
1670 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1672 BLOCK_INPUT;
1673 #if TARGET_API_MAC_CARBON
1674 EnableScreenUpdates ();
1675 #endif
1676 XFlush (FRAME_MAC_DISPLAY (f));
1677 UNBLOCK_INPUT;
1681 /* This function is called from various places in xdisp.c whenever a
1682 complete update has been performed. The global variable
1683 updated_window is not available here. */
1685 static void
1686 XTframe_up_to_date (f)
1687 struct frame *f;
1689 if (FRAME_MAC_P (f))
1691 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1693 if (dpyinfo->mouse_face_deferred_gc
1694 || f == dpyinfo->mouse_face_mouse_frame)
1696 BLOCK_INPUT;
1697 if (dpyinfo->mouse_face_mouse_frame)
1698 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1699 dpyinfo->mouse_face_mouse_x,
1700 dpyinfo->mouse_face_mouse_y);
1701 dpyinfo->mouse_face_deferred_gc = 0;
1702 UNBLOCK_INPUT;
1708 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1709 arrow bitmaps, or clear the fringes if no bitmaps are required
1710 before DESIRED_ROW is made current. The window being updated is
1711 found in updated_window. This function is called from
1712 update_window_line only if it is known that there are differences
1713 between bitmaps to be drawn between current row and DESIRED_ROW. */
1715 static void
1716 x_after_update_window_line (desired_row)
1717 struct glyph_row *desired_row;
1719 struct window *w = updated_window;
1720 struct frame *f;
1721 int width, height;
1723 xassert (w);
1725 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1726 desired_row->redraw_fringe_bitmaps_p = 1;
1728 /* When a window has disappeared, make sure that no rest of
1729 full-width rows stays visible in the internal border. Could
1730 check here if updated_window is the leftmost/rightmost window,
1731 but I guess it's not worth doing since vertically split windows
1732 are almost never used, internal border is rarely set, and the
1733 overhead is very small. */
1734 if (windows_or_buffers_changed
1735 && desired_row->full_width_p
1736 && (f = XFRAME (w->frame),
1737 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1738 width != 0)
1739 && (height = desired_row->visible_height,
1740 height > 0))
1742 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1744 /* Internal border is drawn below the tool bar. */
1745 if (WINDOWP (f->tool_bar_window)
1746 && w == XWINDOW (f->tool_bar_window))
1747 y -= width;
1749 BLOCK_INPUT;
1750 mac_clear_area (f, 0, y, width, height);
1751 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1752 UNBLOCK_INPUT;
1757 /* Draw the bitmap WHICH in one of the left or right fringes of
1758 window W. ROW is the glyph row for which to display the bitmap; it
1759 determines the vertical position at which the bitmap has to be
1760 drawn. */
1762 static void
1763 x_draw_fringe_bitmap (w, row, p)
1764 struct window *w;
1765 struct glyph_row *row;
1766 struct draw_fringe_bitmap_params *p;
1768 struct frame *f = XFRAME (WINDOW_FRAME (w));
1769 Display *display = FRAME_MAC_DISPLAY (f);
1770 struct face *face = p->face;
1771 int rowY;
1773 /* Must clip because of partially visible lines. */
1774 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1775 if (p->y < rowY)
1777 /* Adjust position of "bottom aligned" bitmap on partially
1778 visible last row. */
1779 int oldY = row->y;
1780 int oldVH = row->visible_height;
1781 row->visible_height = p->h;
1782 row->y -= rowY - p->y;
1783 x_clip_to_row (w, row, -1, face->gc);
1784 row->y = oldY;
1785 row->visible_height = oldVH;
1787 else
1788 x_clip_to_row (w, row, -1, face->gc);
1790 if (p->bx >= 0 && !p->overlay_p)
1792 #if 0 /* MAC_TODO: stipple */
1793 /* In case the same realized face is used for fringes and
1794 for something displayed in the text (e.g. face `region' on
1795 mono-displays, the fill style may have been changed to
1796 FillSolid in x_draw_glyph_string_background. */
1797 if (face->stipple)
1798 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1799 else
1800 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1801 #endif
1803 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
1805 #if 0 /* MAC_TODO: stipple */
1806 if (!face->stipple)
1807 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1808 #endif
1811 if (p->which)
1813 unsigned short *bits = p->bits + p->dh;
1814 XGCValues gcv;
1816 XGetGCValues (display, face->gc, GCForeground, &gcv);
1817 XSetForeground (display, face->gc,
1818 (p->cursor_p
1819 ? (p->overlay_p ? face->background
1820 : f->output_data.mac->cursor_pixel)
1821 : face->foreground));
1822 mac_draw_bitmap (f, face->gc, p->x, p->y,
1823 p->wd, p->h, bits, p->overlay_p);
1824 XSetForeground (display, face->gc, gcv.foreground);
1827 mac_reset_clip_rectangles (display, face->gc);
1832 /* This is called when starting Emacs and when restarting after
1833 suspend. When starting Emacs, no window is mapped. And nothing
1834 must be done to Emacs's own window if it is suspended (though that
1835 rarely happens). */
1837 static void
1838 XTset_terminal_modes ()
1842 /* This is called when exiting or suspending Emacs. Exiting will make
1843 the windows go away, and suspending requires no action. */
1845 static void
1846 XTreset_terminal_modes ()
1852 /***********************************************************************
1853 Display Iterator
1854 ***********************************************************************/
1856 /* Function prototypes of this page. */
1858 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1859 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1862 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1863 is not contained in the font. */
1865 static INLINE XCharStruct *
1866 x_per_char_metric (font, char2b)
1867 XFontStruct *font;
1868 XChar2b *char2b;
1870 /* The result metric information. */
1871 XCharStruct *pcm = NULL;
1873 xassert (font && char2b);
1875 #if USE_ATSUI
1876 if (font->mac_style)
1878 XCharStructRow **row = font->bounds.rows + char2b->byte1;
1880 if (*row == NULL)
1882 *row = xmalloc (sizeof (XCharStructRow));
1883 if (*row)
1884 bzero (*row, sizeof (XCharStructRow));
1886 if (*row)
1888 pcm = (*row)->per_char + char2b->byte2;
1889 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row, char2b->byte2))
1891 BLOCK_INPUT;
1892 mac_query_char_extents (font->mac_style,
1893 (char2b->byte1 << 8) + char2b->byte2,
1894 NULL, NULL, pcm, NULL);
1895 UNBLOCK_INPUT;
1896 XCHARSTRUCTROW_SET_CHAR_VALID (*row, char2b->byte2);
1900 else
1902 #endif
1903 if (font->bounds.per_char != NULL)
1905 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1907 /* min_char_or_byte2 specifies the linear character index
1908 corresponding to the first element of the per_char array,
1909 max_char_or_byte2 is the index of the last character. A
1910 character with non-zero CHAR2B->byte1 is not in the font.
1911 A character with byte2 less than min_char_or_byte2 or
1912 greater max_char_or_byte2 is not in the font. */
1913 if (char2b->byte1 == 0
1914 && char2b->byte2 >= font->min_char_or_byte2
1915 && char2b->byte2 <= font->max_char_or_byte2)
1916 pcm = font->bounds.per_char
1917 + (char2b->byte2 - font->min_char_or_byte2);
1919 else
1921 /* If either min_byte1 or max_byte1 are nonzero, both
1922 min_char_or_byte2 and max_char_or_byte2 are less than
1923 256, and the 2-byte character index values corresponding
1924 to the per_char array element N (counting from 0) are:
1926 byte1 = N/D + min_byte1
1927 byte2 = N\D + min_char_or_byte2
1929 where:
1931 D = max_char_or_byte2 - min_char_or_byte2 + 1
1932 / = integer division
1933 \ = integer modulus */
1934 if (char2b->byte1 >= font->min_byte1
1935 && char2b->byte1 <= font->max_byte1
1936 && char2b->byte2 >= font->min_char_or_byte2
1937 && char2b->byte2 <= font->max_char_or_byte2)
1939 pcm = (font->bounds.per_char
1940 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1941 * (char2b->byte1 - font->min_byte1))
1942 + (char2b->byte2 - font->min_char_or_byte2));
1946 else
1948 /* If the per_char pointer is null, all glyphs between the first
1949 and last character indexes inclusive have the same
1950 information, as given by both min_bounds and max_bounds. */
1951 if (char2b->byte2 >= font->min_char_or_byte2
1952 && char2b->byte2 <= font->max_char_or_byte2)
1953 pcm = &font->max_bounds;
1955 #if USE_ATSUI
1957 #endif
1959 return ((pcm == NULL
1960 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1961 ? NULL : pcm);
1964 /* RIF:
1967 static XCharStruct *
1968 mac_per_char_metric (font, char2b, font_type)
1969 XFontStruct *font;
1970 XChar2b *char2b;
1971 int font_type;
1973 return x_per_char_metric (font, char2b);
1976 /* RIF:
1977 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1978 the two-byte form of C. Encoding is returned in *CHAR2B. */
1980 static int
1981 mac_encode_char (c, char2b, font_info, two_byte_p)
1982 int c;
1983 XChar2b *char2b;
1984 struct font_info *font_info;
1985 int *two_byte_p;
1987 int charset = CHAR_CHARSET (c);
1988 XFontStruct *font = font_info->font;
1990 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1991 This may be either a program in a special encoder language or a
1992 fixed encoding. */
1993 if (font_info->font_encoder)
1995 /* It's a program. */
1996 struct ccl_program *ccl = font_info->font_encoder;
1998 check_ccl_update (ccl);
1999 if (CHARSET_DIMENSION (charset) == 1)
2001 ccl->reg[0] = charset;
2002 ccl->reg[1] = char2b->byte2;
2003 ccl->reg[2] = -1;
2005 else
2007 ccl->reg[0] = charset;
2008 ccl->reg[1] = char2b->byte1;
2009 ccl->reg[2] = char2b->byte2;
2012 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
2014 /* We assume that MSBs are appropriately set/reset by CCL
2015 program. */
2016 if (font->max_byte1 == 0) /* 1-byte font */
2017 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
2018 else
2019 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
2021 else if (font_info->encoding[charset])
2023 /* Fixed encoding scheme. See fontset.h for the meaning of the
2024 encoding numbers. */
2025 int enc = font_info->encoding[charset];
2027 if ((enc == 1 || enc == 2)
2028 && CHARSET_DIMENSION (charset) == 2)
2029 char2b->byte1 |= 0x80;
2031 if (enc == 1 || enc == 3)
2032 char2b->byte2 |= 0x80;
2034 if (enc == 4)
2036 int sjis1, sjis2;
2038 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
2039 char2b->byte1 = sjis1;
2040 char2b->byte2 = sjis2;
2044 if (two_byte_p)
2045 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
2047 return FONT_TYPE_UNKNOWN;
2052 /***********************************************************************
2053 Glyph display
2054 ***********************************************************************/
2058 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2059 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2060 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2061 int));
2062 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2063 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2064 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2065 static void x_draw_glyph_string P_ ((struct glyph_string *));
2066 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2067 static void x_set_cursor_gc P_ ((struct glyph_string *));
2068 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2069 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2070 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2071 unsigned long *, double, int));*/
2072 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2073 double, int, unsigned long));
2074 static void x_setup_relief_colors P_ ((struct glyph_string *));
2075 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2076 static void x_draw_image_relief P_ ((struct glyph_string *));
2077 static void x_draw_image_foreground P_ ((struct glyph_string *));
2078 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2079 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2080 int, int, int));
2081 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2082 int, int, int, int, int, int,
2083 Rect *));
2084 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2085 int, int, int, Rect *));
2087 #if GLYPH_DEBUG
2088 static void x_check_font P_ ((struct frame *, XFontStruct *));
2089 #endif
2092 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2093 face. */
2095 static void
2096 x_set_cursor_gc (s)
2097 struct glyph_string *s;
2099 if (s->font == FRAME_FONT (s->f)
2100 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2101 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2102 && !s->cmp)
2103 s->gc = s->f->output_data.mac->cursor_gc;
2104 else
2106 /* Cursor on non-default face: must merge. */
2107 XGCValues xgcv;
2108 unsigned long mask;
2110 xgcv.background = s->f->output_data.mac->cursor_pixel;
2111 xgcv.foreground = s->face->background;
2113 /* If the glyph would be invisible, try a different foreground. */
2114 if (xgcv.foreground == xgcv.background)
2115 xgcv.foreground = s->face->foreground;
2116 if (xgcv.foreground == xgcv.background)
2117 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
2118 if (xgcv.foreground == xgcv.background)
2119 xgcv.foreground = s->face->foreground;
2121 /* Make sure the cursor is distinct from text in this face. */
2122 if (xgcv.background == s->face->background
2123 && xgcv.foreground == s->face->foreground)
2125 xgcv.background = s->face->foreground;
2126 xgcv.foreground = s->face->background;
2129 IF_DEBUG (x_check_font (s->f, s->font));
2130 xgcv.font = s->font;
2131 mask = GCForeground | GCBackground | GCFont;
2133 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2134 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2135 mask, &xgcv);
2136 else
2137 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2138 = XCreateGC (s->display, s->window, mask, &xgcv);
2140 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2145 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2147 static void
2148 x_set_mouse_face_gc (s)
2149 struct glyph_string *s;
2151 int face_id;
2152 struct face *face;
2154 /* What face has to be used last for the mouse face? */
2155 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2156 face = FACE_FROM_ID (s->f, face_id);
2157 if (face == NULL)
2158 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2160 if (s->first_glyph->type == CHAR_GLYPH)
2161 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2162 else
2163 face_id = FACE_FOR_CHAR (s->f, face, 0);
2164 s->face = FACE_FROM_ID (s->f, face_id);
2165 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2167 /* If font in this face is same as S->font, use it. */
2168 if (s->font == s->face->font)
2169 s->gc = s->face->gc;
2170 else
2172 /* Otherwise construct scratch_cursor_gc with values from FACE
2173 but font FONT. */
2174 XGCValues xgcv;
2175 unsigned long mask;
2177 xgcv.background = s->face->background;
2178 xgcv.foreground = s->face->foreground;
2179 IF_DEBUG (x_check_font (s->f, s->font));
2180 xgcv.font = s->font;
2181 mask = GCForeground | GCBackground | GCFont;
2183 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2184 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2185 mask, &xgcv);
2186 else
2187 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
2188 = XCreateGC (s->display, s->window, mask, &xgcv);
2190 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2193 xassert (s->gc != 0);
2197 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2198 Faces to use in the mode line have already been computed when the
2199 matrix was built, so there isn't much to do, here. */
2201 static INLINE void
2202 x_set_mode_line_face_gc (s)
2203 struct glyph_string *s;
2205 s->gc = s->face->gc;
2209 /* Set S->gc of glyph string S for drawing that glyph string. Set
2210 S->stippled_p to a non-zero value if the face of S has a stipple
2211 pattern. */
2213 static INLINE void
2214 x_set_glyph_string_gc (s)
2215 struct glyph_string *s;
2217 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2219 if (s->hl == DRAW_NORMAL_TEXT)
2221 s->gc = s->face->gc;
2222 s->stippled_p = s->face->stipple != 0;
2224 else if (s->hl == DRAW_INVERSE_VIDEO)
2226 x_set_mode_line_face_gc (s);
2227 s->stippled_p = s->face->stipple != 0;
2229 else if (s->hl == DRAW_CURSOR)
2231 x_set_cursor_gc (s);
2232 s->stippled_p = 0;
2234 else if (s->hl == DRAW_MOUSE_FACE)
2236 x_set_mouse_face_gc (s);
2237 s->stippled_p = s->face->stipple != 0;
2239 else if (s->hl == DRAW_IMAGE_RAISED
2240 || s->hl == DRAW_IMAGE_SUNKEN)
2242 s->gc = s->face->gc;
2243 s->stippled_p = s->face->stipple != 0;
2245 else
2247 s->gc = s->face->gc;
2248 s->stippled_p = s->face->stipple != 0;
2251 /* GC must have been set. */
2252 xassert (s->gc != 0);
2256 /* Set clipping for output of glyph string S. S may be part of a mode
2257 line or menu if we don't have X toolkit support. */
2259 static INLINE void
2260 x_set_glyph_string_clipping (s)
2261 struct glyph_string *s;
2263 Rect rects[MAX_CLIP_RECTS];
2264 int n;
2266 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS);
2267 mac_set_clip_rectangles (s->display, s->gc, rects, n);
2271 /* RIF:
2272 Compute left and right overhang of glyph string S. If S is a glyph
2273 string for a composition, assume overhangs don't exist. */
2275 static void
2276 mac_compute_glyph_string_overhangs (s)
2277 struct glyph_string *s;
2279 if (s->cmp == NULL
2280 && s->first_glyph->type == CHAR_GLYPH)
2281 if (!s->two_byte_p
2282 #if USE_ATSUI
2283 || s->font->mac_style
2284 #endif
2287 XCharStruct cs;
2289 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs);
2290 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2291 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2293 else
2295 Rect r;
2296 MacFontStruct *font = s->font;
2298 TextFont (font->mac_fontnum);
2299 TextSize (font->mac_fontsize);
2300 TextFace (font->mac_fontface);
2302 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2304 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2305 s->left_overhang = r.left < 0 ? -r.left : 0;
2310 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2312 static INLINE void
2313 x_clear_glyph_string_rect (s, x, y, w, h)
2314 struct glyph_string *s;
2315 int x, y, w, h;
2317 mac_erase_rectangle (s->f, s->gc, x, y, w, h);
2321 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2322 on Mac OS X because:
2323 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2324 into an offscreen graphics world first. So performance gain
2325 cannot be expected.)
2326 - It lowers rendering quality.
2327 - Some fonts leave garbage on cursor movement. */
2329 /* Draw the background of glyph_string S. If S->background_filled_p
2330 is non-zero don't draw it. FORCE_P non-zero means draw the
2331 background even if it wouldn't be drawn normally. This is used
2332 when a string preceding S draws into the background of S, or S
2333 contains the first component of a composition. */
2335 static void
2336 x_draw_glyph_string_background (s, force_p)
2337 struct glyph_string *s;
2338 int force_p;
2340 /* Nothing to do if background has already been drawn or if it
2341 shouldn't be drawn in the first place. */
2342 if (!s->background_filled_p)
2344 int box_line_width = max (s->face->box_line_width, 0);
2346 #if 0 /* MAC_TODO: stipple */
2347 if (s->stippled_p)
2349 /* Fill background with a stipple pattern. */
2350 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2351 XFillRectangle (s->display, s->window, s->gc, s->x,
2352 s->y + box_line_width,
2353 s->background_width,
2354 s->height - 2 * box_line_width);
2355 XSetFillStyle (s->display, s->gc, FillSolid);
2356 s->background_filled_p = 1;
2358 else
2359 #endif
2360 #if defined (MAC_OS8) && !USE_ATSUI
2361 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2362 || s->font_not_found_p
2363 || s->extends_to_end_of_line_p
2364 || force_p)
2365 #endif
2367 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2368 s->background_width,
2369 s->height - 2 * box_line_width);
2370 s->background_filled_p = 1;
2376 /* Draw the foreground of glyph string S. */
2378 static void
2379 x_draw_glyph_string_foreground (s)
2380 struct glyph_string *s;
2382 int i, x;
2384 /* If first glyph of S has a left box line, start drawing the text
2385 of S to the right of that box line. */
2386 if (s->face->box != FACE_NO_BOX
2387 && s->first_glyph->left_box_line_p)
2388 x = s->x + abs (s->face->box_line_width);
2389 else
2390 x = s->x;
2392 /* Draw characters of S as rectangles if S's font could not be
2393 loaded. */
2394 if (s->font_not_found_p)
2396 for (i = 0; i < s->nchars; ++i)
2398 struct glyph *g = s->first_glyph + i;
2399 mac_draw_rectangle (s->f, s->gc, x, s->y,
2400 g->pixel_width - 1, s->height - 1);
2401 x += g->pixel_width;
2404 else
2406 char *char1b = (char *) s->char2b;
2407 int boff = s->font_info->baseline_offset;
2409 if (s->font_info->vertical_centering)
2410 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2412 /* If we can use 8-bit functions, condense S->char2b. */
2413 if (!s->two_byte_p
2414 #if USE_ATSUI
2415 && GC_FONT (s->gc)->mac_style == NULL
2416 #endif
2418 for (i = 0; i < s->nchars; ++i)
2419 char1b[i] = s->char2b[i].byte2;
2421 #if defined (MAC_OS8) && !USE_ATSUI
2422 /* Draw text with XDrawString if background has already been
2423 filled. Otherwise, use XDrawImageString. (Note that
2424 XDrawImageString is usually faster than XDrawString.) Always
2425 use XDrawImageString when drawing the cursor so that there is
2426 no chance that characters under a box cursor are invisible. */
2427 if (s->for_overlaps
2428 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2429 #endif
2431 /* Draw characters with 16-bit or 8-bit functions. */
2432 if (s->two_byte_p
2433 #if USE_ATSUI
2434 || GC_FONT (s->gc)->mac_style
2435 #endif
2437 #if USE_CG_TEXT_DRAWING
2438 if (!s->two_byte_p
2439 && mac_draw_string_cg (s->f, s->gc, x, s->ybase - boff,
2440 s->char2b, s->nchars))
2442 else
2443 #endif
2444 mac_draw_string_16 (s->f, s->gc, x, s->ybase - boff,
2445 s->char2b, s->nchars);
2446 else
2447 mac_draw_string (s->f, s->gc, x, s->ybase - boff,
2448 char1b, s->nchars);
2450 #if defined (MAC_OS8) && !USE_ATSUI
2451 else
2453 if (s->two_byte_p)
2454 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff,
2455 s->char2b, s->nchars);
2456 else
2457 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff,
2458 char1b, s->nchars);
2460 #endif
2464 /* Draw the foreground of composite glyph string S. */
2466 static void
2467 x_draw_composite_glyph_string_foreground (s)
2468 struct glyph_string *s;
2470 int i, x;
2472 /* If first glyph of S has a left box line, start drawing the text
2473 of S to the right of that box line. */
2474 if (s->face->box != FACE_NO_BOX
2475 && s->first_glyph->left_box_line_p)
2476 x = s->x + abs (s->face->box_line_width);
2477 else
2478 x = s->x;
2480 /* S is a glyph string for a composition. S->gidx is the index of
2481 the first character drawn for glyphs of this composition.
2482 S->gidx == 0 means we are drawing the very first character of
2483 this composition. */
2485 /* Draw a rectangle for the composition if the font for the very
2486 first character of the composition could not be loaded. */
2487 if (s->font_not_found_p)
2489 if (s->gidx == 0)
2490 mac_draw_rectangle (s->f, s->gc, x, s->y,
2491 s->width - 1, s->height - 1);
2493 else
2495 for (i = 0; i < s->nchars; i++, ++s->gidx)
2496 mac_draw_string_16 (s->f, s->gc,
2497 x + s->cmp->offsets[s->gidx * 2],
2498 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2499 s->char2b + i, 1);
2504 #ifdef USE_X_TOOLKIT
2506 static struct frame *x_frame_of_widget P_ ((Widget));
2509 /* Return the frame on which widget WIDGET is used.. Abort if frame
2510 cannot be determined. */
2512 static struct frame *
2513 x_frame_of_widget (widget)
2514 Widget widget;
2516 struct x_display_info *dpyinfo;
2517 Lisp_Object tail;
2518 struct frame *f;
2520 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2522 /* Find the top-level shell of the widget. Note that this function
2523 can be called when the widget is not yet realized, so XtWindow
2524 (widget) == 0. That's the reason we can't simply use
2525 x_any_window_to_frame. */
2526 while (!XtIsTopLevelShell (widget))
2527 widget = XtParent (widget);
2529 /* Look for a frame with that top-level widget. Allocate the color
2530 on that frame to get the right gamma correction value. */
2531 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2532 if (GC_FRAMEP (XCAR (tail))
2533 && (f = XFRAME (XCAR (tail)),
2534 (f->output_data.nothing != 1
2535 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2536 && f->output_data.x->widget == widget)
2537 return f;
2539 abort ();
2543 /* Allocate the color COLOR->pixel on the screen and display of
2544 widget WIDGET in colormap CMAP. If an exact match cannot be
2545 allocated, try the nearest color available. Value is non-zero
2546 if successful. This is called from lwlib. */
2549 x_alloc_nearest_color_for_widget (widget, cmap, color)
2550 Widget widget;
2551 Colormap cmap;
2552 XColor *color;
2554 struct frame *f = x_frame_of_widget (widget);
2555 return x_alloc_nearest_color (f, cmap, color);
2559 #endif /* USE_X_TOOLKIT */
2561 #if 0 /* MAC_TODO */
2563 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2564 CMAP. If an exact match can't be allocated, try the nearest color
2565 available. Value is non-zero if successful. Set *COLOR to the
2566 color allocated. */
2569 x_alloc_nearest_color (f, cmap, color)
2570 struct frame *f;
2571 Colormap cmap;
2572 XColor *color;
2574 Display *display = FRAME_X_DISPLAY (f);
2575 Screen *screen = FRAME_X_SCREEN (f);
2576 int rc;
2578 gamma_correct (f, color);
2579 rc = XAllocColor (display, cmap, color);
2580 if (rc == 0)
2582 /* If we got to this point, the colormap is full, so we're going
2583 to try to get the next closest color. The algorithm used is
2584 a least-squares matching, which is what X uses for closest
2585 color matching with StaticColor visuals. */
2586 int nearest, i;
2587 unsigned long nearest_delta = ~0;
2588 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2589 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2591 for (i = 0; i < ncells; ++i)
2592 cells[i].pixel = i;
2593 XQueryColors (display, cmap, cells, ncells);
2595 for (nearest = i = 0; i < ncells; ++i)
2597 long dred = (color->red >> 8) - (cells[i].red >> 8);
2598 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2599 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2600 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2602 if (delta < nearest_delta)
2604 nearest = i;
2605 nearest_delta = delta;
2609 color->red = cells[nearest].red;
2610 color->green = cells[nearest].green;
2611 color->blue = cells[nearest].blue;
2612 rc = XAllocColor (display, cmap, color);
2615 #ifdef DEBUG_X_COLORS
2616 if (rc)
2617 register_color (color->pixel);
2618 #endif /* DEBUG_X_COLORS */
2620 return rc;
2624 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2625 It's necessary to do this instead of just using PIXEL directly to
2626 get color reference counts right. */
2628 unsigned long
2629 x_copy_color (f, pixel)
2630 struct frame *f;
2631 unsigned long pixel;
2633 XColor color;
2635 color.pixel = pixel;
2636 BLOCK_INPUT;
2637 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2638 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2639 UNBLOCK_INPUT;
2640 #ifdef DEBUG_X_COLORS
2641 register_color (pixel);
2642 #endif
2643 return color.pixel;
2647 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2648 It's necessary to do this instead of just using PIXEL directly to
2649 get color reference counts right. */
2651 unsigned long
2652 x_copy_dpy_color (dpy, cmap, pixel)
2653 Display *dpy;
2654 Colormap cmap;
2655 unsigned long pixel;
2657 XColor color;
2659 color.pixel = pixel;
2660 BLOCK_INPUT;
2661 XQueryColor (dpy, cmap, &color);
2662 XAllocColor (dpy, cmap, &color);
2663 UNBLOCK_INPUT;
2664 #ifdef DEBUG_X_COLORS
2665 register_color (pixel);
2666 #endif
2667 return color.pixel;
2670 #endif /* MAC_TODO */
2673 /* Brightness beyond which a color won't have its highlight brightness
2674 boosted.
2676 Nominally, highlight colors for `3d' faces are calculated by
2677 brightening an object's color by a constant scale factor, but this
2678 doesn't yield good results for dark colors, so for colors who's
2679 brightness is less than this value (on a scale of 0-255) have to
2680 use an additional additive factor.
2682 The value here is set so that the default menu-bar/mode-line color
2683 (grey75) will not have its highlights changed at all. */
2684 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2687 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2688 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2689 If this produces the same color as COLOR, try a color where all RGB
2690 values have DELTA added. Return the allocated color in *COLOR.
2691 DISPLAY is the X display, CMAP is the colormap to operate on.
2692 Value is non-zero if successful. */
2694 static int
2695 mac_alloc_lighter_color (f, color, factor, delta)
2696 struct frame *f;
2697 unsigned long *color;
2698 double factor;
2699 int delta;
2701 unsigned long new;
2702 long bright;
2704 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2705 delta /= 256;
2707 /* Change RGB values by specified FACTOR. Avoid overflow! */
2708 xassert (factor >= 0);
2709 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2710 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2711 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2713 /* Calculate brightness of COLOR. */
2714 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2715 + BLUE_FROM_ULONG (*color)) / 6;
2717 /* We only boost colors that are darker than
2718 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2719 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2720 /* Make an additive adjustment to NEW, because it's dark enough so
2721 that scaling by FACTOR alone isn't enough. */
2723 /* How far below the limit this color is (0 - 1, 1 being darker). */
2724 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2725 /* The additive adjustment. */
2726 int min_delta = delta * dimness * factor / 2;
2728 if (factor < 1)
2729 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2730 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2731 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2732 else
2733 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2734 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2735 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2738 if (new == *color)
2739 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2740 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2741 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2743 /* MAC_TODO: Map to palette and retry with delta if same? */
2744 /* MAC_TODO: Free colors (if using palette)? */
2746 if (new == *color)
2747 return 0;
2749 *color = new;
2751 return 1;
2755 /* Set up the foreground color for drawing relief lines of glyph
2756 string S. RELIEF is a pointer to a struct relief containing the GC
2757 with which lines will be drawn. Use a color that is FACTOR or
2758 DELTA lighter or darker than the relief's background which is found
2759 in S->f->output_data.x->relief_background. If such a color cannot
2760 be allocated, use DEFAULT_PIXEL, instead. */
2762 static void
2763 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2764 struct frame *f;
2765 struct relief *relief;
2766 double factor;
2767 int delta;
2768 unsigned long default_pixel;
2770 XGCValues xgcv;
2771 struct mac_output *di = f->output_data.mac;
2772 unsigned long mask = GCForeground;
2773 unsigned long pixel;
2774 unsigned long background = di->relief_background;
2775 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2777 /* MAC_TODO: Free colors (if using palette)? */
2779 /* Allocate new color. */
2780 xgcv.foreground = default_pixel;
2781 pixel = background;
2782 if (dpyinfo->n_planes != 1
2783 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2785 relief->allocated_p = 1;
2786 xgcv.foreground = relief->pixel = pixel;
2789 if (relief->gc == 0)
2791 #if 0 /* MAC_TODO: stipple */
2792 xgcv.stipple = dpyinfo->gray;
2793 mask |= GCStipple;
2794 #endif
2795 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2797 else
2798 XChangeGC (NULL, relief->gc, mask, &xgcv);
2802 /* Set up colors for the relief lines around glyph string S. */
2804 static void
2805 x_setup_relief_colors (s)
2806 struct glyph_string *s;
2808 struct mac_output *di = s->f->output_data.mac;
2809 unsigned long color;
2811 if (s->face->use_box_color_for_shadows_p)
2812 color = s->face->box_color;
2813 else if (s->first_glyph->type == IMAGE_GLYPH
2814 && s->img->pixmap
2815 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2816 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2817 else
2819 XGCValues xgcv;
2821 /* Get the background color of the face. */
2822 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2823 color = xgcv.background;
2826 if (di->white_relief.gc == 0
2827 || color != di->relief_background)
2829 di->relief_background = color;
2830 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2831 WHITE_PIX_DEFAULT (s->f));
2832 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2833 BLACK_PIX_DEFAULT (s->f));
2838 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2839 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2840 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2841 relief. LEFT_P non-zero means draw a relief on the left side of
2842 the rectangle. RIGHT_P non-zero means draw a relief on the right
2843 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2844 when drawing. */
2846 static void
2847 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2848 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2849 struct frame *f;
2850 int left_x, top_y, right_x, bottom_y, width;
2851 int top_p, bot_p, left_p, right_p, raised_p;
2852 Rect *clip_rect;
2854 Display *dpy = FRAME_MAC_DISPLAY (f);
2855 int i;
2856 GC gc;
2858 if (raised_p)
2859 gc = f->output_data.mac->white_relief.gc;
2860 else
2861 gc = f->output_data.mac->black_relief.gc;
2862 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
2864 /* Top. */
2865 if (top_p)
2866 for (i = 0; i < width; ++i)
2867 mac_draw_line (f, gc,
2868 left_x + i * left_p, top_y + i,
2869 right_x - i * right_p, top_y + i);
2871 /* Left. */
2872 if (left_p)
2873 for (i = 0; i < width; ++i)
2874 mac_draw_line (f, gc,
2875 left_x + i, top_y + i, left_x + i, bottom_y - i);
2877 mac_reset_clip_rectangles (dpy, gc);
2878 if (raised_p)
2879 gc = f->output_data.mac->black_relief.gc;
2880 else
2881 gc = f->output_data.mac->white_relief.gc;
2882 mac_set_clip_rectangles (dpy, gc, clip_rect, 1);
2884 /* Bottom. */
2885 if (bot_p)
2886 for (i = 0; i < width; ++i)
2887 mac_draw_line (f, gc,
2888 left_x + i * left_p, bottom_y - i,
2889 right_x - i * right_p, bottom_y - i);
2891 /* Right. */
2892 if (right_p)
2893 for (i = 0; i < width; ++i)
2894 mac_draw_line (f, gc,
2895 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2897 mac_reset_clip_rectangles (dpy, gc);
2901 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2902 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2903 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2904 left side of the rectangle. RIGHT_P non-zero means draw a line
2905 on the right side of the rectangle. CLIP_RECT is the clipping
2906 rectangle to use when drawing. */
2908 static void
2909 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2910 left_p, right_p, clip_rect)
2911 struct glyph_string *s;
2912 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2913 Rect *clip_rect;
2915 XGCValues xgcv;
2917 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2918 XSetForeground (s->display, s->gc, s->face->box_color);
2919 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1);
2921 /* Top. */
2922 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
2923 right_x - left_x + 1, width);
2925 /* Left. */
2926 if (left_p)
2927 mac_fill_rectangle (s->f, s->gc, left_x, top_y,
2928 width, bottom_y - top_y + 1);
2930 /* Bottom. */
2931 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1,
2932 right_x - left_x + 1, width);
2934 /* Right. */
2935 if (right_p)
2936 mac_fill_rectangle (s->f, s->gc, right_x - width + 1,
2937 top_y, width, bottom_y - top_y + 1);
2939 XSetForeground (s->display, s->gc, xgcv.foreground);
2940 mac_reset_clip_rectangles (s->display, s->gc);
2944 /* Draw a box around glyph string S. */
2946 static void
2947 x_draw_glyph_string_box (s)
2948 struct glyph_string *s;
2950 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2951 int left_p, right_p;
2952 struct glyph *last_glyph;
2953 Rect clip_rect;
2955 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2956 ? WINDOW_RIGHT_EDGE_X (s->w)
2957 : window_box_right (s->w, s->area));
2959 /* The glyph that may have a right box line. */
2960 last_glyph = (s->cmp || s->img
2961 ? s->first_glyph
2962 : s->first_glyph + s->nchars - 1);
2964 width = abs (s->face->box_line_width);
2965 raised_p = s->face->box == FACE_RAISED_BOX;
2966 left_x = s->x;
2967 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2968 ? last_x - 1
2969 : min (last_x, s->x + s->background_width) - 1);
2970 top_y = s->y;
2971 bottom_y = top_y + s->height - 1;
2973 left_p = (s->first_glyph->left_box_line_p
2974 || (s->hl == DRAW_MOUSE_FACE
2975 && (s->prev == NULL
2976 || s->prev->hl != s->hl)));
2977 right_p = (last_glyph->right_box_line_p
2978 || (s->hl == DRAW_MOUSE_FACE
2979 && (s->next == NULL
2980 || s->next->hl != s->hl)));
2982 get_glyph_string_clip_rect (s, &clip_rect);
2984 if (s->face->box == FACE_SIMPLE_BOX)
2985 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2986 left_p, right_p, &clip_rect);
2987 else
2989 x_setup_relief_colors (s);
2990 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2991 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2996 /* Draw foreground of image glyph string S. */
2998 static void
2999 x_draw_image_foreground (s)
3000 struct glyph_string *s;
3002 int x = s->x;
3003 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3005 /* If first glyph of S has a left box line, start drawing it to the
3006 right of that line. */
3007 if (s->face->box != FACE_NO_BOX
3008 && s->first_glyph->left_box_line_p
3009 && s->slice.x == 0)
3010 x += abs (s->face->box_line_width);
3012 /* If there is a margin around the image, adjust x- and y-position
3013 by that margin. */
3014 if (s->slice.x == 0)
3015 x += s->img->hmargin;
3016 if (s->slice.y == 0)
3017 y += s->img->vmargin;
3019 if (s->img->pixmap)
3021 x_set_glyph_string_clipping (s);
3023 if (s->img->mask)
3024 mac_copy_area_with_mask (s->img->pixmap, s->img->mask,
3025 s->f, s->gc, s->slice.x, s->slice.y,
3026 s->slice.width, s->slice.height, x, y);
3027 else
3029 mac_copy_area (s->img->pixmap,
3030 s->f, s->gc, s->slice.x, s->slice.y,
3031 s->slice.width, s->slice.height, x, y);
3033 /* When the image has a mask, we can expect that at
3034 least part of a mouse highlight or a block cursor will
3035 be visible. If the image doesn't have a mask, make
3036 a block cursor visible by drawing a rectangle around
3037 the image. I believe it's looking better if we do
3038 nothing here for mouse-face. */
3039 if (s->hl == DRAW_CURSOR)
3041 int r = s->img->relief;
3042 if (r < 0) r = -r;
3043 mac_draw_rectangle (s->f, s->gc, x - r, y - r,
3044 s->slice.width + r*2 - 1,
3045 s->slice.height + r*2 - 1);
3049 else
3050 /* Draw a rectangle if image could not be loaded. */
3051 mac_draw_rectangle (s->f, s->gc, x, y,
3052 s->slice.width - 1, s->slice.height - 1);
3056 /* Draw a relief around the image glyph string S. */
3058 static void
3059 x_draw_image_relief (s)
3060 struct glyph_string *s;
3062 int x0, y0, x1, y1, thick, raised_p;
3063 Rect r;
3064 int x = s->x;
3065 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
3067 /* If first glyph of S has a left box line, start drawing it to the
3068 right of that line. */
3069 if (s->face->box != FACE_NO_BOX
3070 && s->first_glyph->left_box_line_p
3071 && s->slice.x == 0)
3072 x += abs (s->face->box_line_width);
3074 /* If there is a margin around the image, adjust x- and y-position
3075 by that margin. */
3076 if (s->slice.x == 0)
3077 x += s->img->hmargin;
3078 if (s->slice.y == 0)
3079 y += s->img->vmargin;
3081 if (s->hl == DRAW_IMAGE_SUNKEN
3082 || s->hl == DRAW_IMAGE_RAISED)
3084 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3085 raised_p = s->hl == DRAW_IMAGE_RAISED;
3087 else
3089 thick = abs (s->img->relief);
3090 raised_p = s->img->relief > 0;
3093 x0 = x - thick;
3094 y0 = y - thick;
3095 x1 = x + s->slice.width + thick - 1;
3096 y1 = y + s->slice.height + thick - 1;
3098 x_setup_relief_colors (s);
3099 get_glyph_string_clip_rect (s, &r);
3100 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
3101 s->slice.y == 0,
3102 s->slice.y + s->slice.height == s->img->height,
3103 s->slice.x == 0,
3104 s->slice.x + s->slice.width == s->img->width,
3105 &r);
3109 /* Draw part of the background of glyph string S. X, Y, W, and H
3110 give the rectangle to draw. */
3112 static void
3113 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3114 struct glyph_string *s;
3115 int x, y, w, h;
3117 #if 0 /* MAC_TODO: stipple */
3118 if (s->stippled_p)
3120 /* Fill background with a stipple pattern. */
3121 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3122 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3123 XSetFillStyle (s->display, s->gc, FillSolid);
3125 else
3126 #endif /* MAC_TODO */
3127 x_clear_glyph_string_rect (s, x, y, w, h);
3131 /* Draw image glyph string S.
3133 s->y
3134 s->x +-------------------------
3135 | s->face->box
3137 | +-------------------------
3138 | | s->img->margin
3140 | | +-------------------
3141 | | | the image
3145 static void
3146 x_draw_image_glyph_string (s)
3147 struct glyph_string *s;
3149 int x, y;
3150 int box_line_hwidth = abs (s->face->box_line_width);
3151 int box_line_vwidth = max (s->face->box_line_width, 0);
3152 int height;
3153 Pixmap pixmap = 0;
3155 height = s->height - 2 * box_line_vwidth;
3158 /* Fill background with face under the image. Do it only if row is
3159 taller than image or if image has a clip mask to reduce
3160 flickering. */
3161 s->stippled_p = s->face->stipple != 0;
3162 if (height > s->slice.height
3163 || s->img->hmargin
3164 || s->img->vmargin
3165 || s->img->mask
3166 || s->img->pixmap == 0
3167 || s->width != s->background_width)
3169 x = s->x;
3170 if (s->first_glyph->left_box_line_p
3171 && s->slice.x == 0)
3172 x += box_line_hwidth;
3174 y = s->y;
3175 if (s->slice.y == 0)
3176 y += box_line_vwidth;
3178 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3180 s->background_filled_p = 1;
3183 /* Draw the foreground. */
3184 x_draw_image_foreground (s);
3186 /* If we must draw a relief around the image, do it. */
3187 if (s->img->relief
3188 || s->hl == DRAW_IMAGE_RAISED
3189 || s->hl == DRAW_IMAGE_SUNKEN)
3190 x_draw_image_relief (s);
3194 /* Draw stretch glyph string S. */
3196 static void
3197 x_draw_stretch_glyph_string (s)
3198 struct glyph_string *s;
3200 xassert (s->first_glyph->type == STRETCH_GLYPH);
3201 s->stippled_p = s->face->stipple != 0;
3203 if (s->hl == DRAW_CURSOR
3204 && !x_stretch_cursor_p)
3206 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3207 as wide as the stretch glyph. */
3208 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
3210 /* Draw cursor. */
3211 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3213 /* Clear rest using the GC of the original non-cursor face. */
3214 if (width < s->background_width)
3216 int x = s->x + width, y = s->y;
3217 int w = s->background_width - width, h = s->height;
3218 Rect r;
3219 GC gc;
3221 if (s->row->mouse_face_p
3222 && cursor_in_mouse_face_p (s->w))
3224 x_set_mouse_face_gc (s);
3225 gc = s->gc;
3227 else
3228 gc = s->face->gc;
3230 get_glyph_string_clip_rect (s, &r);
3231 mac_set_clip_rectangles (s->display, gc, &r, 1);
3233 #if 0 /* MAC_TODO: stipple */
3234 if (s->face->stipple)
3236 /* Fill background with a stipple pattern. */
3237 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3238 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3239 XSetFillStyle (s->display, gc, FillSolid);
3241 else
3242 #endif /* MAC_TODO */
3243 mac_erase_rectangle (s->f, gc, x, y, w, h);
3246 else if (!s->background_filled_p)
3247 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3248 s->height);
3250 s->background_filled_p = 1;
3254 /* Draw glyph string S. */
3256 static void
3257 x_draw_glyph_string (s)
3258 struct glyph_string *s;
3260 int relief_drawn_p = 0;
3262 /* If S draws into the background of its successor that does not
3263 draw a cursor, draw the background of the successor first so that
3264 S can draw into it. This makes S->next use XDrawString instead
3265 of XDrawImageString. */
3266 if (s->next && s->right_overhang && !s->for_overlaps
3267 && s->next->hl != DRAW_CURSOR)
3269 xassert (s->next->img == NULL);
3270 x_set_glyph_string_gc (s->next);
3271 x_set_glyph_string_clipping (s->next);
3272 x_draw_glyph_string_background (s->next, 1);
3275 /* Set up S->gc, set clipping and draw S. */
3276 x_set_glyph_string_gc (s);
3278 /* Draw relief (if any) in advance for char/composition so that the
3279 glyph string can be drawn over it. */
3280 if (!s->for_overlaps
3281 && s->face->box != FACE_NO_BOX
3282 && (s->first_glyph->type == CHAR_GLYPH
3283 || s->first_glyph->type == COMPOSITE_GLYPH))
3286 x_set_glyph_string_clipping (s);
3287 x_draw_glyph_string_background (s, 1);
3288 x_draw_glyph_string_box (s);
3289 x_set_glyph_string_clipping (s);
3290 relief_drawn_p = 1;
3292 else
3293 x_set_glyph_string_clipping (s);
3295 switch (s->first_glyph->type)
3297 case IMAGE_GLYPH:
3298 x_draw_image_glyph_string (s);
3299 break;
3301 case STRETCH_GLYPH:
3302 x_draw_stretch_glyph_string (s);
3303 break;
3305 case CHAR_GLYPH:
3306 if (s->for_overlaps)
3307 s->background_filled_p = 1;
3308 else
3309 x_draw_glyph_string_background (s, 0);
3310 x_draw_glyph_string_foreground (s);
3311 break;
3313 case COMPOSITE_GLYPH:
3314 if (s->for_overlaps || s->gidx > 0)
3315 s->background_filled_p = 1;
3316 else
3317 x_draw_glyph_string_background (s, 1);
3318 x_draw_composite_glyph_string_foreground (s);
3319 break;
3321 default:
3322 abort ();
3325 if (!s->for_overlaps)
3327 /* Draw underline. */
3328 if (s->face->underline_p)
3330 unsigned long h = 1;
3331 unsigned long dy = s->height - h;
3333 if (s->face->underline_defaulted_p)
3334 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3335 s->width, h);
3336 else
3338 XGCValues xgcv;
3339 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3340 XSetForeground (s->display, s->gc, s->face->underline_color);
3341 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3342 s->width, h);
3343 XSetForeground (s->display, s->gc, xgcv.foreground);
3347 /* Draw overline. */
3348 if (s->face->overline_p)
3350 unsigned long dy = 0, h = 1;
3352 if (s->face->overline_color_defaulted_p)
3353 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3354 s->width, h);
3355 else
3357 XGCValues xgcv;
3358 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3359 XSetForeground (s->display, s->gc, s->face->overline_color);
3360 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3361 s->width, h);
3362 XSetForeground (s->display, s->gc, xgcv.foreground);
3366 /* Draw strike-through. */
3367 if (s->face->strike_through_p)
3369 unsigned long h = 1;
3370 unsigned long dy = (s->height - h) / 2;
3372 if (s->face->strike_through_color_defaulted_p)
3373 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3374 s->width, h);
3375 else
3377 XGCValues xgcv;
3378 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3379 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3380 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
3381 s->width, h);
3382 XSetForeground (s->display, s->gc, xgcv.foreground);
3386 /* Draw relief if not yet drawn. */
3387 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3388 x_draw_glyph_string_box (s);
3391 /* Reset clipping. */
3392 mac_reset_clip_rectangles (s->display, s->gc);
3395 /* Shift display to make room for inserted glyphs. */
3397 void
3398 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3399 struct frame *f;
3400 int x, y, width, height, shift_by;
3402 mac_scroll_area (f, f->output_data.mac->normal_gc,
3403 x, y, width, height,
3404 x + shift_by, y);
3407 /* Delete N glyphs at the nominal cursor position. Not implemented
3408 for X frames. */
3410 static void
3411 x_delete_glyphs (n)
3412 register int n;
3414 abort ();
3418 /* Clear entire frame. If updating_frame is non-null, clear that
3419 frame. Otherwise clear the selected frame. */
3421 static void
3422 x_clear_frame ()
3424 struct frame *f;
3426 if (updating_frame)
3427 f = updating_frame;
3428 else
3429 f = SELECTED_FRAME ();
3431 /* Clearing the frame will erase any cursor, so mark them all as no
3432 longer visible. */
3433 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3434 output_cursor.hpos = output_cursor.vpos = 0;
3435 output_cursor.x = -1;
3437 /* We don't set the output cursor here because there will always
3438 follow an explicit cursor_to. */
3439 BLOCK_INPUT;
3440 mac_clear_window (f);
3442 /* We have to clear the scroll bars, too. If we have changed
3443 colors or something like that, then they should be notified. */
3444 x_scroll_bar_clear (f);
3446 XFlush (FRAME_MAC_DISPLAY (f));
3447 UNBLOCK_INPUT;
3452 /* Invert the middle quarter of the frame for .15 sec. */
3454 /* We use the select system call to do the waiting, so we have to make
3455 sure it's available. If it isn't, we just won't do visual bells. */
3457 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3460 /* Subtract the `struct timeval' values X and Y, storing the result in
3461 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3463 static int
3464 timeval_subtract (result, x, y)
3465 struct timeval *result, x, y;
3467 /* Perform the carry for the later subtraction by updating y. This
3468 is safer because on some systems the tv_sec member is unsigned. */
3469 if (x.tv_usec < y.tv_usec)
3471 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3472 y.tv_usec -= 1000000 * nsec;
3473 y.tv_sec += nsec;
3476 if (x.tv_usec - y.tv_usec > 1000000)
3478 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3479 y.tv_usec += 1000000 * nsec;
3480 y.tv_sec -= nsec;
3483 /* Compute the time remaining to wait. tv_usec is certainly
3484 positive. */
3485 result->tv_sec = x.tv_sec - y.tv_sec;
3486 result->tv_usec = x.tv_usec - y.tv_usec;
3488 /* Return indication of whether the result should be considered
3489 negative. */
3490 return x.tv_sec < y.tv_sec;
3493 void
3494 XTflash (f)
3495 struct frame *f;
3497 /* Get the height not including a menu bar widget. */
3498 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
3499 /* Height of each line to flash. */
3500 int flash_height = FRAME_LINE_HEIGHT (f);
3501 /* These will be the left and right margins of the rectangles. */
3502 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
3503 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
3505 int width;
3507 /* Don't flash the area between a scroll bar and the frame
3508 edge it is next to. */
3509 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
3511 case vertical_scroll_bar_left:
3512 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3513 break;
3515 case vertical_scroll_bar_right:
3516 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
3517 break;
3519 default:
3520 break;
3523 width = flash_right - flash_left;
3525 BLOCK_INPUT;
3527 /* If window is tall, flash top and bottom line. */
3528 if (height > 3 * FRAME_LINE_HEIGHT (f))
3530 mac_invert_rectangle (f, flash_left,
3531 (FRAME_INTERNAL_BORDER_WIDTH (f)
3532 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3533 width, flash_height);
3534 mac_invert_rectangle (f, flash_left,
3535 (height - flash_height
3536 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3537 width, flash_height);
3539 else
3540 /* If it is short, flash it all. */
3541 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3542 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3544 x_flush (f);
3547 struct timeval wakeup;
3549 EMACS_GET_TIME (wakeup);
3551 /* Compute time to wait until, propagating carry from usecs. */
3552 wakeup.tv_usec += 150000;
3553 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3554 wakeup.tv_usec %= 1000000;
3556 /* Keep waiting until past the time wakeup or any input gets
3557 available. */
3558 while (! detect_input_pending ())
3560 struct timeval current;
3561 struct timeval timeout;
3563 EMACS_GET_TIME (current);
3565 /* Break if result would be negative. */
3566 if (timeval_subtract (&current, wakeup, current))
3567 break;
3569 /* How long `select' should wait. */
3570 timeout.tv_sec = 0;
3571 timeout.tv_usec = 10000;
3573 /* Try to wait that long--but we might wake up sooner. */
3574 select (0, NULL, NULL, NULL, &timeout);
3578 /* If window is tall, flash top and bottom line. */
3579 if (height > 3 * FRAME_LINE_HEIGHT (f))
3581 mac_invert_rectangle (f, flash_left,
3582 (FRAME_INTERNAL_BORDER_WIDTH (f)
3583 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)),
3584 width, flash_height);
3585 mac_invert_rectangle (f, flash_left,
3586 (height - flash_height
3587 - FRAME_INTERNAL_BORDER_WIDTH (f)),
3588 width, flash_height);
3590 else
3591 /* If it is short, flash it all. */
3592 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
3593 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
3595 x_flush (f);
3597 UNBLOCK_INPUT;
3600 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3603 /* Make audible bell. */
3605 void
3606 XTring_bell ()
3608 struct frame *f = SELECTED_FRAME ();
3610 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3611 if (visible_bell)
3612 XTflash (f);
3613 else
3614 #endif
3616 BLOCK_INPUT;
3617 SysBeep (1);
3618 XFlush (FRAME_MAC_DISPLAY (f));
3619 UNBLOCK_INPUT;
3624 /* Specify how many text lines, from the top of the window,
3625 should be affected by insert-lines and delete-lines operations.
3626 This, and those operations, are used only within an update
3627 that is bounded by calls to x_update_begin and x_update_end. */
3629 static void
3630 XTset_terminal_window (n)
3631 register int n;
3633 /* This function intentionally left blank. */
3638 /***********************************************************************
3639 Line Dance
3640 ***********************************************************************/
3642 /* Perform an insert-lines or delete-lines operation, inserting N
3643 lines or deleting -N lines at vertical position VPOS. */
3645 static void
3646 x_ins_del_lines (vpos, n)
3647 int vpos, n;
3649 abort ();
3653 /* Scroll part of the display as described by RUN. */
3655 static void
3656 x_scroll_run (w, run)
3657 struct window *w;
3658 struct run *run;
3660 struct frame *f = XFRAME (w->frame);
3661 int x, y, width, height, from_y, to_y, bottom_y;
3663 /* Get frame-relative bounding box of the text display area of W,
3664 without mode lines. Include in this box the left and right
3665 fringe of W. */
3666 window_box (w, -1, &x, &y, &width, &height);
3668 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3669 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3670 bottom_y = y + height;
3672 if (to_y < from_y)
3674 /* Scrolling up. Make sure we don't copy part of the mode
3675 line at the bottom. */
3676 if (from_y + run->height > bottom_y)
3677 height = bottom_y - from_y;
3678 else
3679 height = run->height;
3681 else
3683 /* Scolling down. Make sure we don't copy over the mode line.
3684 at the bottom. */
3685 if (to_y + run->height > bottom_y)
3686 height = bottom_y - to_y;
3687 else
3688 height = run->height;
3691 BLOCK_INPUT;
3693 /* Cursor off. Will be switched on again in x_update_window_end. */
3694 updated_window = w;
3695 x_clear_cursor (w);
3697 mac_scroll_area (f, f->output_data.mac->normal_gc,
3698 x, from_y,
3699 width, height,
3700 x, to_y);
3702 UNBLOCK_INPUT;
3707 /***********************************************************************
3708 Exposure Events
3709 ***********************************************************************/
3712 static void
3713 frame_highlight (f)
3714 struct frame *f;
3716 OSErr err;
3717 ControlRef root_control;
3719 BLOCK_INPUT;
3720 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
3721 if (err == noErr)
3722 ActivateControl (root_control);
3723 UNBLOCK_INPUT;
3724 x_update_cursor (f, 1);
3727 static void
3728 frame_unhighlight (f)
3729 struct frame *f;
3731 OSErr err;
3732 ControlRef root_control;
3734 BLOCK_INPUT;
3735 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
3736 if (err == noErr)
3737 DeactivateControl (root_control);
3738 UNBLOCK_INPUT;
3739 x_update_cursor (f, 1);
3742 /* The focus has changed. Update the frames as necessary to reflect
3743 the new situation. Note that we can't change the selected frame
3744 here, because the Lisp code we are interrupting might become confused.
3745 Each event gets marked with the frame in which it occurred, so the
3746 Lisp code can tell when the switch took place by examining the events. */
3748 static void
3749 x_new_focus_frame (dpyinfo, frame)
3750 struct x_display_info *dpyinfo;
3751 struct frame *frame;
3753 struct frame *old_focus = dpyinfo->x_focus_frame;
3755 if (frame != dpyinfo->x_focus_frame)
3757 /* Set this before calling other routines, so that they see
3758 the correct value of x_focus_frame. */
3759 dpyinfo->x_focus_frame = frame;
3761 if (old_focus && old_focus->auto_lower)
3762 x_lower_frame (old_focus);
3764 #if 0
3765 selected_frame = frame;
3766 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3767 selected_frame);
3768 Fselect_window (selected_frame->selected_window, Qnil);
3769 choose_minibuf_frame ();
3770 #endif /* ! 0 */
3772 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3773 pending_autoraise_frame = dpyinfo->x_focus_frame;
3774 else
3775 pending_autoraise_frame = 0;
3778 x_frame_rehighlight (dpyinfo);
3781 /* Handle FocusIn and FocusOut state changes for FRAME.
3782 If FRAME has focus and there exists more than one frame, puts
3783 a FOCUS_IN_EVENT into *BUFP. */
3785 static void
3786 mac_focus_changed (type, dpyinfo, frame, bufp)
3787 int type;
3788 struct mac_display_info *dpyinfo;
3789 struct frame *frame;
3790 struct input_event *bufp;
3792 if (type == activeFlag)
3794 if (dpyinfo->x_focus_event_frame != frame)
3796 x_new_focus_frame (dpyinfo, frame);
3797 dpyinfo->x_focus_event_frame = frame;
3799 /* Don't stop displaying the initial startup message
3800 for a switch-frame event we don't need. */
3801 if (GC_NILP (Vterminal_frame)
3802 && GC_CONSP (Vframe_list)
3803 && !GC_NILP (XCDR (Vframe_list)))
3805 bufp->kind = FOCUS_IN_EVENT;
3806 XSETFRAME (bufp->frame_or_window, frame);
3810 else
3812 if (dpyinfo->x_focus_event_frame == frame)
3814 dpyinfo->x_focus_event_frame = 0;
3815 x_new_focus_frame (dpyinfo, 0);
3820 /* The focus may have changed. Figure out if it is a real focus change,
3821 by checking both FocusIn/Out and Enter/LeaveNotify events.
3823 Returns FOCUS_IN_EVENT event in *BUFP. */
3825 static void
3826 x_detect_focus_change (dpyinfo, event, bufp)
3827 struct mac_display_info *dpyinfo;
3828 EventRecord *event;
3829 struct input_event *bufp;
3831 struct frame *frame;
3833 frame = mac_window_to_frame ((WindowPtr) event->message);
3834 if (! frame)
3835 return;
3837 /* On Mac, this is only called from focus events, so no switch needed. */
3838 mac_focus_changed ((event->modifiers & activeFlag),
3839 dpyinfo, frame, bufp);
3843 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3845 void
3846 x_mouse_leave (dpyinfo)
3847 struct x_display_info *dpyinfo;
3849 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3852 /* The focus has changed, or we have redirected a frame's focus to
3853 another frame (this happens when a frame uses a surrogate
3854 mini-buffer frame). Shift the highlight as appropriate.
3856 The FRAME argument doesn't necessarily have anything to do with which
3857 frame is being highlighted or un-highlighted; we only use it to find
3858 the appropriate X display info. */
3860 static void
3861 XTframe_rehighlight (frame)
3862 struct frame *frame;
3864 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3867 static void
3868 x_frame_rehighlight (dpyinfo)
3869 struct x_display_info *dpyinfo;
3871 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3873 if (dpyinfo->x_focus_frame)
3875 dpyinfo->x_highlight_frame
3876 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3877 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3878 : dpyinfo->x_focus_frame);
3879 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3881 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3882 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3885 else
3886 dpyinfo->x_highlight_frame = 0;
3888 if (dpyinfo->x_highlight_frame != old_highlight)
3890 if (old_highlight)
3891 frame_unhighlight (old_highlight);
3892 if (dpyinfo->x_highlight_frame)
3893 frame_highlight (dpyinfo->x_highlight_frame);
3899 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3901 #if 0 /* MAC_TODO */
3902 /* Initialize mode_switch_bit and modifier_meaning. */
3903 static void
3904 x_find_modifier_meanings (dpyinfo)
3905 struct x_display_info *dpyinfo;
3907 int min_code, max_code;
3908 KeySym *syms;
3909 int syms_per_code;
3910 XModifierKeymap *mods;
3912 dpyinfo->meta_mod_mask = 0;
3913 dpyinfo->shift_lock_mask = 0;
3914 dpyinfo->alt_mod_mask = 0;
3915 dpyinfo->super_mod_mask = 0;
3916 dpyinfo->hyper_mod_mask = 0;
3918 #ifdef HAVE_X11R4
3919 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3920 #else
3921 min_code = dpyinfo->display->min_keycode;
3922 max_code = dpyinfo->display->max_keycode;
3923 #endif
3925 syms = XGetKeyboardMapping (dpyinfo->display,
3926 min_code, max_code - min_code + 1,
3927 &syms_per_code);
3928 mods = XGetModifierMapping (dpyinfo->display);
3930 /* Scan the modifier table to see which modifier bits the Meta and
3931 Alt keysyms are on. */
3933 int row, col; /* The row and column in the modifier table. */
3935 for (row = 3; row < 8; row++)
3936 for (col = 0; col < mods->max_keypermod; col++)
3938 KeyCode code
3939 = mods->modifiermap[(row * mods->max_keypermod) + col];
3941 /* Zeroes are used for filler. Skip them. */
3942 if (code == 0)
3943 continue;
3945 /* Are any of this keycode's keysyms a meta key? */
3947 int code_col;
3949 for (code_col = 0; code_col < syms_per_code; code_col++)
3951 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3953 switch (sym)
3955 case XK_Meta_L:
3956 case XK_Meta_R:
3957 dpyinfo->meta_mod_mask |= (1 << row);
3958 break;
3960 case XK_Alt_L:
3961 case XK_Alt_R:
3962 dpyinfo->alt_mod_mask |= (1 << row);
3963 break;
3965 case XK_Hyper_L:
3966 case XK_Hyper_R:
3967 dpyinfo->hyper_mod_mask |= (1 << row);
3968 break;
3970 case XK_Super_L:
3971 case XK_Super_R:
3972 dpyinfo->super_mod_mask |= (1 << row);
3973 break;
3975 case XK_Shift_Lock:
3976 /* Ignore this if it's not on the lock modifier. */
3977 if ((1 << row) == LockMask)
3978 dpyinfo->shift_lock_mask = LockMask;
3979 break;
3986 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3987 if (! dpyinfo->meta_mod_mask)
3989 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3990 dpyinfo->alt_mod_mask = 0;
3993 /* If some keys are both alt and meta,
3994 make them just meta, not alt. */
3995 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3997 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
4000 XFree ((char *) syms);
4001 XFreeModifiermap (mods);
4004 #endif /* MAC_TODO */
4006 /* Convert between the modifier bits X uses and the modifier bits
4007 Emacs uses. */
4009 static unsigned int
4010 x_mac_to_emacs_modifiers (dpyinfo, state)
4011 struct x_display_info *dpyinfo;
4012 unsigned short state;
4014 return (((state & shiftKey) ? shift_modifier : 0)
4015 | ((state & controlKey) ? ctrl_modifier : 0)
4016 | ((state & cmdKey) ? meta_modifier : 0)
4017 | ((state & optionKey) ? alt_modifier : 0));
4020 #if 0 /* MAC_TODO */
4021 static unsigned short
4022 x_emacs_to_x_modifiers (dpyinfo, state)
4023 struct x_display_info *dpyinfo;
4024 unsigned int state;
4026 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
4027 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
4028 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
4029 | ((state & shift_modifier) ? ShiftMask : 0)
4030 | ((state & ctrl_modifier) ? ControlMask : 0)
4031 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
4033 #endif /* MAC_TODO */
4035 /* Convert a keysym to its name. */
4037 char *
4038 x_get_keysym_name (keysym)
4039 int keysym;
4041 char *value;
4043 BLOCK_INPUT;
4044 #if 0
4045 value = XKeysymToString (keysym);
4046 #else
4047 value = 0;
4048 #endif
4049 UNBLOCK_INPUT;
4051 return value;
4056 /* Function to report a mouse movement to the mainstream Emacs code.
4057 The input handler calls this.
4059 We have received a mouse movement event, which is given in *event.
4060 If the mouse is over a different glyph than it was last time, tell
4061 the mainstream emacs code by setting mouse_moved. If not, ask for
4062 another motion event, so we can check again the next time it moves. */
4064 static Point last_mouse_motion_position;
4065 static Lisp_Object last_mouse_motion_frame;
4067 static int
4068 note_mouse_movement (frame, pos)
4069 FRAME_PTR frame;
4070 Point *pos;
4072 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
4073 #if TARGET_API_MAC_CARBON
4074 Rect r;
4075 #endif
4077 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
4078 last_mouse_motion_position = *pos;
4079 XSETFRAME (last_mouse_motion_frame, frame);
4081 #if TARGET_API_MAC_CARBON
4082 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
4083 #else
4084 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
4085 #endif
4087 if (frame == dpyinfo->mouse_face_mouse_frame)
4088 /* This case corresponds to LeaveNotify in X11. */
4090 /* If we move outside the frame, then we're certainly no
4091 longer on any text in the frame. */
4092 clear_mouse_face (dpyinfo);
4093 dpyinfo->mouse_face_mouse_frame = 0;
4094 if (!dpyinfo->grabbed)
4095 rif->define_frame_cursor (frame,
4096 frame->output_data.mac->nontext_cursor);
4098 return 1;
4100 /* Has the mouse moved off the glyph it was on at the last sighting? */
4101 if (frame != last_mouse_glyph_frame
4102 || !PtInRect (*pos, &last_mouse_glyph))
4104 frame->mouse_moved = 1;
4105 last_mouse_scroll_bar = Qnil;
4106 note_mouse_highlight (frame, pos->h, pos->v);
4107 /* Remember which glyph we're now on. */
4108 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph);
4109 last_mouse_glyph_frame = frame;
4110 return 1;
4113 return 0;
4117 /************************************************************************
4118 Mouse Face
4119 ************************************************************************/
4121 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4123 static void
4124 redo_mouse_highlight ()
4126 if (!NILP (last_mouse_motion_frame)
4127 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
4128 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
4129 last_mouse_motion_position.h,
4130 last_mouse_motion_position.v);
4134 static struct frame *
4135 mac_focus_frame (dpyinfo)
4136 struct mac_display_info *dpyinfo;
4138 if (dpyinfo->x_focus_frame)
4139 return dpyinfo->x_focus_frame;
4140 else
4141 /* Mac version may get events, such as a menu bar click, even when
4142 all the frames are invisible. In this case, we regard the
4143 event came to the selected frame. */
4144 return SELECTED_FRAME ();
4148 /* Return the current position of the mouse.
4149 *FP should be a frame which indicates which display to ask about.
4151 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4152 and *PART to the frame, window, and scroll bar part that the mouse
4153 is over. Set *X and *Y to the portion and whole of the mouse's
4154 position on the scroll bar.
4156 If the mouse movement started elsewhere, set *FP to the frame the
4157 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4158 the mouse is over.
4160 Set *TIME to the server time-stamp for the time at which the mouse
4161 was at this position.
4163 Don't store anything if we don't have a valid set of values to report.
4165 This clears the mouse_moved flag, so we can wait for the next mouse
4166 movement. */
4168 static void
4169 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4170 FRAME_PTR *fp;
4171 int insist;
4172 Lisp_Object *bar_window;
4173 enum scroll_bar_part *part;
4174 Lisp_Object *x, *y;
4175 unsigned long *time;
4177 FRAME_PTR f1;
4179 BLOCK_INPUT;
4181 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4182 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4183 else
4185 Lisp_Object frame, tail;
4187 /* Clear the mouse-moved flag for every frame on this display. */
4188 FOR_EACH_FRAME (tail, frame)
4189 XFRAME (frame)->mouse_moved = 0;
4191 last_mouse_scroll_bar = Qnil;
4193 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
4194 && FRAME_LIVE_P (last_mouse_frame))
4195 f1 = last_mouse_frame;
4196 else
4197 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4199 if (f1)
4201 /* Ok, we found a frame. Store all the values.
4202 last_mouse_glyph is a rectangle used to reduce the
4203 generation of mouse events. To not miss any motion
4204 events, we must divide the frame into rectangles of the
4205 size of the smallest character that could be displayed
4206 on it, i.e. into the same rectangles that matrices on
4207 the frame are divided into. */
4208 Point mouse_pos;
4210 SetPortWindowPort (FRAME_MAC_WINDOW (f1));
4211 GetMouse (&mouse_pos);
4212 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
4213 &last_mouse_glyph);
4214 last_mouse_glyph_frame = f1;
4216 *bar_window = Qnil;
4217 *part = 0;
4218 *fp = f1;
4219 XSETINT (*x, mouse_pos.h);
4220 XSETINT (*y, mouse_pos.v);
4221 *time = last_mouse_movement_time;
4225 UNBLOCK_INPUT;
4229 /************************************************************************
4230 Toolkit scroll bars
4231 ************************************************************************/
4233 #ifdef USE_TOOLKIT_SCROLL_BARS
4235 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4236 static OSStatus install_scroll_bar_timer P_ ((void));
4237 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4238 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4239 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4240 struct input_event *));
4241 static OSErr get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
4242 Rect *));
4243 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4244 ControlPartCode,
4245 struct input_event *));
4246 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4247 struct input_event *));
4248 static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
4249 Point, struct input_event *));
4250 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4251 int, int, int));
4253 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4255 static int last_scroll_bar_part;
4257 static EventLoopTimerRef scroll_bar_timer;
4259 static int scroll_bar_timer_event_posted_p;
4261 #define SCROLL_BAR_FIRST_DELAY 0.5
4262 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4264 static pascal void
4265 scroll_bar_timer_callback (timer, data)
4266 EventLoopTimerRef timer;
4267 void *data;
4269 EventRef event = NULL;
4270 OSErr err;
4272 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
4273 kEventAttributeNone, &event);
4274 if (err == noErr)
4276 Point mouse_pos;
4278 GetMouse (&mouse_pos);
4279 LocalToGlobal (&mouse_pos);
4280 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
4281 sizeof (Point), &mouse_pos);
4283 if (err == noErr)
4285 UInt32 modifiers = GetCurrentKeyModifiers ();
4287 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
4288 sizeof (UInt32), &modifiers);
4290 if (err == noErr)
4291 err = PostEventToQueue (GetCurrentEventQueue (), event,
4292 kEventPriorityStandard);
4293 if (err == noErr)
4294 scroll_bar_timer_event_posted_p = 1;
4296 if (event)
4297 ReleaseEvent (event);
4300 static OSStatus
4301 install_scroll_bar_timer ()
4303 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4305 if (scroll_bar_timer_callbackUPP == NULL)
4306 scroll_bar_timer_callbackUPP =
4307 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4309 if (scroll_bar_timer == NULL)
4310 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4311 kEventDurationForever as delays. */
4312 return
4313 InstallEventLoopTimer (GetCurrentEventLoop (),
4314 kEventDurationForever, kEventDurationForever,
4315 scroll_bar_timer_callbackUPP, NULL,
4316 &scroll_bar_timer);
4319 static OSStatus
4320 set_scroll_bar_timer (delay)
4321 EventTimerInterval delay;
4323 if (scroll_bar_timer == NULL)
4324 install_scroll_bar_timer ();
4326 scroll_bar_timer_event_posted_p = 0;
4328 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4331 static int
4332 control_part_code_to_scroll_bar_part (part_code)
4333 ControlPartCode part_code;
4335 switch (part_code)
4337 case kControlUpButtonPart: return scroll_bar_up_arrow;
4338 case kControlDownButtonPart: return scroll_bar_down_arrow;
4339 case kControlPageUpPart: return scroll_bar_above_handle;
4340 case kControlPageDownPart: return scroll_bar_below_handle;
4341 case kControlIndicatorPart: return scroll_bar_handle;
4344 return -1;
4347 static void
4348 construct_scroll_bar_click (bar, part, bufp)
4349 struct scroll_bar *bar;
4350 int part;
4351 struct input_event *bufp;
4353 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4354 bufp->frame_or_window = bar->window;
4355 bufp->arg = Qnil;
4356 bufp->part = part;
4357 bufp->code = 0;
4358 XSETINT (bufp->x, 0);
4359 XSETINT (bufp->y, 0);
4360 bufp->modifiers = 0;
4363 static OSErr
4364 get_control_part_bounds (ch, part_code, rect)
4365 ControlHandle ch;
4366 ControlPartCode part_code;
4367 Rect *rect;
4369 RgnHandle region = NewRgn ();
4370 OSStatus err;
4372 err = GetControlRegion (ch, part_code, region);
4373 if (err == noErr)
4374 GetRegionBounds (region, rect);
4375 DisposeRgn (region);
4377 return err;
4380 static void
4381 x_scroll_bar_handle_press (bar, part_code, bufp)
4382 struct scroll_bar *bar;
4383 ControlPartCode part_code;
4384 struct input_event *bufp;
4386 int part = control_part_code_to_scroll_bar_part (part_code);
4388 if (part < 0)
4389 return;
4391 if (part != scroll_bar_handle)
4393 construct_scroll_bar_click (bar, part, bufp);
4394 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4395 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4398 last_scroll_bar_part = part;
4399 bar->dragging = Qnil;
4400 tracked_scroll_bar = bar;
4403 static void
4404 x_scroll_bar_handle_release (bar, bufp)
4405 struct scroll_bar *bar;
4406 struct input_event *bufp;
4408 if (last_scroll_bar_part != scroll_bar_handle
4409 || !GC_NILP (bar->dragging))
4410 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4412 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4413 set_scroll_bar_timer (kEventDurationForever);
4415 last_scroll_bar_part = -1;
4416 bar->dragging = Qnil;
4417 tracked_scroll_bar = NULL;
4420 static void
4421 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4422 WindowPtr win;
4423 struct scroll_bar *bar;
4424 Point mouse_pos;
4425 struct input_event *bufp;
4427 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4429 if (last_scroll_bar_part == scroll_bar_handle)
4431 int top, top_range;
4432 Rect r;
4434 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4435 kControlIndicatorPart, &r);
4437 if (GC_NILP (bar->dragging))
4438 XSETINT (bar->dragging, mouse_pos.v - r.top);
4440 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4441 top_range = (XINT (bar->track_height) - (r.bottom - r.top)) *
4442 (1.0 + (float) GetControlViewSize (ch) / GetControl32BitMaximum (ch))
4443 + .5;
4445 if (top < 0)
4446 top = 0;
4447 if (top > top_range)
4448 top = top_range;
4450 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4451 XSETINT (bufp->x, top);
4452 XSETINT (bufp->y, top_range);
4454 else
4456 ControlPartCode part_code;
4457 int unhilite_p = 0, part;
4459 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4460 unhilite_p = 1;
4461 else
4463 part = control_part_code_to_scroll_bar_part (part_code);
4465 switch (last_scroll_bar_part)
4467 case scroll_bar_above_handle:
4468 case scroll_bar_below_handle:
4469 if (part != scroll_bar_above_handle
4470 && part != scroll_bar_below_handle)
4471 unhilite_p = 1;
4472 break;
4474 case scroll_bar_up_arrow:
4475 case scroll_bar_down_arrow:
4476 if (part != scroll_bar_up_arrow
4477 && part != scroll_bar_down_arrow)
4478 unhilite_p = 1;
4479 break;
4483 if (unhilite_p)
4484 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4485 else if (part != last_scroll_bar_part
4486 || scroll_bar_timer_event_posted_p)
4488 construct_scroll_bar_click (bar, part, bufp);
4489 last_scroll_bar_part = part;
4490 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4491 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4496 /* Set the thumb size and position of scroll bar BAR. We are currently
4497 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4499 static void
4500 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4501 struct scroll_bar *bar;
4502 int portion, position, whole;
4504 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4506 int value, viewsize, maximum;
4508 if (whole == 0 || XINT (bar->track_height) == 0)
4509 value = 0, viewsize = 1, maximum = 0;
4510 else
4512 value = position;
4513 viewsize = portion;
4514 maximum = max (0, whole - portion);
4517 BLOCK_INPUT;
4519 SetControl32BitMinimum (ch, 0);
4520 SetControl32BitMaximum (ch, maximum);
4521 SetControl32BitValue (ch, value);
4522 SetControlViewSize (ch, viewsize);
4524 UNBLOCK_INPUT;
4527 #endif /* USE_TOOLKIT_SCROLL_BARS */
4531 /************************************************************************
4532 Scroll bars, general
4533 ************************************************************************/
4535 /* Create a scroll bar and return the scroll bar vector for it. W is
4536 the Emacs window on which to create the scroll bar. TOP, LEFT,
4537 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4538 scroll bar. */
4540 static struct scroll_bar *
4541 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4542 struct window *w;
4543 int top, left, width, height, disp_top, disp_height;
4545 struct frame *f = XFRAME (w->frame);
4546 struct scroll_bar *bar
4547 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4548 Rect r;
4549 ControlHandle ch;
4551 BLOCK_INPUT;
4553 r.left = left;
4554 r.top = disp_top;
4555 r.right = left + width;
4556 r.bottom = disp_top + disp_height;
4558 #if TARGET_API_MAC_CARBON
4559 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4560 0, 0, 0, kControlScrollBarProc, (long) bar);
4561 #else
4562 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4563 0, 0, 0, scrollBarProc, (long) bar);
4564 #endif
4565 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4567 XSETWINDOW (bar->window, w);
4568 XSETINT (bar->top, top);
4569 XSETINT (bar->left, left);
4570 XSETINT (bar->width, width);
4571 XSETINT (bar->height, height);
4572 XSETINT (bar->start, 0);
4573 XSETINT (bar->end, 0);
4574 bar->dragging = Qnil;
4575 #ifdef USE_TOOLKIT_SCROLL_BARS
4576 bar->track_top = Qnil;
4577 bar->track_height = Qnil;
4578 #endif
4580 /* Add bar to its frame's list of scroll bars. */
4581 bar->next = FRAME_SCROLL_BARS (f);
4582 bar->prev = Qnil;
4583 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4584 if (!NILP (bar->next))
4585 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4587 UNBLOCK_INPUT;
4588 return bar;
4592 /* Draw BAR's handle in the proper position.
4594 If the handle is already drawn from START to END, don't bother
4595 redrawing it, unless REBUILD is non-zero; in that case, always
4596 redraw it. (REBUILD is handy for drawing the handle after expose
4597 events.)
4599 Normally, we want to constrain the start and end of the handle to
4600 fit inside its rectangle, but if the user is dragging the scroll
4601 bar handle, we want to let them drag it down all the way, so that
4602 the bar's top is as far down as it goes; otherwise, there's no way
4603 to move to the very end of the buffer. */
4605 #ifndef USE_TOOLKIT_SCROLL_BARS
4607 static void
4608 x_scroll_bar_set_handle (bar, start, end, rebuild)
4609 struct scroll_bar *bar;
4610 int start, end;
4611 int rebuild;
4613 int dragging = ! NILP (bar->dragging);
4614 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4615 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4616 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4617 int length = end - start;
4619 /* If the display is already accurate, do nothing. */
4620 if (! rebuild
4621 && start == XINT (bar->start)
4622 && end == XINT (bar->end))
4623 return;
4625 BLOCK_INPUT;
4627 /* Make sure the values are reasonable, and try to preserve the
4628 distance between start and end. */
4629 if (start < 0)
4630 start = 0;
4631 else if (start > top_range)
4632 start = top_range;
4633 end = start + length;
4635 if (end < start)
4636 end = start;
4637 else if (end > top_range && ! dragging)
4638 end = top_range;
4640 /* Store the adjusted setting in the scroll bar. */
4641 XSETINT (bar->start, start);
4642 XSETINT (bar->end, end);
4644 /* Clip the end position, just for display. */
4645 if (end > top_range)
4646 end = top_range;
4648 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4649 top positions, to make sure the handle is always at least that
4650 many pixels tall. */
4651 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4653 SetControlMinimum (ch, 0);
4654 /* Don't inadvertently activate deactivated scroll bars */
4655 if (GetControlMaximum (ch) != -1)
4656 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4657 - (end - start));
4658 SetControlValue (ch, start);
4659 #if TARGET_API_MAC_CARBON
4660 SetControlViewSize (ch, end - start);
4661 #endif
4663 UNBLOCK_INPUT;
4666 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4668 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4669 nil. */
4671 static void
4672 x_scroll_bar_remove (bar)
4673 struct scroll_bar *bar;
4675 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4677 BLOCK_INPUT;
4679 /* Destroy the Mac scroll bar control */
4680 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4682 /* Disassociate this scroll bar from its window. */
4683 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4685 UNBLOCK_INPUT;
4689 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4690 that we are displaying PORTION characters out of a total of WHOLE
4691 characters, starting at POSITION. If WINDOW has no scroll bar,
4692 create one. */
4694 static void
4695 XTset_vertical_scroll_bar (w, portion, whole, position)
4696 struct window *w;
4697 int portion, whole, position;
4699 struct frame *f = XFRAME (w->frame);
4700 struct scroll_bar *bar;
4701 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4702 int window_y, window_height;
4704 /* Get window dimensions. */
4705 window_box (w, -1, 0, &window_y, 0, &window_height);
4706 top = window_y;
4707 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4708 height = window_height;
4710 /* Compute the left edge of the scroll bar area. */
4711 left = WINDOW_SCROLL_BAR_AREA_X (w);
4713 /* Compute the width of the scroll bar which might be less than
4714 the width of the area reserved for the scroll bar. */
4715 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4716 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4717 else
4718 sb_width = width;
4720 /* Compute the left edge of the scroll bar. */
4721 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4722 sb_left = left;
4723 else
4724 sb_left = left + width - sb_width;
4726 /* Adjustments according to Inside Macintosh to make it look nice */
4727 disp_top = top;
4728 disp_height = height;
4729 if (disp_top == 0)
4731 disp_top = -1;
4732 disp_height++;
4734 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4736 disp_top++;
4737 disp_height--;
4740 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4741 sb_left++;
4743 /* Does the scroll bar exist yet? */
4744 if (NILP (w->vertical_scroll_bar))
4746 BLOCK_INPUT;
4747 mac_clear_area (f, left, top, width, height);
4748 UNBLOCK_INPUT;
4749 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4750 disp_height);
4751 XSETVECTOR (w->vertical_scroll_bar, bar);
4753 else
4755 /* It may just need to be moved and resized. */
4756 ControlHandle ch;
4758 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4759 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4761 BLOCK_INPUT;
4763 /* If already correctly positioned, do nothing. */
4764 if (!(XINT (bar->left) == sb_left
4765 && XINT (bar->top) == top
4766 && XINT (bar->width) == sb_width
4767 && XINT (bar->height) == height))
4769 /* Since toolkit scroll bars are smaller than the space reserved
4770 for them on the frame, we have to clear "under" them. */
4771 mac_clear_area (f, left, top, width, height);
4773 HideControl (ch);
4774 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4775 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4776 disp_height);
4777 if (sb_width < disp_height)
4778 ShowControl (ch);
4780 /* Remember new settings. */
4781 XSETINT (bar->left, sb_left);
4782 XSETINT (bar->top, top);
4783 XSETINT (bar->width, sb_width);
4784 XSETINT (bar->height, height);
4785 #ifdef USE_TOOLKIT_SCROLL_BARS
4786 bar->track_top = Qnil;
4787 bar->track_height = Qnil;
4788 #endif
4791 UNBLOCK_INPUT;
4794 #ifdef USE_TOOLKIT_SCROLL_BARS
4795 if (NILP (bar->track_top))
4797 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4798 Rect r0, r1;
4800 BLOCK_INPUT;
4802 SetControl32BitMinimum (ch, 0);
4803 SetControl32BitMaximum (ch, 1);
4804 SetControlViewSize (ch, 1);
4806 /* Move the scroll bar thumb to the top. */
4807 SetControl32BitValue (ch, 0);
4808 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
4810 /* Move the scroll bar thumb to the bottom. */
4811 SetControl32BitValue (ch, 1);
4812 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
4814 UnionRect (&r0, &r1, &r0);
4815 XSETINT (bar->track_top, r0.top);
4816 XSETINT (bar->track_height, r0.bottom - r0.top);
4818 UNBLOCK_INPUT;
4821 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4822 #else /* not USE_TOOLKIT_SCROLL_BARS */
4823 /* Set the scroll bar's current state, unless we're currently being
4824 dragged. */
4825 if (NILP (bar->dragging))
4827 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4829 if (whole == 0)
4830 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4831 else
4833 int start = ((double) position * top_range) / whole;
4834 int end = ((double) (position + portion) * top_range) / whole;
4835 x_scroll_bar_set_handle (bar, start, end, 0);
4838 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4842 /* The following three hooks are used when we're doing a thorough
4843 redisplay of the frame. We don't explicitly know which scroll bars
4844 are going to be deleted, because keeping track of when windows go
4845 away is a real pain - "Can you say set-window-configuration, boys
4846 and girls?" Instead, we just assert at the beginning of redisplay
4847 that *all* scroll bars are to be removed, and then save a scroll bar
4848 from the fiery pit when we actually redisplay its window. */
4850 /* Arrange for all scroll bars on FRAME to be removed at the next call
4851 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4852 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4854 static void
4855 XTcondemn_scroll_bars (frame)
4856 FRAME_PTR frame;
4858 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4859 while (! NILP (FRAME_SCROLL_BARS (frame)))
4861 Lisp_Object bar;
4862 bar = FRAME_SCROLL_BARS (frame);
4863 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4864 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4865 XSCROLL_BAR (bar)->prev = Qnil;
4866 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4867 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4868 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4873 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4874 Note that WINDOW isn't necessarily condemned at all. */
4876 static void
4877 XTredeem_scroll_bar (window)
4878 struct window *window;
4880 struct scroll_bar *bar;
4881 struct frame *f;
4883 /* We can't redeem this window's scroll bar if it doesn't have one. */
4884 if (NILP (window->vertical_scroll_bar))
4885 abort ();
4887 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4889 /* Unlink it from the condemned list. */
4890 f = XFRAME (WINDOW_FRAME (window));
4891 if (NILP (bar->prev))
4893 /* If the prev pointer is nil, it must be the first in one of
4894 the lists. */
4895 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4896 /* It's not condemned. Everything's fine. */
4897 return;
4898 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4899 window->vertical_scroll_bar))
4900 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4901 else
4902 /* If its prev pointer is nil, it must be at the front of
4903 one or the other! */
4904 abort ();
4906 else
4907 XSCROLL_BAR (bar->prev)->next = bar->next;
4909 if (! NILP (bar->next))
4910 XSCROLL_BAR (bar->next)->prev = bar->prev;
4912 bar->next = FRAME_SCROLL_BARS (f);
4913 bar->prev = Qnil;
4914 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4915 if (! NILP (bar->next))
4916 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4919 /* Remove all scroll bars on FRAME that haven't been saved since the
4920 last call to `*condemn_scroll_bars_hook'. */
4922 static void
4923 XTjudge_scroll_bars (f)
4924 FRAME_PTR f;
4926 Lisp_Object bar, next;
4928 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4930 /* Clear out the condemned list now so we won't try to process any
4931 more events on the hapless scroll bars. */
4932 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4934 for (; ! NILP (bar); bar = next)
4936 struct scroll_bar *b = XSCROLL_BAR (bar);
4938 x_scroll_bar_remove (b);
4940 next = b->next;
4941 b->next = b->prev = Qnil;
4944 /* Now there should be no references to the condemned scroll bars,
4945 and they should get garbage-collected. */
4949 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4950 is set to something other than NO_EVENT, it is enqueued.
4952 This may be called from a signal handler, so we have to ignore GC
4953 mark bits. */
4955 static void
4956 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4957 struct scroll_bar *bar;
4958 ControlPartCode part_code;
4959 EventRecord *er;
4960 struct input_event *bufp;
4962 int win_y, top_range;
4964 if (! GC_WINDOWP (bar->window))
4965 abort ();
4967 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4968 bufp->frame_or_window = bar->window;
4969 bufp->arg = Qnil;
4971 bar->dragging = Qnil;
4973 switch (part_code)
4975 case kControlUpButtonPart:
4976 bufp->part = scroll_bar_up_arrow;
4977 break;
4978 case kControlDownButtonPart:
4979 bufp->part = scroll_bar_down_arrow;
4980 break;
4981 case kControlPageUpPart:
4982 bufp->part = scroll_bar_above_handle;
4983 break;
4984 case kControlPageDownPart:
4985 bufp->part = scroll_bar_below_handle;
4986 break;
4987 #if TARGET_API_MAC_CARBON
4988 default:
4989 #else
4990 case kControlIndicatorPart:
4991 #endif
4992 if (er->what == mouseDown)
4993 bar->dragging = make_number (0);
4994 XSETVECTOR (last_mouse_scroll_bar, bar);
4995 bufp->part = scroll_bar_handle;
4996 break;
4999 win_y = XINT (bufp->y) - XINT (bar->top);
5000 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
5002 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5004 win_y -= 24;
5006 if (! NILP (bar->dragging))
5007 win_y -= XINT (bar->dragging);
5009 if (win_y < 0)
5010 win_y = 0;
5011 if (win_y > top_range)
5012 win_y = top_range;
5014 XSETINT (bufp->x, win_y);
5015 XSETINT (bufp->y, top_range);
5018 #ifndef USE_TOOLKIT_SCROLL_BARS
5020 /* Handle some mouse motion while someone is dragging the scroll bar.
5022 This may be called from a signal handler, so we have to ignore GC
5023 mark bits. */
5025 static void
5026 x_scroll_bar_note_movement (bar, y_pos, t)
5027 struct scroll_bar *bar;
5028 int y_pos;
5029 Time t;
5031 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
5033 last_mouse_movement_time = t;
5035 f->mouse_moved = 1;
5036 XSETVECTOR (last_mouse_scroll_bar, bar);
5038 /* If we're dragging the bar, display it. */
5039 if (! GC_NILP (bar->dragging))
5041 /* Where should the handle be now? */
5042 int new_start = y_pos - 24;
5044 if (new_start != XINT (bar->start))
5046 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
5048 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
5053 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5055 /* Return information to the user about the current position of the mouse
5056 on the scroll bar. */
5058 static void
5059 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
5060 FRAME_PTR *fp;
5061 Lisp_Object *bar_window;
5062 enum scroll_bar_part *part;
5063 Lisp_Object *x, *y;
5064 unsigned long *time;
5066 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
5067 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
5068 #if TARGET_API_MAC_CARBON
5069 WindowPtr wp = GetControlOwner (ch);
5070 #else
5071 WindowPtr wp = (*ch)->contrlOwner;
5072 #endif
5073 Point mouse_pos;
5074 struct frame *f = mac_window_to_frame (wp);
5075 int win_y, top_range;
5077 SetPortWindowPort (wp);
5079 GetMouse (&mouse_pos);
5081 win_y = mouse_pos.v - XINT (bar->top);
5082 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5084 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5086 win_y -= 24;
5088 if (! NILP (bar->dragging))
5089 win_y -= XINT (bar->dragging);
5091 if (win_y < 0)
5092 win_y = 0;
5093 if (win_y > top_range)
5094 win_y = top_range;
5096 *fp = f;
5097 *bar_window = bar->window;
5099 if (! NILP (bar->dragging))
5100 *part = scroll_bar_handle;
5101 else if (win_y < XINT (bar->start))
5102 *part = scroll_bar_above_handle;
5103 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5104 *part = scroll_bar_handle;
5105 else
5106 *part = scroll_bar_below_handle;
5108 XSETINT (*x, win_y);
5109 XSETINT (*y, top_range);
5111 f->mouse_moved = 0;
5112 last_mouse_scroll_bar = Qnil;
5114 *time = last_mouse_movement_time;
5118 /* The screen has been cleared so we may have changed foreground or
5119 background colors, and the scroll bars may need to be redrawn.
5120 Clear out the scroll bars, and ask for expose events, so we can
5121 redraw them. */
5123 void
5124 x_scroll_bar_clear (f)
5125 FRAME_PTR f;
5127 XTcondemn_scroll_bars (f);
5128 XTjudge_scroll_bars (f);
5132 /***********************************************************************
5133 Text Cursor
5134 ***********************************************************************/
5136 /* Set clipping for output in glyph row ROW. W is the window in which
5137 we operate. GC is the graphics context to set clipping in.
5139 ROW may be a text row or, e.g., a mode line. Text rows must be
5140 clipped to the interior of the window dedicated to text display,
5141 mode lines must be clipped to the whole window. */
5143 static void
5144 x_clip_to_row (w, row, area, gc)
5145 struct window *w;
5146 struct glyph_row *row;
5147 int area;
5148 GC gc;
5150 struct frame *f = XFRAME (WINDOW_FRAME (w));
5151 Rect clip_rect;
5152 int window_x, window_y, window_width;
5154 window_box (w, area, &window_x, &window_y, &window_width, 0);
5156 clip_rect.left = window_x;
5157 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5158 clip_rect.top = max (clip_rect.top, window_y);
5159 clip_rect.right = clip_rect.left + window_width;
5160 clip_rect.bottom = clip_rect.top + row->visible_height;
5162 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1);
5166 /* Draw a hollow box cursor on window W in glyph row ROW. */
5168 static void
5169 x_draw_hollow_cursor (w, row)
5170 struct window *w;
5171 struct glyph_row *row;
5173 struct frame *f = XFRAME (WINDOW_FRAME (w));
5174 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5175 Display *dpy = FRAME_MAC_DISPLAY (f);
5176 int x, y, wd, h;
5177 XGCValues xgcv;
5178 struct glyph *cursor_glyph;
5179 GC gc;
5181 /* Get the glyph the cursor is on. If we can't tell because
5182 the current matrix is invalid or such, give up. */
5183 cursor_glyph = get_phys_cursor_glyph (w);
5184 if (cursor_glyph == NULL)
5185 return;
5187 /* Compute frame-relative coordinates for phys cursor. */
5188 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5189 y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
5190 wd = w->phys_cursor_width;
5192 /* The foreground of cursor_gc is typically the same as the normal
5193 background color, which can cause the cursor box to be invisible. */
5194 xgcv.foreground = f->output_data.mac->cursor_pixel;
5195 if (dpyinfo->scratch_cursor_gc)
5196 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5197 else
5198 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5199 GCForeground, &xgcv);
5200 gc = dpyinfo->scratch_cursor_gc;
5202 /* Set clipping, draw the rectangle, and reset clipping again. */
5203 x_clip_to_row (w, row, TEXT_AREA, gc);
5204 mac_draw_rectangle (f, gc, x, y, wd, h);
5205 mac_reset_clip_rectangles (dpy, gc);
5209 /* Draw a bar cursor on window W in glyph row ROW.
5211 Implementation note: One would like to draw a bar cursor with an
5212 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5213 Unfortunately, I didn't find a font yet that has this property set.
5214 --gerd. */
5216 static void
5217 x_draw_bar_cursor (w, row, width, kind)
5218 struct window *w;
5219 struct glyph_row *row;
5220 int width;
5221 enum text_cursor_kinds kind;
5223 struct frame *f = XFRAME (w->frame);
5224 struct glyph *cursor_glyph;
5226 /* If cursor is out of bounds, don't draw garbage. This can happen
5227 in mini-buffer windows when switching between echo area glyphs
5228 and mini-buffer. */
5229 cursor_glyph = get_phys_cursor_glyph (w);
5230 if (cursor_glyph == NULL)
5231 return;
5233 /* If on an image, draw like a normal cursor. That's usually better
5234 visible than drawing a bar, esp. if the image is large so that
5235 the bar might not be in the window. */
5236 if (cursor_glyph->type == IMAGE_GLYPH)
5238 struct glyph_row *row;
5239 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5240 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5242 else
5244 Display *dpy = FRAME_MAC_DISPLAY (f);
5245 Window window = FRAME_MAC_WINDOW (f);
5246 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5247 unsigned long mask = GCForeground | GCBackground;
5248 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5249 XGCValues xgcv;
5251 /* If the glyph's background equals the color we normally draw
5252 the bar cursor in, the bar cursor in its normal color is
5253 invisible. Use the glyph's foreground color instead in this
5254 case, on the assumption that the glyph's colors are chosen so
5255 that the glyph is legible. */
5256 if (face->background == f->output_data.mac->cursor_pixel)
5257 xgcv.background = xgcv.foreground = face->foreground;
5258 else
5259 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5261 if (gc)
5262 XChangeGC (dpy, gc, mask, &xgcv);
5263 else
5265 gc = XCreateGC (dpy, window, mask, &xgcv);
5266 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5269 if (width < 0)
5270 width = FRAME_CURSOR_WIDTH (f);
5271 width = min (cursor_glyph->pixel_width, width);
5273 w->phys_cursor_width = width;
5274 x_clip_to_row (w, row, TEXT_AREA, gc);
5276 if (kind == BAR_CURSOR)
5277 mac_fill_rectangle (f, gc,
5278 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5279 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5280 width, row->height);
5281 else
5282 mac_fill_rectangle (f, gc,
5283 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5284 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5285 row->height - width),
5286 cursor_glyph->pixel_width,
5287 width);
5289 mac_reset_clip_rectangles (dpy, gc);
5294 /* RIF: Define cursor CURSOR on frame F. */
5296 static void
5297 mac_define_frame_cursor (f, cursor)
5298 struct frame *f;
5299 Cursor cursor;
5301 SetThemeCursor (cursor);
5305 /* RIF: Clear area on frame F. */
5307 static void
5308 mac_clear_frame_area (f, x, y, width, height)
5309 struct frame *f;
5310 int x, y, width, height;
5312 mac_clear_area (f, x, y, width, height);
5316 /* RIF: Draw cursor on window W. */
5318 static void
5319 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5320 struct window *w;
5321 struct glyph_row *glyph_row;
5322 int x, y;
5323 int cursor_type, cursor_width;
5324 int on_p, active_p;
5326 if (on_p)
5328 w->phys_cursor_type = cursor_type;
5329 w->phys_cursor_on_p = 1;
5331 if (glyph_row->exact_window_width_line_p
5332 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5334 glyph_row->cursor_in_fringe_p = 1;
5335 draw_fringe_bitmap (w, glyph_row, 0);
5337 else
5338 switch (cursor_type)
5340 case HOLLOW_BOX_CURSOR:
5341 x_draw_hollow_cursor (w, glyph_row);
5342 break;
5344 case FILLED_BOX_CURSOR:
5345 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5346 break;
5348 case BAR_CURSOR:
5349 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5350 break;
5352 case HBAR_CURSOR:
5353 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5354 break;
5356 case NO_CURSOR:
5357 w->phys_cursor_width = 0;
5358 break;
5360 default:
5361 abort ();
5367 /* Icons. */
5369 #if 0 /* MAC_TODO: no icon support yet. */
5371 x_bitmap_icon (f, icon)
5372 struct frame *f;
5373 Lisp_Object icon;
5375 HANDLE hicon;
5377 if (FRAME_W32_WINDOW (f) == 0)
5378 return 1;
5380 if (NILP (icon))
5381 hicon = LoadIcon (hinst, EMACS_CLASS);
5382 else if (STRINGP (icon))
5383 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5384 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5385 else if (SYMBOLP (icon))
5387 LPCTSTR name;
5389 if (EQ (icon, intern ("application")))
5390 name = (LPCTSTR) IDI_APPLICATION;
5391 else if (EQ (icon, intern ("hand")))
5392 name = (LPCTSTR) IDI_HAND;
5393 else if (EQ (icon, intern ("question")))
5394 name = (LPCTSTR) IDI_QUESTION;
5395 else if (EQ (icon, intern ("exclamation")))
5396 name = (LPCTSTR) IDI_EXCLAMATION;
5397 else if (EQ (icon, intern ("asterisk")))
5398 name = (LPCTSTR) IDI_ASTERISK;
5399 else if (EQ (icon, intern ("winlogo")))
5400 name = (LPCTSTR) IDI_WINLOGO;
5401 else
5402 return 1;
5404 hicon = LoadIcon (NULL, name);
5406 else
5407 return 1;
5409 if (hicon == NULL)
5410 return 1;
5412 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5413 (LPARAM) hicon);
5415 return 0;
5417 #endif /* MAC_TODO */
5419 /************************************************************************
5420 Handling X errors
5421 ************************************************************************/
5423 /* Display Error Handling functions not used on W32. Listing them here
5424 helps diff stay in step when comparing w32term.c with xterm.c.
5426 x_error_catcher (display, error)
5427 x_catch_errors (dpy)
5428 x_catch_errors_unwind (old_val)
5429 x_check_errors (dpy, format)
5430 x_had_errors_p (dpy)
5431 x_clear_errors (dpy)
5432 x_uncatch_errors (dpy, count)
5433 x_trace_wire ()
5434 x_connection_signal (signalnum)
5435 x_connection_closed (dpy, error_message)
5436 x_error_quitter (display, error)
5437 x_error_handler (display, error)
5438 x_io_error_quitter (display)
5443 /* Changing the font of the frame. */
5445 /* Give frame F the font named FONTNAME as its default font, and
5446 return the full name of that font. FONTNAME may be a wildcard
5447 pattern; in that case, we choose some font that fits the pattern.
5448 The return value shows which font we chose. */
5450 Lisp_Object
5451 x_new_font (f, fontname)
5452 struct frame *f;
5453 register char *fontname;
5455 struct font_info *fontp
5456 = FS_LOAD_FONT (f, 0, fontname, -1);
5458 if (!fontp)
5459 return Qnil;
5461 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5462 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5463 FRAME_FONTSET (f) = -1;
5465 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5466 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5467 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5469 compute_fringe_widths (f, 1);
5471 /* Compute the scroll bar width in character columns. */
5472 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5474 int wid = FRAME_COLUMN_WIDTH (f);
5475 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5476 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5478 else
5480 int wid = FRAME_COLUMN_WIDTH (f);
5481 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5484 /* Now make the frame display the given font. */
5485 if (FRAME_MAC_WINDOW (f) != 0)
5487 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5488 FRAME_FONT (f));
5489 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5490 FRAME_FONT (f));
5491 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5492 FRAME_FONT (f));
5494 /* Don't change the size of a tip frame; there's no point in
5495 doing it because it's done in Fx_show_tip, and it leads to
5496 problems because the tip frame has no widget. */
5497 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5498 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5501 return build_string (fontp->full_name);
5504 /* Give frame F the fontset named FONTSETNAME as its default font, and
5505 return the full name of that fontset. FONTSETNAME may be a wildcard
5506 pattern; in that case, we choose some fontset that fits the pattern.
5507 The return value shows which fontset we chose. */
5509 Lisp_Object
5510 x_new_fontset (f, fontsetname)
5511 struct frame *f;
5512 char *fontsetname;
5514 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5515 Lisp_Object result;
5517 if (fontset < 0)
5518 return Qnil;
5520 if (FRAME_FONTSET (f) == fontset)
5521 /* This fontset is already set in frame F. There's nothing more
5522 to do. */
5523 return fontset_name (fontset);
5525 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5527 if (!STRINGP (result))
5528 /* Can't load ASCII font. */
5529 return Qnil;
5531 /* Since x_new_font doesn't update any fontset information, do it now. */
5532 FRAME_FONTSET (f) = fontset;
5534 return build_string (fontsetname);
5538 /***********************************************************************
5539 TODO: W32 Input Methods
5540 ***********************************************************************/
5541 /* Listing missing functions from xterm.c helps diff stay in step.
5543 xim_destroy_callback (xim, client_data, call_data)
5544 xim_open_dpy (dpyinfo, resource_name)
5545 struct xim_inst_t
5546 xim_instantiate_callback (display, client_data, call_data)
5547 xim_initialize (dpyinfo, resource_name)
5548 xim_close_dpy (dpyinfo)
5553 void
5554 mac_get_window_bounds (f, inner, outer)
5555 struct frame *f;
5556 Rect *inner, *outer;
5558 #if TARGET_API_MAC_CARBON
5559 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5560 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5561 #else /* not TARGET_API_MAC_CARBON */
5562 RgnHandle region = NewRgn ();
5564 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5565 *inner = (*region)->rgnBBox;
5566 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5567 *outer = (*region)->rgnBBox;
5568 DisposeRgn (region);
5569 #endif /* not TARGET_API_MAC_CARBON */
5574 /* Calculate the absolute position in frame F
5575 from its current recorded position values and gravity. */
5577 void
5578 x_calc_absolute_position (f)
5579 struct frame *f;
5581 int width_diff = 0, height_diff = 0;
5582 int flags = f->size_hint_flags;
5583 Rect inner, outer;
5585 /* We have nothing to do if the current position
5586 is already for the top-left corner. */
5587 if (! ((flags & XNegative) || (flags & YNegative)))
5588 return;
5590 /* Find the offsets of the outside upper-left corner of
5591 the inner window, with respect to the outer window. */
5592 mac_get_window_bounds (f, &inner, &outer);
5594 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5595 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5597 /* Treat negative positions as relative to the leftmost bottommost
5598 position that fits on the screen. */
5599 if (flags & XNegative)
5600 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5601 - width_diff
5602 - FRAME_PIXEL_WIDTH (f)
5603 + f->left_pos);
5605 if (flags & YNegative)
5606 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5607 - height_diff
5608 - FRAME_PIXEL_HEIGHT (f)
5609 + f->top_pos);
5611 /* The left_pos and top_pos
5612 are now relative to the top and left screen edges,
5613 so the flags should correspond. */
5614 f->size_hint_flags &= ~ (XNegative | YNegative);
5617 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5618 to really change the position, and 0 when calling from
5619 x_make_frame_visible (in that case, XOFF and YOFF are the current
5620 position values). It is -1 when calling from x_set_frame_parameters,
5621 which means, do adjust for borders but don't change the gravity. */
5623 void
5624 x_set_offset (f, xoff, yoff, change_gravity)
5625 struct frame *f;
5626 register int xoff, yoff;
5627 int change_gravity;
5629 if (change_gravity > 0)
5631 f->top_pos = yoff;
5632 f->left_pos = xoff;
5633 f->size_hint_flags &= ~ (XNegative | YNegative);
5634 if (xoff < 0)
5635 f->size_hint_flags |= XNegative;
5636 if (yoff < 0)
5637 f->size_hint_flags |= YNegative;
5638 f->win_gravity = NorthWestGravity;
5640 x_calc_absolute_position (f);
5642 BLOCK_INPUT;
5643 x_wm_set_size_hint (f, (long) 0, 0);
5645 #if TARGET_API_MAC_CARBON
5646 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5647 /* If the title bar is completely outside the screen, adjust the
5648 position. */
5649 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5650 kWindowConstrainMoveRegardlessOfFit
5651 | kWindowConstrainAllowPartial, NULL, NULL);
5652 x_real_positions (f, &f->left_pos, &f->top_pos);
5653 #else
5655 Rect inner, outer, screen_rect, dummy;
5656 RgnHandle region = NewRgn ();
5658 mac_get_window_bounds (f, &inner, &outer);
5659 f->x_pixels_diff = inner.left - outer.left;
5660 f->y_pixels_diff = inner.top - outer.top;
5661 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5662 f->top_pos + f->y_pixels_diff, false);
5664 /* If the title bar is completely outside the screen, adjust the
5665 position. The variable `outer' holds the title bar rectangle.
5666 The variable `inner' holds slightly smaller one than `outer',
5667 so that the calculation of overlapping may not become too
5668 strict. */
5669 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5670 outer = (*region)->rgnBBox;
5671 DisposeRgn (region);
5672 inner = outer;
5673 InsetRect (&inner, 8, 8);
5674 screen_rect = qd.screenBits.bounds;
5675 screen_rect.top += GetMBarHeight ();
5677 if (!SectRect (&inner, &screen_rect, &dummy))
5679 if (inner.right <= screen_rect.left)
5680 f->left_pos = screen_rect.left;
5681 else if (inner.left >= screen_rect.right)
5682 f->left_pos = screen_rect.right - (outer.right - outer.left);
5684 if (inner.bottom <= screen_rect.top)
5685 f->top_pos = screen_rect.top;
5686 else if (inner.top >= screen_rect.bottom)
5687 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5689 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5690 f->top_pos + f->y_pixels_diff, false);
5693 #endif
5695 UNBLOCK_INPUT;
5698 /* Call this to change the size of frame F's x-window.
5699 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5700 for this size change and subsequent size changes.
5701 Otherwise we leave the window gravity unchanged. */
5703 void
5704 x_set_window_size (f, change_gravity, cols, rows)
5705 struct frame *f;
5706 int change_gravity;
5707 int cols, rows;
5709 int pixelwidth, pixelheight;
5711 BLOCK_INPUT;
5713 check_frame_size (f, &rows, &cols);
5714 f->scroll_bar_actual_width
5715 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5717 compute_fringe_widths (f, 0);
5719 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5720 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5722 f->win_gravity = NorthWestGravity;
5723 x_wm_set_size_hint (f, (long) 0, 0);
5725 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5726 #if TARGET_API_MAC_CARBON
5727 if (f->output_data.mac->hourglass_control)
5728 MoveControl (f->output_data.mac->hourglass_control,
5729 pixelwidth - HOURGLASS_WIDTH, 0);
5730 #endif
5732 /* Now, strictly speaking, we can't be sure that this is accurate,
5733 but the window manager will get around to dealing with the size
5734 change request eventually, and we'll hear how it went when the
5735 ConfigureNotify event gets here.
5737 We could just not bother storing any of this information here,
5738 and let the ConfigureNotify event set everything up, but that
5739 might be kind of confusing to the Lisp code, since size changes
5740 wouldn't be reported in the frame parameters until some random
5741 point in the future when the ConfigureNotify event arrives.
5743 We pass 1 for DELAY since we can't run Lisp code inside of
5744 a BLOCK_INPUT. */
5745 change_frame_size (f, rows, cols, 0, 1, 0);
5746 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5747 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5749 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5750 receive in the ConfigureNotify event; if we get what we asked
5751 for, then the event won't cause the screen to become garbaged, so
5752 we have to make sure to do it here. */
5753 SET_FRAME_GARBAGED (f);
5755 XFlush (FRAME_X_DISPLAY (f));
5757 /* If cursor was outside the new size, mark it as off. */
5758 mark_window_cursors_off (XWINDOW (f->root_window));
5760 /* Clear out any recollection of where the mouse highlighting was,
5761 since it might be in a place that's outside the new frame size.
5762 Actually checking whether it is outside is a pain in the neck,
5763 so don't try--just let the highlighting be done afresh with new size. */
5764 cancel_mouse_face (f);
5766 UNBLOCK_INPUT;
5769 /* Mouse warping. */
5771 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5773 void
5774 x_set_mouse_position (f, x, y)
5775 struct frame *f;
5776 int x, y;
5778 int pix_x, pix_y;
5780 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5781 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5783 if (pix_x < 0) pix_x = 0;
5784 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5786 if (pix_y < 0) pix_y = 0;
5787 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5789 x_set_mouse_pixel_position (f, pix_x, pix_y);
5792 void
5793 x_set_mouse_pixel_position (f, pix_x, pix_y)
5794 struct frame *f;
5795 int pix_x, pix_y;
5797 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5798 BLOCK_INPUT;
5800 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5801 0, 0, 0, 0, pix_x, pix_y);
5802 UNBLOCK_INPUT;
5803 #endif
5806 /* focus shifting, raising and lowering. */
5808 void
5809 x_focus_on_frame (f)
5810 struct frame *f;
5812 #if 0 /* This proves to be unpleasant. */
5813 x_raise_frame (f);
5814 #endif
5815 #if 0
5816 /* I don't think that the ICCCM allows programs to do things like this
5817 without the interaction of the window manager. Whatever you end up
5818 doing with this code, do it to x_unfocus_frame too. */
5819 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5820 RevertToPointerRoot, CurrentTime);
5821 #endif /* ! 0 */
5824 void
5825 x_unfocus_frame (f)
5826 struct frame *f;
5830 /* Raise frame F. */
5832 void
5833 x_raise_frame (f)
5834 struct frame *f;
5836 if (f->async_visible)
5838 BLOCK_INPUT;
5839 SelectWindow (FRAME_MAC_WINDOW (f));
5840 UNBLOCK_INPUT;
5844 /* Lower frame F. */
5846 void
5847 x_lower_frame (f)
5848 struct frame *f;
5850 if (f->async_visible)
5852 BLOCK_INPUT;
5853 SendBehind (FRAME_MAC_WINDOW (f), nil);
5854 UNBLOCK_INPUT;
5858 static void
5859 XTframe_raise_lower (f, raise_flag)
5860 FRAME_PTR f;
5861 int raise_flag;
5863 if (raise_flag)
5864 x_raise_frame (f);
5865 else
5866 x_lower_frame (f);
5869 /* Change of visibility. */
5871 static void
5872 mac_handle_visibility_change (f)
5873 struct frame *f;
5875 WindowPtr wp = FRAME_MAC_WINDOW (f);
5876 int visible = 0, iconified = 0;
5877 struct input_event buf;
5879 if (IsWindowVisible (wp))
5880 if (IsWindowCollapsed (wp))
5881 iconified = 1;
5882 else
5883 visible = 1;
5885 if (!f->async_visible && visible)
5887 if (f->iconified)
5889 /* wait_reading_process_output will notice this and update
5890 the frame's display structures. If we were made
5891 invisible, we should not set garbaged, because that stops
5892 redrawing on Update events. */
5893 SET_FRAME_GARBAGED (f);
5895 EVENT_INIT (buf);
5896 buf.kind = DEICONIFY_EVENT;
5897 XSETFRAME (buf.frame_or_window, f);
5898 kbd_buffer_store_event (&buf);
5900 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
5901 /* Force a redisplay sooner or later to update the
5902 frame titles in case this is the second frame. */
5903 record_asynch_buffer_change ();
5905 else if (f->async_visible && !visible)
5906 if (iconified)
5908 EVENT_INIT (buf);
5909 buf.kind = ICONIFY_EVENT;
5910 XSETFRAME (buf.frame_or_window, f);
5911 kbd_buffer_store_event (&buf);
5914 f->async_visible = visible;
5915 f->async_iconified = iconified;
5918 /* This tries to wait until the frame is really visible.
5919 However, if the window manager asks the user where to position
5920 the frame, this will return before the user finishes doing that.
5921 The frame will not actually be visible at that time,
5922 but it will become visible later when the window manager
5923 finishes with it. */
5925 void
5926 x_make_frame_visible (f)
5927 struct frame *f;
5929 Lisp_Object type;
5930 int original_top, original_left;
5932 BLOCK_INPUT;
5934 if (! FRAME_VISIBLE_P (f))
5936 /* We test FRAME_GARBAGED_P here to make sure we don't
5937 call x_set_offset a second time
5938 if we get to x_make_frame_visible a second time
5939 before the window gets really visible. */
5940 if (! FRAME_ICONIFIED_P (f)
5941 && ! f->output_data.mac->asked_for_visible)
5942 #if TARGET_API_MAC_CARBON
5943 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5945 struct frame *sf = SELECTED_FRAME ();
5946 if (!FRAME_MAC_P (sf))
5947 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5948 kWindowCenterOnMainScreen);
5949 else
5950 RepositionWindow (FRAME_MAC_WINDOW (f),
5951 FRAME_MAC_WINDOW (sf),
5952 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5953 kWindowCascadeStartAtParentWindowScreen
5954 #else
5955 kWindowCascadeOnParentWindowScreen
5956 #endif
5958 x_real_positions (f, &f->left_pos, &f->top_pos);
5960 else
5961 #endif
5962 x_set_offset (f, f->left_pos, f->top_pos, 0);
5964 f->output_data.mac->asked_for_visible = 1;
5966 SelectWindow (FRAME_MAC_WINDOW (f));
5967 CollapseWindow (FRAME_MAC_WINDOW (f), false);
5968 ShowWindow (FRAME_MAC_WINDOW (f));
5971 XFlush (FRAME_MAC_DISPLAY (f));
5973 /* Synchronize to ensure Emacs knows the frame is visible
5974 before we do anything else. We do this loop with input not blocked
5975 so that incoming events are handled. */
5977 Lisp_Object frame;
5978 int count;
5980 /* This must come after we set COUNT. */
5981 UNBLOCK_INPUT;
5983 XSETFRAME (frame, f);
5985 /* Wait until the frame is visible. Process X events until a
5986 MapNotify event has been seen, or until we think we won't get a
5987 MapNotify at all.. */
5988 for (count = input_signal_count + 10;
5989 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5991 /* Force processing of queued events. */
5992 x_sync (f);
5994 /* Machines that do polling rather than SIGIO have been
5995 observed to go into a busy-wait here. So we'll fake an
5996 alarm signal to let the handler know that there's something
5997 to be read. We used to raise a real alarm, but it seems
5998 that the handler isn't always enabled here. This is
5999 probably a bug. */
6000 if (input_polling_used ())
6002 /* It could be confusing if a real alarm arrives while
6003 processing the fake one. Turn it off and let the
6004 handler reset it. */
6005 extern void poll_for_input_1 P_ ((void));
6006 int old_poll_suppress_count = poll_suppress_count;
6007 poll_suppress_count = 1;
6008 poll_for_input_1 ();
6009 poll_suppress_count = old_poll_suppress_count;
6012 /* See if a MapNotify event has been processed. */
6013 FRAME_SAMPLE_VISIBILITY (f);
6018 /* Change from mapped state to withdrawn state. */
6020 /* Make the frame visible (mapped and not iconified). */
6022 void
6023 x_make_frame_invisible (f)
6024 struct frame *f;
6026 /* A deactivate event does not occur when the last visible frame is
6027 made invisible. So if we clear the highlight here, it will not
6028 be rehighlighted when it is made visible. */
6029 #if 0
6030 /* Don't keep the highlight on an invisible frame. */
6031 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6032 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6033 #endif
6035 BLOCK_INPUT;
6037 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6038 that the current position of the window is user-specified, rather than
6039 program-specified, so that when the window is mapped again, it will be
6040 placed at the same location, without forcing the user to position it
6041 by hand again (they have already done that once for this window.) */
6042 x_wm_set_size_hint (f, (long) 0, 1);
6044 HideWindow (FRAME_MAC_WINDOW (f));
6046 UNBLOCK_INPUT;
6048 #if !USE_CARBON_EVENTS
6049 mac_handle_visibility_change (f);
6050 #endif
6053 /* Change window state from mapped to iconified. */
6055 void
6056 x_iconify_frame (f)
6057 struct frame *f;
6059 OSErr err;
6061 /* A deactivate event does not occur when the last visible frame is
6062 iconified. So if we clear the highlight here, it will not be
6063 rehighlighted when it is deiconified. */
6064 #if 0
6065 /* Don't keep the highlight on an invisible frame. */
6066 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
6067 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
6068 #endif
6070 if (f->async_iconified)
6071 return;
6073 BLOCK_INPUT;
6075 FRAME_SAMPLE_VISIBILITY (f);
6077 if (! FRAME_VISIBLE_P (f))
6078 ShowWindow (FRAME_MAC_WINDOW (f));
6080 err = CollapseWindow (FRAME_MAC_WINDOW (f), true);
6082 UNBLOCK_INPUT;
6084 if (err != noErr)
6085 error ("Can't notify window manager of iconification");
6087 #if !USE_CARBON_EVENTS
6088 mac_handle_visibility_change (f);
6089 #endif
6093 /* Free X resources of frame F. */
6095 void
6096 x_free_frame_resources (f)
6097 struct frame *f;
6099 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6100 WindowPtr wp = FRAME_MAC_WINDOW (f);
6102 BLOCK_INPUT;
6104 if (wp != tip_window)
6105 remove_window_handler (wp);
6107 DisposeWindow (wp);
6108 if (wp == tip_window)
6109 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6110 closed' event. So we reset tip_window here. */
6111 tip_window = NULL;
6113 free_frame_menubar (f);
6115 if (FRAME_FACE_CACHE (f))
6116 free_frame_faces (f);
6118 x_free_gcs (f);
6120 if (FRAME_SIZE_HINTS (f))
6121 xfree (FRAME_SIZE_HINTS (f));
6123 xfree (f->output_data.mac);
6124 f->output_data.mac = NULL;
6126 if (f == dpyinfo->x_focus_frame)
6127 dpyinfo->x_focus_frame = 0;
6128 if (f == dpyinfo->x_focus_event_frame)
6129 dpyinfo->x_focus_event_frame = 0;
6130 if (f == dpyinfo->x_highlight_frame)
6131 dpyinfo->x_highlight_frame = 0;
6133 if (f == dpyinfo->mouse_face_mouse_frame)
6135 dpyinfo->mouse_face_beg_row
6136 = dpyinfo->mouse_face_beg_col = -1;
6137 dpyinfo->mouse_face_end_row
6138 = dpyinfo->mouse_face_end_col = -1;
6139 dpyinfo->mouse_face_window = Qnil;
6140 dpyinfo->mouse_face_deferred_gc = 0;
6141 dpyinfo->mouse_face_mouse_frame = 0;
6144 UNBLOCK_INPUT;
6148 /* Destroy the X window of frame F. */
6150 void
6151 x_destroy_window (f)
6152 struct frame *f;
6154 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6156 x_free_frame_resources (f);
6158 dpyinfo->reference_count--;
6162 /* Setting window manager hints. */
6164 /* Set the normal size hints for the window manager, for frame F.
6165 FLAGS is the flags word to use--or 0 meaning preserve the flags
6166 that the window now has.
6167 If USER_POSITION is nonzero, we set the USPosition
6168 flag (this is useful when FLAGS is 0). */
6169 void
6170 x_wm_set_size_hint (f, flags, user_position)
6171 struct frame *f;
6172 long flags;
6173 int user_position;
6175 int base_width, base_height, width_inc, height_inc;
6176 int min_rows = 0, min_cols = 0;
6177 XSizeHints *size_hints;
6179 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6180 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6181 width_inc = FRAME_COLUMN_WIDTH (f);
6182 height_inc = FRAME_LINE_HEIGHT (f);
6184 check_frame_size (f, &min_rows, &min_cols);
6186 size_hints = FRAME_SIZE_HINTS (f);
6187 if (size_hints == NULL)
6189 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6190 bzero (size_hints, sizeof (XSizeHints));
6193 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6194 size_hints->width_inc = width_inc;
6195 size_hints->height_inc = height_inc;
6196 size_hints->min_width = base_width + min_cols * width_inc;
6197 size_hints->min_height = base_height + min_rows * height_inc;
6198 size_hints->base_width = base_width;
6199 size_hints->base_height = base_height;
6201 if (flags)
6202 size_hints->flags = flags;
6203 else if (user_position)
6205 size_hints->flags &= ~ PPosition;
6206 size_hints->flags |= USPosition;
6210 #if 0 /* MAC_TODO: hide application instead of iconify? */
6211 /* Used for IconicState or NormalState */
6213 void
6214 x_wm_set_window_state (f, state)
6215 struct frame *f;
6216 int state;
6218 #ifdef USE_X_TOOLKIT
6219 Arg al[1];
6221 XtSetArg (al[0], XtNinitialState, state);
6222 XtSetValues (f->output_data.x->widget, al, 1);
6223 #else /* not USE_X_TOOLKIT */
6224 Window window = FRAME_X_WINDOW (f);
6226 f->output_data.x->wm_hints.flags |= StateHint;
6227 f->output_data.x->wm_hints.initial_state = state;
6229 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6230 #endif /* not USE_X_TOOLKIT */
6233 void
6234 x_wm_set_icon_pixmap (f, pixmap_id)
6235 struct frame *f;
6236 int pixmap_id;
6238 Pixmap icon_pixmap;
6240 #ifndef USE_X_TOOLKIT
6241 Window window = FRAME_X_WINDOW (f);
6242 #endif
6244 if (pixmap_id > 0)
6246 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6247 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6249 else
6251 /* It seems there is no way to turn off use of an icon pixmap.
6252 The following line does it, only if no icon has yet been created,
6253 for some window managers. But with mwm it crashes.
6254 Some people say it should clear the IconPixmapHint bit in this case,
6255 but that doesn't work, and the X consortium said it isn't the
6256 right thing at all. Since there is no way to win,
6257 best to explicitly give up. */
6258 #if 0
6259 f->output_data.x->wm_hints.icon_pixmap = None;
6260 #else
6261 return;
6262 #endif
6265 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6268 Arg al[1];
6269 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6270 XtSetValues (f->output_data.x->widget, al, 1);
6273 #else /* not USE_X_TOOLKIT */
6275 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6276 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6278 #endif /* not USE_X_TOOLKIT */
6281 #endif /* MAC_TODO */
6283 void
6284 x_wm_set_icon_position (f, icon_x, icon_y)
6285 struct frame *f;
6286 int icon_x, icon_y;
6288 #if 0 /* MAC_TODO: no icons on Mac */
6289 #ifdef USE_X_TOOLKIT
6290 Window window = XtWindow (f->output_data.x->widget);
6291 #else
6292 Window window = FRAME_X_WINDOW (f);
6293 #endif
6295 f->output_data.x->wm_hints.flags |= IconPositionHint;
6296 f->output_data.x->wm_hints.icon_x = icon_x;
6297 f->output_data.x->wm_hints.icon_y = icon_y;
6299 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6300 #endif /* MAC_TODO */
6304 /***********************************************************************
6305 XLFD Pattern Match
6306 ***********************************************************************/
6308 /* An XLFD pattern is divided into blocks delimited by '*'. This
6309 structure holds information for each block. */
6310 struct xlfdpat_block
6312 /* Length of the pattern string in this block. Non-zero except for
6313 the first and the last blocks. */
6314 int len;
6316 /* Pattern string except the last character in this block. The last
6317 character is replaced with NUL in order to use it as a
6318 sentinel. */
6319 unsigned char *pattern;
6321 /* Last character of the pattern string. Must not be '?'. */
6322 unsigned char last_char;
6324 /* One of the tables for the Boyer-Moore string search. It
6325 specifies the number of positions to proceed for each character
6326 with which the match fails. */
6327 int skip[256];
6329 /* The skip value for the last character in the above `skip' is
6330 assigned to `infinity' in order to simplify a loop condition.
6331 The original value is saved here. */
6332 int last_char_skip;
6335 struct xlfdpat
6337 /* Normalized pattern string. "Normalized" means that capital
6338 letters are lowered, blocks are not empty except the first and
6339 the last ones, and trailing '?'s in a block that is not the last
6340 one are moved to the next one. The last character in each block
6341 is replaced with NUL. */
6342 unsigned char *buf;
6344 /* Number of characters except '*'s and trailing '?'s in the
6345 normalized pattern string. */
6346 int nchars;
6348 /* Number of trailing '?'s in the normalized pattern string. */
6349 int trailing_anychars;
6351 /* Number of blocks and information for each block. The latter is
6352 NULL if the pattern is exact (no '*' or '?' in it). */
6353 int nblocks;
6354 struct xlfdpat_block *blocks;
6357 static void
6358 xlfdpat_destroy (pat)
6359 struct xlfdpat *pat;
6361 if (pat)
6363 if (pat->buf)
6365 if (pat->blocks)
6366 xfree (pat->blocks);
6367 xfree (pat->buf);
6369 xfree (pat);
6373 static struct xlfdpat *
6374 xlfdpat_create (pattern)
6375 char *pattern;
6377 struct xlfdpat *pat;
6378 int nblocks, i, skip;
6379 unsigned char last_char, *p, *q, *anychar_head;
6380 struct xlfdpat_block *blk;
6382 pat = xmalloc (sizeof (struct xlfdpat));
6383 if (pat == NULL)
6384 goto error;
6386 pat->buf = xmalloc (strlen (pattern) + 1);
6387 if (pat->buf == NULL)
6388 goto error;
6390 /* Normalize the pattern string and store it to `pat->buf'. */
6391 nblocks = 0;
6392 anychar_head = NULL;
6393 q = pat->buf;
6394 last_char = '\0';
6395 for (p = pattern; *p; p++)
6397 unsigned char c = *p;
6399 if (c == '*')
6400 if (last_char == '*')
6401 /* ...a** -> ...a* */
6402 continue;
6403 else
6405 if (last_char == '?')
6406 if (anychar_head > pat->buf && *(anychar_head - 1) == '*')
6407 /* ...*??* -> ...*?? */
6408 continue;
6409 else
6410 /* ...a??* -> ...a*?? */
6412 *anychar_head++ = '*';
6413 c = '?';
6415 nblocks++;
6417 else if (c == '?')
6419 if (last_char != '?')
6420 anychar_head = q;
6422 else
6423 /* On Mac OS X 10.3, tolower also converts non-ASCII
6424 characters for some locales. */
6425 if (isascii (c))
6426 c = tolower (c);
6428 *q++ = last_char = c;
6430 *q = '\0';
6431 nblocks++;
6432 pat->nblocks = nblocks;
6433 if (last_char != '?')
6434 pat->trailing_anychars = 0;
6435 else
6437 pat->trailing_anychars = q - anychar_head;
6438 q = anychar_head;
6440 pat->nchars = q - pat->buf - (nblocks - 1);
6442 if (anychar_head == NULL && nblocks == 1)
6444 /* The pattern is exact. */
6445 pat->blocks = NULL;
6446 return pat;
6449 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks);
6450 if (pat->blocks == NULL)
6451 goto error;
6453 /* Divide the normalized pattern into blocks. */
6454 p = pat->buf;
6455 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++)
6457 blk->pattern = p;
6458 while (*p != '*')
6459 p++;
6460 blk->len = p - blk->pattern;
6461 p++;
6463 blk->pattern = p;
6464 blk->len = q - blk->pattern;
6466 /* Setup a table for the Boyer-Moore string search. */
6467 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++)
6468 if (blk->len != 0)
6470 blk->last_char = blk->pattern[blk->len - 1];
6471 blk->pattern[blk->len - 1] = '\0';
6473 for (skip = 1; skip < blk->len; skip++)
6474 if (blk->pattern[blk->len - skip - 1] == '?')
6475 break;
6477 for (i = 0; i < 256; i++)
6478 blk->skip[i] = skip;
6480 p = blk->pattern + (blk->len - skip);
6481 while (--skip > 0)
6482 blk->skip[*p++] = skip;
6484 blk->last_char_skip = blk->skip[blk->last_char];
6487 return pat;
6489 error:
6490 xlfdpat_destroy (pat);
6491 return NULL;
6494 static INLINE int
6495 xlfdpat_exact_p (pat)
6496 struct xlfdpat *pat;
6498 return pat->blocks == NULL;
6501 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6502 that the pattern in *BLK matches with its prefix. Return NULL
6503 there is no such strings. STRING must be lowered in advance. */
6505 static char *
6506 xlfdpat_block_match_1 (blk, string, start_max)
6507 struct xlfdpat_block *blk;
6508 unsigned char *string;
6509 int start_max;
6511 int start, infinity;
6512 unsigned char *p, *s;
6514 xassert (blk->len > 0);
6515 xassert (start_max + blk->len <= strlen (string));
6516 xassert (blk->last_char != '?');
6518 /* See the comments in the function `boyer_moore' (search.c) for the
6519 use of `infinity'. */
6520 infinity = start_max + blk->len + 1;
6521 blk->skip[blk->last_char] = infinity;
6523 start = 0;
6526 /* Check the last character of the pattern. */
6527 s = string + blk->len - 1;
6530 start += blk->skip[*(s + start)];
6532 while (start <= start_max);
6534 if (start < infinity)
6535 /* Couldn't find the last character. */
6536 return NULL;
6538 /* No less than `infinity' means we could find the last
6539 character at `s[start - infinity]'. */
6540 start -= infinity;
6542 /* Check the remaining characters. We prefer making no-'?'
6543 cases faster because the use of '?' is really rare. */
6544 p = blk->pattern;
6545 s = string + start;
6548 while (*p++ == *s++)
6551 while (*(p - 1) == '?');
6553 if (*(p - 1) == '\0')
6554 /* Matched. */
6555 return string + start;
6557 /* Didn't match. */
6558 start += blk->last_char_skip;
6560 while (start <= start_max);
6562 return NULL;
6565 #define xlfdpat_block_match(b, s, m) \
6566 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6567 : xlfdpat_block_match_1 (b, s, m))
6569 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6570 matches with STRING. STRING must be lowered in advance. */
6572 static int
6573 xlfdpat_match (pat, string)
6574 struct xlfdpat *pat;
6575 unsigned char *string;
6577 int str_len, nblocks, i, start_max;
6578 struct xlfdpat_block *blk;
6579 unsigned char *s;
6581 xassert (pat->nblocks > 0);
6583 if (xlfdpat_exact_p (pat))
6584 return strcmp (pat->buf, string) == 0;
6586 /* The number of the characters in the string must not be smaller
6587 than that in the pattern. */
6588 str_len = strlen (string);
6589 if (str_len < pat->nchars + pat->trailing_anychars)
6590 return 0;
6592 /* Chop off the trailing '?'s. */
6593 str_len -= pat->trailing_anychars;
6595 /* The last block. When it is non-empty, it must match at the end
6596 of the string. */
6597 nblocks = pat->nblocks;
6598 blk = pat->blocks + (nblocks - 1);
6599 if (nblocks == 1)
6600 /* The last block is also the first one. */
6601 return (str_len == blk->len
6602 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0)));
6603 else if (blk->len != 0)
6604 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0))
6605 return 0;
6607 /* The first block. When it is non-empty, it must match at the
6608 beginning of the string. */
6609 blk = pat->blocks;
6610 if (blk->len != 0)
6612 s = xlfdpat_block_match (blk, string, 0);
6613 if (s == NULL)
6614 return 0;
6615 string = s + blk->len;
6618 /* The rest of the blocks. */
6619 start_max = str_len - pat->nchars;
6620 for (i = 1, blk++; i < nblocks - 1; i++, blk++)
6622 s = xlfdpat_block_match (blk, string, start_max);
6623 if (s == NULL)
6624 return 0;
6625 start_max -= s - string;
6626 string = s + blk->len;
6629 return 1;
6633 /***********************************************************************
6634 Fonts
6635 ***********************************************************************/
6637 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6639 struct font_info *
6640 x_get_font_info (f, font_idx)
6641 FRAME_PTR f;
6642 int font_idx;
6644 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6647 /* the global font name table */
6648 static char **font_name_table = NULL;
6649 static int font_name_table_size = 0;
6650 static int font_name_count = 0;
6652 /* Alist linking font family names to Font Manager font family
6653 references (which can also be used as QuickDraw font IDs). We use
6654 an alist because hash tables are not ready when the terminal frame
6655 for Mac OS Classic is created. */
6656 static Lisp_Object fm_font_family_alist;
6657 #if USE_ATSUI
6658 /* Hash table linking font family names to ATSU font IDs. */
6659 static Lisp_Object atsu_font_id_hash;
6660 #endif
6662 /* Alist linking character set strings to Mac text encoding and Emacs
6663 coding system. */
6664 static Lisp_Object Vmac_charset_info_alist;
6666 static Lisp_Object
6667 create_text_encoding_info_alist ()
6669 Lisp_Object result = Qnil, rest;
6671 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6673 Lisp_Object charset_info = XCAR (rest);
6674 Lisp_Object charset, coding_system, text_encoding;
6675 Lisp_Object existing_info;
6677 if (!(CONSP (charset_info)
6678 && STRINGP (charset = XCAR (charset_info))
6679 && CONSP (XCDR (charset_info))
6680 && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
6681 && CONSP (XCDR (XCDR (charset_info)))
6682 && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
6683 continue;
6685 existing_info = assq_no_quit (text_encoding, result);
6686 if (NILP (existing_info))
6687 result = Fcons (list3 (text_encoding, coding_system, charset),
6688 result);
6689 else
6690 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6691 XSETCDR (XCDR (existing_info),
6692 Fcons (charset, XCDR (XCDR (existing_info))));
6695 return result;
6699 static void
6700 decode_mac_font_name (name, size, coding_system)
6701 char *name;
6702 int size;
6703 Lisp_Object coding_system;
6705 struct coding_system coding;
6706 char *buf, *p;
6708 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system)))
6710 for (p = name; *p; p++)
6711 if (!isascii (*p) || iscntrl (*p))
6712 break;
6714 if (*p)
6716 setup_coding_system (coding_system, &coding);
6717 coding.src_multibyte = 0;
6718 coding.dst_multibyte = 1;
6719 coding.mode |= CODING_MODE_LAST_BLOCK;
6720 coding.composing = COMPOSITION_DISABLED;
6721 buf = (char *) alloca (size);
6723 decode_coding (&coding, name, buf, strlen (name), size - 1);
6724 bcopy (buf, name, coding.produced);
6725 name[coding.produced] = '\0';
6729 /* If there's just one occurrence of '-' in the family name, it is
6730 replaced with '_'. (More than one occurrence of '-' means a
6731 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6732 p = strchr (name, '-');
6733 if (p && strchr (p + 1, '-') == NULL)
6734 *p = '_';
6736 for (p = name; *p; p++)
6737 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6738 for some locales. */
6739 if (isascii (*p))
6740 *p = tolower (*p);
6744 static char *
6745 mac_to_x_fontname (name, size, style, charset)
6746 char *name;
6747 int size;
6748 Style style;
6749 char *charset;
6751 Str31 foundry, cs;
6752 Str255 family;
6753 char xf[256], *result;
6754 unsigned char *p;
6756 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6757 charset = cs;
6758 else
6760 strcpy(foundry, "Apple");
6761 strcpy(family, name);
6764 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6765 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
6766 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset);
6768 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6769 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6770 for (p = result; *p; p++)
6771 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6772 for some locales. */
6773 if (isascii (*p))
6774 *p = tolower (*p);
6775 return result;
6779 /* Parse fully-specified and instantiated X11 font spec XF, and store
6780 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6781 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6782 caller must allocate at least 256 and 32 bytes respectively. For
6783 ordinary Mac fonts, the value stored to FAMILY should just be their
6784 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6785 intlfonts collection contain their charset designation in their
6786 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6787 types of font names are handled accordingly. */
6789 const int kDefaultFontSize = 12;
6791 static int
6792 parse_x_font_name (xf, family, size, style, charset)
6793 char *xf, *family;
6794 int *size;
6795 Style *style;
6796 char *charset;
6798 Str31 foundry, weight;
6799 int point_size, avgwidth;
6800 char slant[2], *p;
6802 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6803 foundry, family, weight, slant, size,
6804 &point_size, &avgwidth, charset) != 8
6805 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6806 foundry, family, weight, slant, size,
6807 &point_size, &avgwidth, charset) != 8)
6808 return 0;
6810 if (*size == 0)
6812 if (point_size > 0)
6813 *size = point_size / 10;
6814 else if (avgwidth > 0)
6815 *size = avgwidth / 10;
6817 if (*size == 0)
6818 *size = kDefaultFontSize;
6820 *style = normal;
6821 if (strcmp (weight, "bold") == 0)
6822 *style |= bold;
6823 if (*slant == 'i')
6824 *style |= italic;
6826 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist)))
6828 int foundry_len = strlen (foundry), family_len = strlen (family);
6830 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255))
6832 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6833 but take overlap into account. */
6834 memmove (family + foundry_len + 1, family, family_len);
6835 memcpy (family, foundry, foundry_len);
6836 family[foundry_len] = '-';
6837 family[foundry_len + 1 + family_len] = '-';
6838 strcpy (family + foundry_len + 1 + family_len + 1, charset);
6840 else
6841 return 0;
6844 for (p = family; *p; p++)
6845 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6846 for some locales. */
6847 if (isascii (*p))
6848 *p = tolower (*p);
6850 return 1;
6854 static void
6855 add_font_name_table_entry (char *font_name)
6857 if (font_name_table_size == 0)
6859 font_name_table_size = 256;
6860 font_name_table = (char **)
6861 xmalloc (font_name_table_size * sizeof (char *));
6863 else if (font_name_count + 1 >= font_name_table_size)
6865 font_name_table_size *= 2;
6866 font_name_table = (char **)
6867 xrealloc (font_name_table,
6868 font_name_table_size * sizeof (char *));
6871 font_name_table[font_name_count++] = font_name;
6874 /* Sets up the table font_name_table to contain the list of all fonts
6875 in the system the first time the table is used so that the Resource
6876 Manager need not be accessed every time this information is
6877 needed. */
6879 static void
6880 init_font_name_table ()
6882 #if TARGET_API_MAC_CARBON
6883 FMFontFamilyIterator ffi;
6884 FMFontFamilyInstanceIterator ffii;
6885 FMFontFamily ff;
6886 Lisp_Object text_encoding_info_alist;
6887 struct gcpro gcpro1;
6889 text_encoding_info_alist = create_text_encoding_info_alist ();
6891 #if USE_ATSUI
6892 #if USE_CG_TEXT_DRAWING
6893 init_cg_text_anti_aliasing_threshold ();
6894 #endif
6895 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode),
6896 text_encoding_info_alist)))
6898 OSErr err;
6899 ItemCount nfonts, i;
6900 ATSUFontID *font_ids = NULL;
6901 Ptr name, prev_name = NULL;
6902 ByteCount name_len;
6904 atsu_font_id_hash =
6905 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
6906 make_float (DEFAULT_REHASH_SIZE),
6907 make_float (DEFAULT_REHASH_THRESHOLD),
6908 Qnil, Qnil, Qnil);;
6909 err = ATSUFontCount (&nfonts);
6910 if (err == noErr)
6911 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts);
6912 if (font_ids)
6913 err = ATSUGetFontIDs (font_ids, nfonts, NULL);
6914 if (err == noErr)
6915 for (i = 0; i < nfonts; i++)
6917 err = ATSUFindFontName (font_ids[i], kFontFamilyName,
6918 kFontMacintoshPlatform, kFontNoScript,
6919 kFontNoLanguage, 0, NULL, &name_len, NULL);
6920 if (err != noErr)
6921 continue;
6922 name = xmalloc (name_len + 1);
6923 if (name == NULL)
6924 continue;
6925 name[name_len] = '\0';
6926 err = ATSUFindFontName (font_ids[i], kFontFamilyName,
6927 kFontMacintoshPlatform, kFontNoScript,
6928 kFontNoLanguage, name_len, name,
6929 NULL, NULL);
6930 if (err == noErr)
6931 decode_mac_font_name (name, name_len + 1, Qnil);
6932 if (err == noErr
6933 && *name != '.'
6934 && (prev_name == NULL
6935 || strcmp (name, prev_name) != 0))
6937 static char *cs = "iso10646-1";
6939 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6940 normal, cs));
6941 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6942 italic, cs));
6943 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6944 bold, cs));
6945 add_font_name_table_entry (mac_to_x_fontname (name, 0,
6946 italic | bold, cs));
6947 Fputhash (make_unibyte_string (name, name_len),
6948 long_to_cons (font_ids[i]), atsu_font_id_hash);
6949 xfree (prev_name);
6950 prev_name = name;
6952 else
6953 xfree (name);
6955 if (prev_name)
6956 xfree (prev_name);
6957 if (font_ids)
6958 xfree (font_ids);
6960 #endif
6962 /* Create a dummy instance iterator here to avoid creating and
6963 destroying it in the loop. */
6964 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6965 return;
6966 /* Create an iterator to enumerate the font families. */
6967 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6968 != noErr)
6970 FMDisposeFontFamilyInstanceIterator (&ffii);
6971 return;
6974 GCPRO1 (text_encoding_info_alist);
6976 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6978 Str255 name;
6979 FMFont font;
6980 FMFontStyle style;
6981 FMFontSize size;
6982 TextEncoding encoding;
6983 TextEncodingBase sc;
6984 Lisp_Object text_encoding_info;
6986 if (FMGetFontFamilyName (ff, name) != noErr)
6987 break;
6988 p2cstr (name);
6989 if (*name == '.')
6990 continue;
6992 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6993 break;
6994 sc = GetTextEncodingBase (encoding);
6995 text_encoding_info = assq_no_quit (make_number (sc),
6996 text_encoding_info_alist);
6997 if (NILP (text_encoding_info))
6998 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
6999 text_encoding_info_alist);
7000 decode_mac_font_name (name, sizeof (name),
7001 XCAR (XCDR (text_encoding_info)));
7002 fm_font_family_alist = Fcons (Fcons (build_string (name),
7003 make_number (ff)),
7004 fm_font_family_alist);
7006 /* Point the instance iterator at the current font family. */
7007 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
7008 break;
7010 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
7011 == noErr)
7013 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7015 if (size > 0 || style == normal)
7016 for (; !NILP (rest); rest = XCDR (rest))
7018 char *cs = SDATA (XCAR (rest));
7020 if (size == 0)
7022 add_font_name_table_entry (mac_to_x_fontname (name, size,
7023 style, cs));
7024 add_font_name_table_entry (mac_to_x_fontname (name, size,
7025 italic, cs));
7026 add_font_name_table_entry (mac_to_x_fontname (name, size,
7027 bold, cs));
7028 add_font_name_table_entry (mac_to_x_fontname (name, size,
7029 italic | bold,
7030 cs));
7032 else
7034 add_font_name_table_entry (mac_to_x_fontname (name, size,
7035 style, cs));
7041 UNGCPRO;
7043 /* Dispose of the iterators. */
7044 FMDisposeFontFamilyIterator (&ffi);
7045 FMDisposeFontFamilyInstanceIterator (&ffii);
7046 #else /* !TARGET_API_MAC_CARBON */
7047 GrafPtr port;
7048 SInt16 fontnum, old_fontnum;
7049 int num_mac_fonts = CountResources('FOND');
7050 int i, j;
7051 Handle font_handle, font_handle_2;
7052 short id, scriptcode;
7053 ResType type;
7054 Str255 name;
7055 struct FontAssoc *fat;
7056 struct AsscEntry *assc_entry;
7057 Lisp_Object text_encoding_info_alist, text_encoding_info;
7058 struct gcpro gcpro1;
7060 GetPort (&port); /* save the current font number used */
7061 old_fontnum = port->txFont;
7063 text_encoding_info_alist = create_text_encoding_info_alist ();
7065 GCPRO1 (text_encoding_info_alist);
7067 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
7069 font_handle = GetIndResource ('FOND', i);
7070 if (!font_handle)
7071 continue;
7073 GetResInfo (font_handle, &id, &type, name);
7074 GetFNum (name, &fontnum);
7075 p2cstr (name);
7076 if (fontnum == 0)
7077 continue;
7079 TextFont (fontnum);
7080 scriptcode = FontToScript (fontnum);
7081 text_encoding_info = assq_no_quit (make_number (scriptcode),
7082 text_encoding_info_alist);
7083 if (NILP (text_encoding_info))
7084 text_encoding_info = assq_no_quit (make_number (smRoman),
7085 text_encoding_info_alist);
7086 decode_mac_font_name (name, sizeof (name),
7087 XCAR (XCDR (text_encoding_info)));
7088 fm_font_family_alist = Fcons (Fcons (build_string (name),
7089 make_number (fontnum)),
7090 fm_font_family_alist);
7093 HLock (font_handle);
7095 if (GetResourceSizeOnDisk (font_handle)
7096 >= sizeof (struct FamRec))
7098 fat = (struct FontAssoc *) (*font_handle
7099 + sizeof (struct FamRec));
7100 assc_entry
7101 = (struct AsscEntry *) (*font_handle
7102 + sizeof (struct FamRec)
7103 + sizeof (struct FontAssoc));
7105 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
7107 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
7109 for (; !NILP (rest); rest = XCDR (rest))
7111 char *cs = SDATA (XCAR (rest));
7113 add_font_name_table_entry (mac_to_x_fontname (name,
7114 assc_entry->fontSize,
7115 assc_entry->fontStyle,
7116 cs));
7121 HUnlock (font_handle);
7122 font_handle_2 = GetNextFOND (font_handle);
7123 ReleaseResource (font_handle);
7124 font_handle = font_handle_2;
7126 while (ResError () == noErr && font_handle);
7129 UNGCPRO;
7131 TextFont (old_fontnum);
7132 #endif /* !TARGET_API_MAC_CARBON */
7136 void
7137 mac_clear_font_name_table ()
7139 int i;
7141 for (i = 0; i < font_name_count; i++)
7142 xfree (font_name_table[i]);
7143 xfree (font_name_table);
7144 font_name_table = NULL;
7145 font_name_table_size = font_name_count = 0;
7146 fm_font_family_alist = Qnil;
7150 enum xlfd_scalable_field_index
7152 XLFD_SCL_PIXEL_SIZE,
7153 XLFD_SCL_POINT_SIZE,
7154 XLFD_SCL_AVGWIDTH,
7155 XLFD_SCL_LAST
7158 static int xlfd_scalable_fields[] =
7160 6, /* PIXEL_SIZE */
7161 7, /* POINT_SIZE */
7162 11, /* AVGWIDTH */
7166 static Lisp_Object
7167 mac_do_list_fonts (pattern, maxnames)
7168 char *pattern;
7169 int maxnames;
7171 int i, n_fonts = 0;
7172 Lisp_Object font_list = Qnil;
7173 struct xlfdpat *pat;
7174 char *scaled, *ptr;
7175 int scl_val[XLFD_SCL_LAST], *field, *val;
7176 int exact;
7178 if (font_name_table == NULL) /* Initialize when first used. */
7179 init_font_name_table ();
7181 for (i = 0; i < XLFD_SCL_LAST; i++)
7182 scl_val[i] = -1;
7184 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7185 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7186 fonts are scaled according to the specified size. */
7187 ptr = pattern;
7188 i = 0;
7189 field = xlfd_scalable_fields;
7190 val = scl_val;
7191 if (*ptr == '-')
7194 ptr++;
7195 if (i == *field)
7197 if ('0' <= *ptr && *ptr <= '9')
7199 *val = *ptr++ - '0';
7200 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
7201 *val = *val * 10 + *ptr++ - '0';
7202 if (*ptr != '-')
7203 *val = -1;
7205 field++;
7206 val++;
7208 ptr = strchr (ptr, '-');
7209 i++;
7211 while (ptr && i < 14);
7213 if (i == 14 && ptr == NULL)
7215 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
7216 scl_val[XLFD_SCL_PIXEL_SIZE] =
7217 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
7218 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
7219 : -1));
7220 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
7221 scl_val[XLFD_SCL_POINT_SIZE] =
7222 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7223 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
7224 : -1));
7225 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
7226 scl_val[XLFD_SCL_AVGWIDTH] =
7227 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
7228 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
7229 : -1));
7231 else
7232 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
7234 pat = xlfdpat_create (pattern);
7235 if (pat == NULL)
7236 return Qnil;
7238 exact = xlfdpat_exact_p (pat);
7240 for (i = 0; i < font_name_count; i++)
7242 if (xlfdpat_match (pat, font_name_table[i]))
7244 font_list = Fcons (build_string (font_name_table[i]), font_list);
7245 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
7246 break;
7248 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
7249 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
7251 int former_len = ptr - font_name_table[i];
7253 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
7254 if (scaled == NULL)
7255 continue;
7256 memcpy (scaled, font_name_table[i], former_len);
7257 sprintf (scaled + former_len,
7258 "-%d-%d-72-72-m-%d-%s",
7259 scl_val[XLFD_SCL_PIXEL_SIZE],
7260 scl_val[XLFD_SCL_POINT_SIZE],
7261 scl_val[XLFD_SCL_AVGWIDTH],
7262 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
7264 if (xlfdpat_match (pat, scaled))
7266 font_list = Fcons (build_string (scaled), font_list);
7267 xfree (scaled);
7268 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
7269 break;
7271 else
7272 xfree (scaled);
7276 xlfdpat_destroy (pat);
7278 return font_list;
7281 /* Return a list of names of available fonts matching PATTERN on frame F.
7283 Frame F null means we have not yet created any frame on Mac, and
7284 consult the first display in x_display_list. MAXNAMES sets a limit
7285 on how many fonts to match. */
7287 Lisp_Object
7288 x_list_fonts (f, pattern, size, maxnames)
7289 struct frame *f;
7290 Lisp_Object pattern;
7291 int size, maxnames;
7293 Lisp_Object list = Qnil, patterns, tem, key;
7294 struct mac_display_info *dpyinfo
7295 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
7297 xassert (size <= 0);
7299 patterns = Fassoc (pattern, Valternate_fontname_alist);
7300 if (NILP (patterns))
7301 patterns = Fcons (pattern, Qnil);
7303 for (; CONSP (patterns); patterns = XCDR (patterns))
7305 pattern = XCAR (patterns);
7307 if (!STRINGP (pattern))
7308 continue;
7310 tem = XCAR (XCDR (dpyinfo->name_list_element));
7311 key = Fcons (pattern, make_number (maxnames));
7313 list = Fassoc (key, tem);
7314 if (!NILP (list))
7316 list = Fcdr_safe (list);
7317 /* We have a cashed list. Don't have to get the list again. */
7318 goto label_cached;
7321 BLOCK_INPUT;
7322 list = mac_do_list_fonts (SDATA (pattern), maxnames);
7323 UNBLOCK_INPUT;
7325 /* MAC_TODO: add code for matching outline fonts here */
7327 /* Now store the result in the cache. */
7328 XSETCAR (XCDR (dpyinfo->name_list_element),
7329 Fcons (Fcons (key, list),
7330 XCAR (XCDR (dpyinfo->name_list_element))));
7332 label_cached:
7333 if (NILP (list)) continue; /* Try the remaining alternatives. */
7336 return list;
7340 #if GLYPH_DEBUG
7342 /* Check that FONT is valid on frame F. It is if it can be found in F's
7343 font table. */
7345 static void
7346 x_check_font (f, font)
7347 struct frame *f;
7348 XFontStruct *font;
7350 int i;
7351 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7353 xassert (font != NULL);
7355 for (i = 0; i < dpyinfo->n_fonts; i++)
7356 if (dpyinfo->font_table[i].name
7357 && font == dpyinfo->font_table[i].font)
7358 break;
7360 xassert (i < dpyinfo->n_fonts);
7363 #endif /* GLYPH_DEBUG != 0 */
7365 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7366 Note: There are (broken) X fonts out there with invalid XFontStruct
7367 min_bounds contents. For example, handa@etl.go.jp reports that
7368 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7369 have font->min_bounds.width == 0. */
7371 static INLINE void
7372 x_font_min_bounds (font, w, h)
7373 MacFontStruct *font;
7374 int *w, *h;
7376 *h = FONT_HEIGHT (font);
7377 *w = font->min_bounds.width;
7381 /* Compute the smallest character width and smallest font height over
7382 all fonts available on frame F. Set the members smallest_char_width
7383 and smallest_font_height in F's x_display_info structure to
7384 the values computed. Value is non-zero if smallest_font_height or
7385 smallest_char_width become smaller than they were before. */
7387 static int
7388 x_compute_min_glyph_bounds (f)
7389 struct frame *f;
7391 int i;
7392 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7393 MacFontStruct *font;
7394 int old_width = dpyinfo->smallest_char_width;
7395 int old_height = dpyinfo->smallest_font_height;
7397 dpyinfo->smallest_font_height = 100000;
7398 dpyinfo->smallest_char_width = 100000;
7400 for (i = 0; i < dpyinfo->n_fonts; ++i)
7401 if (dpyinfo->font_table[i].name)
7403 struct font_info *fontp = dpyinfo->font_table + i;
7404 int w, h;
7406 font = (MacFontStruct *) fontp->font;
7407 xassert (font != (MacFontStruct *) ~0);
7408 x_font_min_bounds (font, &w, &h);
7410 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
7411 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
7414 xassert (dpyinfo->smallest_char_width > 0
7415 && dpyinfo->smallest_font_height > 0);
7417 return (dpyinfo->n_fonts == 1
7418 || dpyinfo->smallest_char_width < old_width
7419 || dpyinfo->smallest_font_height < old_height);
7423 /* Determine whether given string is a fully-specified XLFD: all 14
7424 fields are present, none is '*'. */
7426 static int
7427 is_fully_specified_xlfd (char *p)
7429 int i;
7430 char *q;
7432 if (*p != '-')
7433 return 0;
7435 for (i = 0; i < 13; i++)
7437 q = strchr (p + 1, '-');
7438 if (q == NULL)
7439 return 0;
7440 if (q - p == 2 && *(p + 1) == '*')
7441 return 0;
7442 p = q;
7445 if (strchr (p + 1, '-') != NULL)
7446 return 0;
7448 if (*(p + 1) == '*' && *(p + 2) == '\0')
7449 return 0;
7451 return 1;
7455 /* XLoadQueryFont creates and returns an internal representation for a
7456 font in a MacFontStruct struct. There is really no concept
7457 corresponding to "loading" a font on the Mac. But we check its
7458 existence and find the font number and all other information for it
7459 and store them in the returned MacFontStruct. */
7461 static MacFontStruct *
7462 XLoadQueryFont (Display *dpy, char *fontname)
7464 int size;
7465 char *name;
7466 Str255 family;
7467 Str31 charset;
7468 SInt16 fontnum;
7469 #if USE_ATSUI
7470 static ATSUFontID font_id;
7471 ATSUStyle mac_style = NULL;
7472 #endif
7473 Style fontface;
7474 #if TARGET_API_MAC_CARBON
7475 TextEncoding encoding;
7476 int scriptcode;
7477 #else
7478 short scriptcode;
7479 #endif
7480 MacFontStruct *font;
7481 XCharStruct *space_bounds = NULL, *pcm;
7483 if (is_fully_specified_xlfd (fontname))
7484 name = fontname;
7485 else
7487 Lisp_Object matched_fonts;
7489 matched_fonts = mac_do_list_fonts (fontname, 1);
7490 if (NILP (matched_fonts))
7491 return NULL;
7492 name = SDATA (XCAR (matched_fonts));
7495 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0)
7496 return NULL;
7498 #if USE_ATSUI
7499 if (strcmp (charset, "iso10646-1") == 0) /* XXX */
7501 OSErr err;
7502 ATSUAttributeTag tags[] = {kATSUFontTag, kATSUSizeTag,
7503 kATSUQDBoldfaceTag, kATSUQDItalicTag};
7504 ByteCount sizes[] = {sizeof (ATSUFontID), sizeof (Fixed),
7505 sizeof (Boolean), sizeof (Boolean)};
7506 static Fixed size_fixed;
7507 static Boolean bold_p, italic_p;
7508 ATSUAttributeValuePtr values[] = {&font_id, &size_fixed,
7509 &bold_p, &italic_p};
7510 ATSUFontFeatureType types[] = {kAllTypographicFeaturesType};
7511 ATSUFontFeatureSelector selectors[] = {kAllTypeFeaturesOffSelector};
7512 Lisp_Object font_id_cons;
7514 font_id_cons = Fgethash (make_unibyte_string (family, strlen (family)),
7515 atsu_font_id_hash, Qnil);
7516 if (NILP (font_id_cons))
7517 return NULL;
7518 font_id = cons_to_long (font_id_cons);
7519 size_fixed = Long2Fix (size);
7520 bold_p = (fontface & bold) != 0;
7521 italic_p = (fontface & italic) != 0;
7522 err = ATSUCreateStyle (&mac_style);
7523 if (err != noErr)
7524 return NULL;
7525 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]),
7526 types, selectors);
7527 if (err != noErr)
7528 return NULL;
7529 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]),
7530 tags, sizes, values);
7531 fontnum = -1;
7532 scriptcode = kTextEncodingMacUnicode;
7534 else
7535 #endif
7537 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist);
7539 if (NILP (tmp))
7540 return NULL;
7541 fontnum = XINT (XCDR (tmp));
7542 #if TARGET_API_MAC_CARBON
7543 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
7544 return NULL;
7545 scriptcode = GetTextEncodingBase (encoding);
7546 #else
7547 scriptcode = FontToScript (fontnum);
7548 #endif
7551 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7553 font->mac_fontnum = fontnum;
7554 font->mac_fontsize = size;
7555 font->mac_fontface = fontface;
7556 font->mac_scriptcode = scriptcode;
7557 #if USE_ATSUI
7558 font->mac_style = mac_style;
7559 #if USE_CG_TEXT_DRAWING
7560 font->cg_font = NULL;
7561 font->cg_glyphs = NULL;
7562 #endif
7563 #endif
7565 /* Apple Japanese (SJIS) font is listed as both
7566 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7567 (Roman script) in init_font_name_table (). The latter should be
7568 treated as a one-byte font. */
7569 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7570 font->mac_scriptcode = smRoman;
7572 font->full_name = mac_to_x_fontname (family, size, fontface, charset);
7574 #if USE_ATSUI
7575 if (font->mac_style)
7577 OSErr err;
7578 UniChar c;
7580 font->min_byte1 = 0;
7581 font->max_byte1 = 0xff;
7582 font->min_char_or_byte2 = 0;
7583 font->max_char_or_byte2 = 0xff;
7585 font->bounds.rows = xmalloc (sizeof (XCharStructRow *) * 0x100);
7586 if (font->bounds.rows == NULL)
7588 mac_unload_font (&one_mac_display_info, font);
7589 return NULL;
7591 bzero (font->bounds.rows, sizeof (XCharStructRow *) * 0x100);
7592 font->bounds.rows[0] = xmalloc (sizeof (XCharStructRow));
7593 if (font->bounds.rows[0] == NULL)
7595 mac_unload_font (&one_mac_display_info, font);
7596 return NULL;
7598 bzero (font->bounds.rows[0], sizeof (XCharStructRow));
7600 #if USE_CG_TEXT_DRAWING
7602 FMFontFamily font_family;
7603 FMFontStyle style;
7604 ATSFontRef ats_font;
7606 err = FMGetFontFamilyInstanceFromFont (font_id, &font_family, &style);
7607 if (err == noErr)
7608 err = FMGetFontFromFontFamilyInstance (font_family, fontface,
7609 &font_id, &style);
7610 /* Use CG text drawing if italic/bold is not synthesized. */
7611 if (err == noErr && style == fontface)
7613 ats_font = FMGetATSFontRefFromFont (font_id);
7614 font->cg_font = CGFontCreateWithPlatformFont (&ats_font);
7618 if (font->cg_font)
7619 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100);
7620 if (font->cg_glyphs)
7621 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100);
7622 #endif
7623 space_bounds = font->bounds.rows[0]->per_char + 0x20;
7624 err = mac_query_char_extents (font->mac_style, 0x20,
7625 &font->ascent, &font->descent,
7626 space_bounds,
7627 #if USE_CG_TEXT_DRAWING
7628 (font->cg_glyphs ? font->cg_glyphs + 0x20
7629 : NULL)
7630 #else
7631 NULL
7632 #endif
7634 if (err != noErr)
7636 mac_unload_font (&one_mac_display_info, font);
7637 return NULL;
7639 XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], 0x20);
7641 pcm = font->bounds.rows[0]->per_char;
7642 for (c = 0x21; c <= 0xff; c++)
7644 if (c == 0xad)
7645 /* Soft hyphen is not supported in ATSUI. */
7646 continue;
7647 else if (c == 0x7f)
7649 c = 0x9f;
7650 continue;
7653 mac_query_char_extents (font->mac_style, c, NULL, NULL, pcm + c,
7654 #if USE_CG_TEXT_DRAWING
7655 (font->cg_glyphs ? font->cg_glyphs + c
7656 : NULL)
7657 #else
7658 NULL
7659 #endif
7661 XCHARSTRUCTROW_SET_CHAR_VALID (font->bounds.rows[0], c);
7663 #if USE_CG_TEXT_DRAWING
7664 if (font->cg_glyphs && font->cg_glyphs[c] == 0)
7666 /* Don't use CG text drawing if font substitution occurs in
7667 ASCII or Latin-1 characters. */
7668 CGFontRelease (font->cg_font);
7669 font->cg_font = NULL;
7670 xfree (font->cg_glyphs);
7671 font->cg_glyphs = NULL;
7673 #endif
7676 else
7677 #endif
7679 GrafPtr port;
7680 SInt16 old_fontnum, old_fontsize;
7681 Style old_fontface;
7682 FontInfo the_fontinfo;
7683 int is_two_byte_font;
7685 /* Save the current font number used. */
7686 GetPort (&port);
7687 #if TARGET_API_MAC_CARBON
7688 old_fontnum = GetPortTextFont (port);
7689 old_fontsize = GetPortTextSize (port);
7690 old_fontface = GetPortTextFace (port);
7691 #else
7692 old_fontnum = port->txFont;
7693 old_fontsize = port->txSize;
7694 old_fontface = port->txFace;
7695 #endif
7697 TextFont (fontnum);
7698 TextSize (size);
7699 TextFace (fontface);
7701 GetFontInfo (&the_fontinfo);
7703 font->ascent = the_fontinfo.ascent;
7704 font->descent = the_fontinfo.descent;
7706 is_two_byte_font = (font->mac_scriptcode == smJapanese
7707 || font->mac_scriptcode == smTradChinese
7708 || font->mac_scriptcode == smSimpChinese
7709 || font->mac_scriptcode == smKorean);
7711 if (is_two_byte_font)
7713 int char_width;
7715 font->min_byte1 = 0xa1;
7716 font->max_byte1 = 0xfe;
7717 font->min_char_or_byte2 = 0xa1;
7718 font->max_char_or_byte2 = 0xfe;
7720 /* Use the width of an "ideographic space" of that font
7721 because the_fontinfo.widMax returns the wrong width for
7722 some fonts. */
7723 switch (font->mac_scriptcode)
7725 case smJapanese:
7726 font->min_byte1 = 0x81;
7727 font->max_byte1 = 0xfc;
7728 font->min_char_or_byte2 = 0x40;
7729 font->max_char_or_byte2 = 0xfc;
7730 char_width = StringWidth("\p\x81\x40");
7731 break;
7732 case smTradChinese:
7733 font->min_char_or_byte2 = 0x40;
7734 char_width = StringWidth("\p\xa1\x40");
7735 break;
7736 case smSimpChinese:
7737 char_width = StringWidth("\p\xa1\xa1");
7738 break;
7739 case smKorean:
7740 char_width = StringWidth("\p\xa1\xa1");
7741 break;
7744 font->bounds.per_char = NULL;
7746 if (fontface & italic)
7747 font->max_bounds.rbearing = char_width + 1;
7748 else
7749 font->max_bounds.rbearing = char_width;
7750 font->max_bounds.lbearing = 0;
7751 font->max_bounds.width = char_width;
7752 font->max_bounds.ascent = the_fontinfo.ascent;
7753 font->max_bounds.descent = the_fontinfo.descent;
7755 font->min_bounds = font->max_bounds;
7757 else
7759 int c;
7761 font->min_byte1 = font->max_byte1 = 0;
7762 font->min_char_or_byte2 = 0x20;
7763 font->max_char_or_byte2 = 0xff;
7765 font->bounds.per_char =
7766 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7767 if (font->bounds.per_char == NULL)
7769 mac_unload_font (&one_mac_display_info, font);
7770 return NULL;
7772 bzero (font->bounds.per_char,
7773 sizeof (XCharStruct) * (0xff - 0x20 + 1));
7775 space_bounds = font->bounds.per_char;
7776 mac_query_char_extents (NULL, 0x20, &font->ascent, &font->descent,
7777 space_bounds, NULL);
7779 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++)
7780 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL);
7783 /* Restore previous font number, size and face. */
7784 TextFont (old_fontnum);
7785 TextSize (old_fontsize);
7786 TextFace (old_fontface);
7789 if (space_bounds)
7791 int c;
7793 font->min_bounds = font->max_bounds = *space_bounds;
7794 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++)
7795 if (pcm->width > 0)
7797 font->min_bounds.lbearing = min (font->min_bounds.lbearing,
7798 pcm->lbearing);
7799 font->min_bounds.rbearing = min (font->min_bounds.rbearing,
7800 pcm->rbearing);
7801 font->min_bounds.width = min (font->min_bounds.width,
7802 pcm->width);
7803 font->min_bounds.ascent = min (font->min_bounds.ascent,
7804 pcm->ascent);
7806 font->max_bounds.lbearing = max (font->max_bounds.lbearing,
7807 pcm->lbearing);
7808 font->max_bounds.rbearing = max (font->max_bounds.rbearing,
7809 pcm->rbearing);
7810 font->max_bounds.width = max (font->max_bounds.width,
7811 pcm->width);
7812 font->max_bounds.ascent = max (font->max_bounds.ascent,
7813 pcm->ascent);
7815 if (
7816 #if USE_ATSUI
7817 font->mac_style == NULL &&
7818 #endif
7819 font->max_bounds.width == font->min_bounds.width
7820 && font->min_bounds.lbearing >= 0
7821 && font->max_bounds.rbearing <= font->max_bounds.width)
7823 /* Fixed width and no overhangs. */
7824 xfree (font->bounds.per_char);
7825 font->bounds.per_char = NULL;
7829 #if !defined (MAC_OS8) || USE_ATSUI
7830 /* AppKit and WebKit do some adjustment to the heights of Courier,
7831 Helvetica, and Times. This only works on the environments where
7832 the XDrawImageString counterpart is never used. */
7833 if (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0
7834 || strcmp (family, "times") == 0)
7835 font->ascent += (font->ascent + font->descent) * .15 + 0.5;
7836 #endif
7838 return font;
7842 void
7843 mac_unload_font (dpyinfo, font)
7844 struct mac_display_info *dpyinfo;
7845 XFontStruct *font;
7847 xfree (font->full_name);
7848 #if USE_ATSUI
7849 if (font->mac_style)
7851 int i;
7853 for (i = font->min_byte1; i <= font->max_byte1; i++)
7854 if (font->bounds.rows[i])
7855 xfree (font->bounds.rows[i]);
7856 xfree (font->bounds.rows);
7857 ATSUDisposeStyle (font->mac_style);
7859 else
7860 #endif
7861 if (font->bounds.per_char)
7862 xfree (font->bounds.per_char);
7863 #if USE_CG_TEXT_DRAWING
7864 if (font->cg_font)
7865 CGFontRelease (font->cg_font);
7866 if (font->cg_glyphs)
7867 xfree (font->cg_glyphs);
7868 #endif
7869 xfree (font);
7873 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7874 pointer to the structure font_info while allocating it dynamically.
7875 If SIZE is 0, load any size of font.
7876 If loading is failed, return NULL. */
7878 struct font_info *
7879 x_load_font (f, fontname, size)
7880 struct frame *f;
7881 register char *fontname;
7882 int size;
7884 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7885 Lisp_Object font_names;
7887 /* Get a list of all the fonts that match this name. Once we
7888 have a list of matching fonts, we compare them against the fonts
7889 we already have by comparing names. */
7890 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7892 if (!NILP (font_names))
7894 Lisp_Object tail;
7895 int i;
7897 for (i = 0; i < dpyinfo->n_fonts; i++)
7898 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7899 if (dpyinfo->font_table[i].name
7900 && (!strcmp (dpyinfo->font_table[i].name,
7901 SDATA (XCAR (tail)))
7902 || !strcmp (dpyinfo->font_table[i].full_name,
7903 SDATA (XCAR (tail)))))
7904 return (dpyinfo->font_table + i);
7906 else
7907 return NULL;
7909 /* Load the font and add it to the table. */
7911 char *full_name;
7912 struct MacFontStruct *font;
7913 struct font_info *fontp;
7914 unsigned long value;
7915 int i;
7917 fontname = (char *) SDATA (XCAR (font_names));
7919 BLOCK_INPUT;
7920 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
7921 UNBLOCK_INPUT;
7922 if (!font)
7923 return NULL;
7925 /* Find a free slot in the font table. */
7926 for (i = 0; i < dpyinfo->n_fonts; ++i)
7927 if (dpyinfo->font_table[i].name == NULL)
7928 break;
7930 /* If no free slot found, maybe enlarge the font table. */
7931 if (i == dpyinfo->n_fonts
7932 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7934 int sz;
7935 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7936 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
7937 dpyinfo->font_table
7938 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
7941 fontp = dpyinfo->font_table + i;
7942 if (i == dpyinfo->n_fonts)
7943 ++dpyinfo->n_fonts;
7945 /* Now fill in the slots of *FONTP. */
7946 BLOCK_INPUT;
7947 bzero (fontp, sizeof (*fontp));
7948 fontp->font = font;
7949 fontp->font_idx = i;
7950 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
7951 bcopy (fontname, fontp->name, strlen (fontname) + 1);
7953 if (font->min_bounds.width == font->max_bounds.width)
7955 /* Fixed width font. */
7956 fontp->average_width = fontp->space_width = font->min_bounds.width;
7958 else
7960 XChar2b char2b;
7961 XCharStruct *pcm;
7963 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
7964 pcm = mac_per_char_metric (font, &char2b, 0);
7965 if (pcm)
7966 fontp->space_width = pcm->width;
7967 else
7968 fontp->space_width = FONT_WIDTH (font);
7970 if (pcm)
7972 int width = pcm->width;
7973 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
7974 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
7975 width += pcm->width;
7976 fontp->average_width = width / 95;
7978 else
7979 fontp->average_width = FONT_WIDTH (font);
7982 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
7983 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
7985 fontp->size = font->max_bounds.width;
7986 fontp->height = FONT_HEIGHT (font);
7988 /* For some font, ascent and descent in max_bounds field is
7989 larger than the above value. */
7990 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
7991 if (max_height > fontp->height)
7992 fontp->height = max_height;
7995 /* The slot `encoding' specifies how to map a character
7996 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7997 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7998 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7999 2:0xA020..0xFF7F). For the moment, we don't know which charset
8000 uses this font. So, we set information in fontp->encoding[1]
8001 which is never used by any charset. If mapping can't be
8002 decided, set FONT_ENCODING_NOT_DECIDED. */
8003 if (font->mac_scriptcode == smJapanese)
8004 fontp->encoding[1] = 4;
8005 else
8007 fontp->encoding[1]
8008 = (font->max_byte1 == 0
8009 /* 1-byte font */
8010 ? (font->min_char_or_byte2 < 0x80
8011 ? (font->max_char_or_byte2 < 0x80
8012 ? 0 /* 0x20..0x7F */
8013 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
8014 : 1) /* 0xA0..0xFF */
8015 /* 2-byte font */
8016 : (font->min_byte1 < 0x80
8017 ? (font->max_byte1 < 0x80
8018 ? (font->min_char_or_byte2 < 0x80
8019 ? (font->max_char_or_byte2 < 0x80
8020 ? 0 /* 0x2020..0x7F7F */
8021 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
8022 : 3) /* 0x20A0..0x7FFF */
8023 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
8024 : (font->min_char_or_byte2 < 0x80
8025 ? (font->max_char_or_byte2 < 0x80
8026 ? 2 /* 0xA020..0xFF7F */
8027 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
8028 : 1))); /* 0xA0A0..0xFFFF */
8031 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8032 fontp->baseline_offset
8033 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
8034 ? (long) value : 0);
8035 fontp->relative_compose
8036 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
8037 ? (long) value : 0);
8038 fontp->default_ascent
8039 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
8040 ? (long) value : 0);
8041 #else
8042 fontp->baseline_offset = 0;
8043 fontp->relative_compose = 0;
8044 fontp->default_ascent = 0;
8045 #endif
8047 /* Set global flag fonts_changed_p to non-zero if the font loaded
8048 has a character with a smaller width than any other character
8049 before, or if the font loaded has a smaller height than any
8050 other font loaded before. If this happens, it will make a
8051 glyph matrix reallocation necessary. */
8052 fonts_changed_p |= x_compute_min_glyph_bounds (f);
8053 UNBLOCK_INPUT;
8054 return fontp;
8059 /* Return a pointer to struct font_info of a font named FONTNAME for
8060 frame F. If no such font is loaded, return NULL. */
8062 struct font_info *
8063 x_query_font (f, fontname)
8064 struct frame *f;
8065 register char *fontname;
8067 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8068 int i;
8070 for (i = 0; i < dpyinfo->n_fonts; i++)
8071 if (dpyinfo->font_table[i].name
8072 && (!strcmp (dpyinfo->font_table[i].name, fontname)
8073 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
8074 return (dpyinfo->font_table + i);
8075 return NULL;
8079 /* Find a CCL program for a font specified by FONTP, and set the member
8080 `encoder' of the structure. */
8082 void
8083 x_find_ccl_program (fontp)
8084 struct font_info *fontp;
8086 Lisp_Object list, elt;
8088 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
8090 elt = XCAR (list);
8091 if (CONSP (elt)
8092 && STRINGP (XCAR (elt))
8093 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
8094 >= 0))
8095 break;
8097 if (! NILP (list))
8099 struct ccl_program *ccl
8100 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
8102 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
8103 xfree (ccl);
8104 else
8105 fontp->font_encoder = ccl;
8111 /* The Mac Event loop code */
8113 #if !TARGET_API_MAC_CARBON
8114 #include <Events.h>
8115 #include <Quickdraw.h>
8116 #include <Balloons.h>
8117 #include <Devices.h>
8118 #include <Fonts.h>
8119 #include <Gestalt.h>
8120 #include <Menus.h>
8121 #include <Processes.h>
8122 #include <Sound.h>
8123 #include <ToolUtils.h>
8124 #include <TextUtils.h>
8125 #include <Dialogs.h>
8126 #include <Script.h>
8127 #include <Types.h>
8128 #include <Resources.h>
8130 #if __MWERKS__
8131 #include <unix.h>
8132 #endif
8133 #endif /* ! TARGET_API_MAC_CARBON */
8135 #define M_APPLE 128
8136 #define I_ABOUT 1
8138 #define WINDOW_RESOURCE 128
8139 #define TERM_WINDOW_RESOURCE 129
8141 #define DEFAULT_NUM_COLS 80
8143 #define MIN_DOC_SIZE 64
8144 #define MAX_DOC_SIZE 32767
8146 #define EXTRA_STACK_ALLOC (256 * 1024)
8148 #define ARGV_STRING_LIST_ID 129
8149 #define ABOUT_ALERT_ID 128
8150 #define RAM_TOO_LARGE_ALERT_ID 129
8152 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8153 Lisp_Object Qreverse;
8156 /* Modifier associated with the control key, or nil to ignore. */
8157 Lisp_Object Vmac_control_modifier;
8159 /* Modifier associated with the option key, or nil to ignore. */
8160 Lisp_Object Vmac_option_modifier;
8162 /* Modifier associated with the command key, or nil to ignore. */
8163 Lisp_Object Vmac_command_modifier;
8165 /* Modifier associated with the function key, or nil to ignore. */
8166 Lisp_Object Vmac_function_modifier;
8168 /* True if the option and command modifiers should be used to emulate
8169 a three button mouse */
8170 Lisp_Object Vmac_emulate_three_button_mouse;
8172 #if USE_CARBON_EVENTS
8173 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8174 mouse-2, instead of mouse-3. */
8175 int mac_wheel_button_is_mouse_2;
8177 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8178 for processing before Emacs sees it. */
8179 int mac_pass_command_to_system;
8181 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8182 for processing before Emacs sees it. */
8183 int mac_pass_control_to_system;
8184 #endif
8186 /* Points to the variable `inev' in the function XTread_socket. It is
8187 used for passing an input event to the function back from
8188 Carbon/Apple event handlers. */
8189 static struct input_event *read_socket_inev = NULL;
8191 Point saved_menu_event_location;
8193 /* Apple Events */
8194 #if USE_CARBON_EVENTS
8195 static Lisp_Object Qhicommand;
8196 #endif
8197 extern int mac_ready_for_apple_events;
8198 extern Lisp_Object Qundefined;
8199 extern void init_apple_event_handler P_ ((void));
8200 extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID,
8201 Lisp_Object *, Lisp_Object *,
8202 Lisp_Object *));
8203 extern OSErr init_coercion_handler P_ ((void));
8205 #if TARGET_API_MAC_CARBON
8206 /* Drag and Drop */
8207 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
8208 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
8209 static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
8210 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
8211 #endif
8213 #if USE_CARBON_EVENTS
8214 #ifdef MAC_OSX
8215 extern void init_service_handler ();
8216 static Lisp_Object Qservices, Qpaste, Qperform;
8217 #endif
8218 /* Window Event Handler */
8219 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
8220 EventRef, void *);
8221 #endif
8222 OSErr install_window_handler (WindowPtr);
8224 extern void init_emacs_passwd_dir ();
8225 extern int emacs_main (int, char **, char **);
8227 extern void initialize_applescript();
8228 extern void terminate_applescript();
8230 static unsigned int
8231 #if USE_CARBON_EVENTS
8232 mac_to_emacs_modifiers (UInt32 mods)
8233 #else
8234 mac_to_emacs_modifiers (EventModifiers mods)
8235 #endif
8237 unsigned int result = 0;
8238 if (mods & shiftKey)
8239 result |= shift_modifier;
8241 /* Deactivated to simplify configuration:
8242 if Vmac_option_modifier is non-NIL, we fully process the Option
8243 key. Otherwise, we only process it if an additional Ctrl or Command
8244 is pressed. That way the system may convert the character to a
8245 composed one.
8246 if ((mods & optionKey) &&
8247 (( !NILP(Vmac_option_modifier) ||
8248 ((mods & cmdKey) || (mods & controlKey))))) */
8250 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
8251 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
8252 if (INTEGERP(val))
8253 result |= XUINT(val);
8255 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) {
8256 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value);
8257 if (INTEGERP(val))
8258 result |= XUINT(val);
8260 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) {
8261 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value);
8262 if (INTEGERP(val))
8263 result |= XUINT(val);
8266 #ifdef MAC_OSX
8267 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) {
8268 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value);
8269 if (INTEGERP(val))
8270 result |= XUINT(val);
8272 #endif
8274 return result;
8277 static int
8278 mac_get_emulated_btn ( UInt32 modifiers )
8280 int result = 0;
8281 if (!NILP (Vmac_emulate_three_button_mouse)) {
8282 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
8283 if (modifiers & cmdKey)
8284 result = cmdIs3 ? 2 : 1;
8285 else if (modifiers & optionKey)
8286 result = cmdIs3 ? 1 : 2;
8288 return result;
8291 #if USE_CARBON_EVENTS
8292 /* Obtains the event modifiers from the event ref and then calls
8293 mac_to_emacs_modifiers. */
8294 static UInt32
8295 mac_event_to_emacs_modifiers (EventRef eventRef)
8297 UInt32 mods = 0;
8298 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
8299 sizeof (UInt32), NULL, &mods);
8300 if (!NILP (Vmac_emulate_three_button_mouse) &&
8301 GetEventClass(eventRef) == kEventClassMouse)
8303 mods &= ~(optionKey | cmdKey);
8305 return mac_to_emacs_modifiers (mods);
8308 /* Given an event ref, return the code to use for the mouse button
8309 code in the emacs input_event. */
8310 static int
8311 mac_get_mouse_btn (EventRef ref)
8313 EventMouseButton result = kEventMouseButtonPrimary;
8314 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
8315 sizeof (EventMouseButton), NULL, &result);
8316 switch (result)
8318 case kEventMouseButtonPrimary:
8319 if (NILP (Vmac_emulate_three_button_mouse))
8320 return 0;
8321 else {
8322 UInt32 mods = 0;
8323 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
8324 sizeof (UInt32), NULL, &mods);
8325 return mac_get_emulated_btn(mods);
8327 case kEventMouseButtonSecondary:
8328 return mac_wheel_button_is_mouse_2 ? 2 : 1;
8329 case kEventMouseButtonTertiary:
8330 case 4: /* 4 is the number for the mouse wheel button */
8331 return mac_wheel_button_is_mouse_2 ? 1 : 2;
8332 default:
8333 return 0;
8337 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8338 events. However the click of the mouse wheel is not converted to a
8339 mouseDown or mouseUp event. Likewise for dead key down events.
8340 This calls ConvertEventRef, but then checks to see if it is a mouse
8341 up/down, or a dead key down carbon event that has not been
8342 converted, and if so, converts it by hand (to be picked up in the
8343 XTread_socket loop). */
8344 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
8346 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
8348 if (result)
8349 return result;
8351 switch (GetEventClass (eventRef))
8353 case kEventClassMouse:
8354 switch (GetEventKind (eventRef))
8356 case kEventMouseDown:
8357 eventRec->what = mouseDown;
8358 result = 1;
8359 break;
8361 case kEventMouseUp:
8362 eventRec->what = mouseUp;
8363 result = 1;
8364 break;
8366 default:
8367 break;
8369 break;
8371 case kEventClassKeyboard:
8372 switch (GetEventKind (eventRef))
8374 case kEventRawKeyDown:
8376 unsigned char char_codes;
8377 UInt32 key_code;
8379 eventRec->what = keyDown;
8380 GetEventParameter (eventRef, kEventParamKeyMacCharCodes, typeChar,
8381 NULL, sizeof (char), NULL, &char_codes);
8382 GetEventParameter (eventRef, kEventParamKeyCode, typeUInt32,
8383 NULL, sizeof (UInt32), NULL, &key_code);
8384 eventRec->message = char_codes | ((key_code & 0xff) << 8);
8385 result = 1;
8387 break;
8389 default:
8390 break;
8392 break;
8394 default:
8395 break;
8398 if (result)
8400 /* Need where and when. */
8401 UInt32 mods;
8403 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
8404 NULL, sizeof (Point), NULL, &eventRec->where);
8405 /* Use two step process because new event modifiers are 32-bit
8406 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8407 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
8408 NULL, sizeof (UInt32), NULL, &mods);
8409 eventRec->modifiers = mods;
8411 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
8414 return result;
8417 #endif
8419 static void
8420 do_get_menus (void)
8422 Handle menubar_handle;
8423 MenuHandle menu_handle;
8425 menubar_handle = GetNewMBar (128);
8426 if(menubar_handle == NULL)
8427 abort ();
8428 SetMenuBar (menubar_handle);
8429 DrawMenuBar ();
8431 #if !TARGET_API_MAC_CARBON
8432 menu_handle = GetMenuHandle (M_APPLE);
8433 if(menu_handle != NULL)
8434 AppendResMenu (menu_handle,'DRVR');
8435 else
8436 abort ();
8437 #endif
8441 static void
8442 do_init_managers (void)
8444 #if !TARGET_API_MAC_CARBON
8445 InitGraf (&qd.thePort);
8446 InitFonts ();
8447 FlushEvents (everyEvent, 0);
8448 InitWindows ();
8449 InitMenus ();
8450 TEInit ();
8451 InitDialogs (NULL);
8452 #endif /* !TARGET_API_MAC_CARBON */
8453 InitCursor ();
8455 #if !TARGET_API_MAC_CARBON
8456 /* set up some extra stack space for use by emacs */
8457 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
8459 /* MaxApplZone must be called for AppleScript to execute more
8460 complicated scripts */
8461 MaxApplZone ();
8462 MoreMasters ();
8463 #endif /* !TARGET_API_MAC_CARBON */
8466 static void
8467 do_check_ram_size (void)
8469 SInt32 physical_ram_size, logical_ram_size;
8471 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
8472 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
8473 || physical_ram_size > (1 << VALBITS)
8474 || logical_ram_size > (1 << VALBITS))
8476 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
8477 exit (1);
8481 static void
8482 do_window_update (WindowPtr win)
8484 struct frame *f = mac_window_to_frame (win);
8486 BeginUpdate (win);
8488 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8489 below. */
8490 if (win != tip_window)
8492 if (f->async_visible == 0)
8494 /* Update events may occur when a frame gets iconified. */
8495 #if 0
8496 f->async_visible = 1;
8497 f->async_iconified = 0;
8498 SET_FRAME_GARBAGED (f);
8499 #endif
8501 else
8503 Rect r;
8504 #if TARGET_API_MAC_CARBON
8505 RgnHandle region = NewRgn ();
8507 GetPortVisibleRegion (GetWindowPort (win), region);
8508 GetRegionBounds (region, &r);
8509 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
8510 UpdateControls (win, region);
8511 DisposeRgn (region);
8512 #else
8513 r = (*win->visRgn)->rgnBBox;
8514 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
8515 UpdateControls (win, win->visRgn);
8516 #endif
8520 EndUpdate (win);
8523 static int
8524 is_emacs_window (WindowPtr win)
8526 Lisp_Object tail, frame;
8528 if (!win)
8529 return 0;
8531 FOR_EACH_FRAME (tail, frame)
8532 if (FRAME_MAC_P (XFRAME (frame)))
8533 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
8534 return 1;
8536 return 0;
8539 static void
8540 do_app_resume ()
8542 /* Window-activate events will do the job. */
8545 static void
8546 do_app_suspend ()
8548 /* Window-deactivate events will do the job. */
8552 static void
8553 do_apple_menu (SInt16 menu_item)
8555 #if !TARGET_API_MAC_CARBON
8556 Str255 item_name;
8557 SInt16 da_driver_refnum;
8559 if (menu_item == I_ABOUT)
8560 NoteAlert (ABOUT_ALERT_ID, NULL);
8561 else
8563 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
8564 da_driver_refnum = OpenDeskAcc (item_name);
8566 #endif /* !TARGET_API_MAC_CARBON */
8569 void
8570 do_menu_choice (SInt32 menu_choice)
8572 SInt16 menu_id, menu_item;
8574 menu_id = HiWord (menu_choice);
8575 menu_item = LoWord (menu_choice);
8577 switch (menu_id)
8579 case 0:
8580 break;
8582 case M_APPLE:
8583 do_apple_menu (menu_item);
8584 break;
8586 default:
8588 struct frame *f = mac_focus_frame (&one_mac_display_info);
8589 MenuHandle menu = GetMenuHandle (menu_id);
8590 if (menu)
8592 UInt32 refcon;
8594 GetMenuItemRefCon (menu, menu_item, &refcon);
8595 menubar_selection_callback (f, refcon);
8600 HiliteMenu (0);
8604 /* Handle drags in size box. Based on code contributed by Ben
8605 Mesander and IM - Window Manager A. */
8607 static void
8608 do_grow_window (WindowPtr w, EventRecord *e)
8610 Rect limit_rect;
8611 int rows, columns, width, height;
8612 struct frame *f = mac_window_to_frame (w);
8613 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
8614 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
8615 #if TARGET_API_MAC_CARBON
8616 Rect new_rect;
8617 #else
8618 long grow_size;
8619 #endif
8621 if (size_hints->flags & PMinSize)
8623 min_width = size_hints->min_width;
8624 min_height = size_hints->min_height;
8626 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
8628 #if TARGET_API_MAC_CARBON
8629 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
8630 return;
8631 height = new_rect.bottom - new_rect.top;
8632 width = new_rect.right - new_rect.left;
8633 #else
8634 grow_size = GrowWindow (w, e->where, &limit_rect);
8635 /* see if it really changed size */
8636 if (grow_size == 0)
8637 return;
8638 height = HiWord (grow_size);
8639 width = LoWord (grow_size);
8640 #endif
8642 if (width != FRAME_PIXEL_WIDTH (f)
8643 || height != FRAME_PIXEL_HEIGHT (f))
8645 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
8646 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
8648 x_set_window_size (f, 0, columns, rows);
8653 /* Handle clicks in zoom box. Calculation of "standard state" based
8654 on code in IM - Window Manager A and code contributed by Ben
8655 Mesander. The standard state of an Emacs window is 80-characters
8656 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8658 static void
8659 do_zoom_window (WindowPtr w, int zoom_in_or_out)
8661 GrafPtr save_port;
8662 Rect zoom_rect, port_rect;
8663 Point top_left;
8664 int w_title_height, columns, rows, width, height;
8665 struct frame *f = mac_window_to_frame (w);
8666 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
8668 #if TARGET_API_MAC_CARBON
8670 Point standard_size;
8672 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
8673 standard_size.v = dpyinfo->height;
8675 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
8676 zoom_in_or_out = inZoomIn;
8677 else
8679 /* Adjust the standard size according to character boundaries. */
8681 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
8682 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
8683 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
8684 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
8685 GetWindowBounds (w, kWindowContentRgn, &port_rect);
8686 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
8687 && port_rect.left == zoom_rect.left
8688 && port_rect.top == zoom_rect.top)
8689 zoom_in_or_out = inZoomIn;
8690 else
8691 zoom_in_or_out = inZoomOut;
8694 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
8696 #else /* not TARGET_API_MAC_CARBON */
8697 GetPort (&save_port);
8699 SetPortWindowPort (w);
8701 /* Clear window to avoid flicker. */
8702 EraseRect (&(w->portRect));
8703 if (zoom_in_or_out == inZoomOut)
8705 SetPt (&top_left, w->portRect.left, w->portRect.top);
8706 LocalToGlobal (&top_left);
8708 /* calculate height of window's title bar */
8709 w_title_height = top_left.v - 1
8710 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
8712 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8713 zoom_rect = qd.screenBits.bounds;
8714 zoom_rect.top += w_title_height;
8715 InsetRect (&zoom_rect, 8, 4); /* not too tight */
8717 zoom_rect.right = zoom_rect.left
8718 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
8720 /* Adjust the standard size according to character boundaries. */
8721 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
8722 zoom_rect.bottom =
8723 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
8725 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
8726 = zoom_rect;
8729 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
8731 SetPort (save_port);
8732 #endif /* not TARGET_API_MAC_CARBON */
8734 /* retrieve window size and update application values */
8735 #if TARGET_API_MAC_CARBON
8736 GetWindowPortBounds (w, &port_rect);
8737 #else
8738 port_rect = w->portRect;
8739 #endif
8740 height = port_rect.bottom - port_rect.top;
8741 width = port_rect.right - port_rect.left;
8743 if (width != FRAME_PIXEL_WIDTH (f)
8744 || height != FRAME_PIXEL_HEIGHT (f))
8746 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
8747 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
8749 change_frame_size (f, rows, columns, 0, 1, 0);
8750 SET_FRAME_GARBAGED (f);
8751 cancel_mouse_face (f);
8753 FRAME_PIXEL_WIDTH (f) = width;
8754 FRAME_PIXEL_HEIGHT (f) = height;
8756 x_real_positions (f, &f->left_pos, &f->top_pos);
8759 OSErr
8760 mac_store_apple_event (class, id, desc)
8761 Lisp_Object class, id;
8762 const AEDesc *desc;
8764 OSErr err = noErr;
8765 struct input_event buf;
8766 AEDesc *desc_copy;
8768 desc_copy = xmalloc (sizeof (AEDesc));
8769 if (desc_copy == NULL)
8770 err = memFullErr;
8771 else
8772 err = AEDuplicateDesc (desc, desc_copy);
8773 if (err == noErr)
8775 EVENT_INIT (buf);
8777 buf.kind = MAC_APPLE_EVENT;
8778 buf.x = class;
8779 buf.y = id;
8780 buf.code = (int)desc_copy;
8781 XSETFRAME (buf.frame_or_window,
8782 mac_focus_frame (&one_mac_display_info));
8783 buf.arg = Qnil;
8784 kbd_buffer_store_event (&buf);
8787 return err;
8790 Lisp_Object
8791 mac_make_lispy_event_code (code)
8792 int code;
8794 AEDesc *desc = (AEDesc *)code;
8795 Lisp_Object obj;
8797 obj = mac_aedesc_to_lisp (desc);
8798 AEDisposeDesc (desc);
8799 xfree (desc);
8801 return obj;
8804 #if USE_CARBON_EVENTS
8805 static pascal OSStatus
8806 mac_handle_command_event (next_handler, event, data)
8807 EventHandlerCallRef next_handler;
8808 EventRef event;
8809 void *data;
8811 OSStatus result;
8812 OSErr err;
8813 HICommand command;
8814 Lisp_Object class_key, id_key, binding;
8816 result = CallNextEventHandler (next_handler, event);
8817 if (result != eventNotHandledErr)
8818 return result;
8820 GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL,
8821 sizeof (HICommand), NULL, &command);
8823 if (command.commandID == 0)
8824 return eventNotHandledErr;
8826 /* A HICommand event is mapped to an Apple event whose event class
8827 symbol is `hicommand' and event ID is its command ID. */
8828 class_key = Qhicommand;
8829 mac_find_apple_event_spec (0, command.commandID,
8830 &class_key, &id_key, &binding);
8831 if (!NILP (binding) && !EQ (binding, Qundefined))
8832 if (INTEGERP (binding))
8833 return XINT (binding);
8834 else
8836 AppleEvent apple_event;
8837 UInt32 modifiers;
8838 static EventParamName names[] = {kEventParamDirectObject,
8839 kEventParamKeyModifiers};
8840 static EventParamType types[] = {typeHICommand,
8841 typeUInt32};
8842 err = create_apple_event_from_event_ref (event, 2, names, types,
8843 &apple_event);
8844 if (err == noErr)
8846 err = mac_store_apple_event (class_key, id_key, &apple_event);
8847 AEDisposeDesc (&apple_event);
8849 if (err == noErr)
8850 return noErr;
8853 return eventNotHandledErr;
8856 static OSErr
8857 init_command_handler ()
8859 OSErr err = noErr;
8860 EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
8861 static EventHandlerUPP handle_command_eventUPP = NULL;
8863 if (handle_command_eventUPP == NULL)
8864 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
8865 return InstallApplicationEventHandler (handle_command_eventUPP,
8866 GetEventTypeCount (specs), specs,
8867 NULL, NULL);
8870 static pascal OSStatus
8871 mac_handle_window_event (next_handler, event, data)
8872 EventHandlerCallRef next_handler;
8873 EventRef event;
8874 void *data;
8876 WindowPtr wp;
8877 OSStatus result;
8878 UInt32 attributes;
8879 XSizeHints *size_hints;
8881 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
8882 NULL, sizeof (WindowPtr), NULL, &wp);
8884 switch (GetEventKind (event))
8886 case kEventWindowUpdate:
8887 result = CallNextEventHandler (next_handler, event);
8888 if (result != eventNotHandledErr)
8889 return result;
8891 do_window_update (wp);
8892 return noErr;
8894 case kEventWindowBoundsChanging:
8895 result = CallNextEventHandler (next_handler, event);
8896 if (result != eventNotHandledErr)
8897 return result;
8899 GetEventParameter (event, kEventParamAttributes, typeUInt32,
8900 NULL, sizeof (UInt32), NULL, &attributes);
8901 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
8902 if ((attributes & kWindowBoundsChangeUserResize)
8903 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
8904 == (PResizeInc | PBaseSize | PMinSize)))
8906 Rect bounds;
8907 int width, height;
8909 GetEventParameter (event, kEventParamCurrentBounds,
8910 typeQDRectangle,
8911 NULL, sizeof (Rect), NULL, &bounds);
8912 width = bounds.right - bounds.left;
8913 height = bounds.bottom - bounds.top;
8915 if (width < size_hints->min_width)
8916 width = size_hints->min_width;
8917 else
8918 width = size_hints->base_width
8919 + (int) ((width - size_hints->base_width)
8920 / (float) size_hints->width_inc + .5)
8921 * size_hints->width_inc;
8923 if (height < size_hints->min_height)
8924 height = size_hints->min_height;
8925 else
8926 height = size_hints->base_height
8927 + (int) ((height - size_hints->base_height)
8928 / (float) size_hints->height_inc + .5)
8929 * size_hints->height_inc;
8931 bounds.right = bounds.left + width;
8932 bounds.bottom = bounds.top + height;
8933 SetEventParameter (event, kEventParamCurrentBounds,
8934 typeQDRectangle, sizeof (Rect), &bounds);
8935 return noErr;
8937 break;
8939 case kEventWindowShown:
8940 case kEventWindowHidden:
8941 case kEventWindowExpanded:
8942 case kEventWindowCollapsed:
8943 result = CallNextEventHandler (next_handler, event);
8945 mac_handle_visibility_change (mac_window_to_frame (wp));
8946 return noErr;
8948 break;
8951 return eventNotHandledErr;
8954 static pascal OSStatus
8955 mac_handle_mouse_event (next_handler, event, data)
8956 EventHandlerCallRef next_handler;
8957 EventRef event;
8958 void *data;
8960 OSStatus result;
8962 switch (GetEventKind (event))
8964 case kEventMouseWheelMoved:
8966 WindowPtr wp;
8967 struct frame *f;
8968 EventMouseWheelAxis axis;
8969 SInt32 delta;
8970 Point point;
8972 result = CallNextEventHandler (next_handler, event);
8973 if (result != eventNotHandledErr || read_socket_inev == NULL)
8974 return result;
8976 GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
8977 NULL, sizeof (WindowRef), NULL, &wp);
8978 f = mac_window_to_frame (wp);
8979 if (f != mac_focus_frame (&one_mac_display_info))
8980 break;
8982 GetEventParameter (event, kEventParamMouseWheelAxis,
8983 typeMouseWheelAxis, NULL,
8984 sizeof (EventMouseWheelAxis), NULL, &axis);
8985 if (axis != kEventMouseWheelAxisY)
8986 break;
8988 GetEventParameter (event, kEventParamMouseWheelDelta, typeSInt32,
8989 NULL, sizeof (SInt32), NULL, &delta);
8990 GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
8991 NULL, sizeof (Point), NULL, &point);
8992 read_socket_inev->kind = WHEEL_EVENT;
8993 read_socket_inev->code = 0;
8994 read_socket_inev->modifiers =
8995 (mac_event_to_emacs_modifiers (event)
8996 | ((delta < 0) ? down_modifier : up_modifier));
8997 SetPortWindowPort (wp);
8998 GlobalToLocal (&point);
8999 XSETINT (read_socket_inev->x, point.h);
9000 XSETINT (read_socket_inev->y, point.v);
9001 XSETFRAME (read_socket_inev->frame_or_window, f);
9003 return noErr;
9005 break;
9007 default:
9008 break;
9011 return eventNotHandledErr;
9014 #ifdef MAC_OSX
9015 OSErr
9016 mac_store_services_event (event)
9017 EventRef event;
9019 OSErr err;
9020 AppleEvent apple_event;
9021 Lisp_Object id_key;
9023 switch (GetEventKind (event))
9025 case kEventServicePaste:
9026 id_key = Qpaste;
9027 err = create_apple_event_from_event_ref (event, 0, NULL, NULL,
9028 &apple_event);
9029 break;
9031 case kEventServicePerform:
9033 static EventParamName names[] = {kEventParamServiceMessageName,
9034 kEventParamServiceUserData};
9035 static EventParamType types[] = {typeCFStringRef,
9036 typeCFStringRef};
9038 id_key = Qperform;
9039 err = create_apple_event_from_event_ref (event, 2, names, types,
9040 &apple_event);
9042 break;
9044 default:
9045 abort ();
9048 if (err == noErr)
9050 err = mac_store_apple_event (Qservices, id_key, &apple_event);
9051 AEDisposeDesc (&apple_event);
9054 return err;
9056 #endif /* MAC_OSX */
9057 #endif /* USE_CARBON_EVENTS */
9060 OSErr
9061 install_window_handler (window)
9062 WindowPtr window;
9064 OSErr err = noErr;
9065 #if USE_CARBON_EVENTS
9066 EventTypeSpec specs_window[] =
9067 {{kEventClassWindow, kEventWindowUpdate},
9068 {kEventClassWindow, kEventWindowBoundsChanging},
9069 {kEventClassWindow, kEventWindowShown},
9070 {kEventClassWindow, kEventWindowHidden},
9071 {kEventClassWindow, kEventWindowExpanded},
9072 {kEventClassWindow, kEventWindowCollapsed}};
9073 EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
9074 static EventHandlerUPP handle_window_eventUPP = NULL;
9075 static EventHandlerUPP handle_mouse_eventUPP = NULL;
9077 if (handle_window_eventUPP == NULL)
9078 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
9079 if (handle_mouse_eventUPP == NULL)
9080 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
9081 err = InstallWindowEventHandler (window, handle_window_eventUPP,
9082 GetEventTypeCount (specs_window),
9083 specs_window, NULL, NULL);
9084 if (err == noErr)
9085 err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
9086 GetEventTypeCount (specs_mouse),
9087 specs_mouse, NULL, NULL);
9088 #endif
9089 #if TARGET_API_MAC_CARBON
9090 if (mac_do_track_dragUPP == NULL)
9091 mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
9092 if (mac_do_receive_dragUPP == NULL)
9093 mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
9095 if (err == noErr)
9096 err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
9097 if (err == noErr)
9098 err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
9099 #endif
9100 return err;
9103 void
9104 remove_window_handler (window)
9105 WindowPtr window;
9107 #if TARGET_API_MAC_CARBON
9108 if (mac_do_track_dragUPP)
9109 RemoveTrackingHandler (mac_do_track_dragUPP, window);
9110 if (mac_do_receive_dragUPP)
9111 RemoveReceiveHandler (mac_do_receive_dragUPP, window);
9112 #endif
9115 #if TARGET_API_MAC_CARBON
9116 static pascal OSErr
9117 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
9118 void *handlerRefCon, DragReference theDrag)
9120 static int can_accept;
9121 short items;
9122 short index;
9123 ItemReference theItem;
9124 FlavorFlags theFlags;
9125 OSErr result;
9127 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
9128 return dragNotAcceptedErr;
9130 switch (message)
9132 case kDragTrackingEnterHandler:
9133 CountDragItems (theDrag, &items);
9134 can_accept = 0;
9135 for (index = 1; index <= items; index++)
9137 GetDragItemReferenceNumber (theDrag, index, &theItem);
9138 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
9139 if (result == noErr)
9141 can_accept = 1;
9142 break;
9145 break;
9147 case kDragTrackingEnterWindow:
9148 if (can_accept)
9150 RgnHandle hilite_rgn = NewRgn ();
9151 Rect r;
9152 struct frame *f = mac_window_to_frame (window);
9154 GetWindowPortBounds (window, &r);
9155 OffsetRect (&r, -r.left, -r.top);
9156 RectRgn (hilite_rgn, &r);
9157 ShowDragHilite (theDrag, hilite_rgn, true);
9158 DisposeRgn (hilite_rgn);
9159 SetThemeCursor (kThemeCopyArrowCursor);
9161 break;
9163 case kDragTrackingInWindow:
9164 break;
9166 case kDragTrackingLeaveWindow:
9167 if (can_accept)
9169 struct frame *f = mac_window_to_frame (window);
9171 HideDragHilite (theDrag);
9172 SetThemeCursor (kThemeArrowCursor);
9174 break;
9176 case kDragTrackingLeaveHandler:
9177 break;
9180 return noErr;
9183 static pascal OSErr
9184 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
9185 DragReference theDrag)
9187 short items;
9188 short index;
9189 FlavorFlags theFlags;
9190 Point mouse;
9191 OSErr result;
9192 ItemReference theItem;
9193 HFSFlavor data;
9194 Size size = sizeof (HFSFlavor);
9195 Lisp_Object file_list;
9197 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
9198 return dragNotAcceptedErr;
9200 file_list = Qnil;
9201 GetDragMouse (theDrag, &mouse, 0L);
9202 CountDragItems (theDrag, &items);
9203 for (index = 1; index <= items; index++)
9205 /* Only handle file references. */
9206 GetDragItemReferenceNumber (theDrag, index, &theItem);
9207 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
9208 if (result == noErr)
9210 OSErr err;
9211 AEDesc desc;
9213 err = GetFlavorData (theDrag, theItem, flavorTypeHFS,
9214 &data, &size, 0L);
9215 if (err == noErr)
9216 err = AECoercePtr (typeFSS, &data.fileSpec, sizeof (FSSpec),
9217 TYPE_FILE_NAME, &desc);
9218 if (err == noErr)
9220 Lisp_Object file;
9222 /* x-dnd functions expect undecoded filenames. */
9223 file = make_uninit_string (AEGetDescDataSize (&desc));
9224 err = AEGetDescData (&desc, SDATA (file), SBYTES (file));
9225 if (err == noErr)
9226 file_list = Fcons (file, file_list);
9227 AEDisposeDesc (&desc);
9231 /* If there are items in the list, construct an event and post it to
9232 the queue like an interrupt using kbd_buffer_store_event. */
9233 if (!NILP (file_list))
9235 struct input_event event;
9236 Lisp_Object frame;
9237 struct frame *f = mac_window_to_frame (window);
9238 SInt16 modifiers;
9240 GlobalToLocal (&mouse);
9241 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
9243 event.kind = DRAG_N_DROP_EVENT;
9244 event.code = 0;
9245 event.modifiers = mac_to_emacs_modifiers (modifiers);
9246 event.timestamp = TickCount () * (1000 / 60);
9247 XSETINT (event.x, mouse.h);
9248 XSETINT (event.y, mouse.v);
9249 XSETFRAME (frame, f);
9250 event.frame_or_window = frame;
9251 event.arg = file_list;
9252 /* Post to the interrupt queue */
9253 kbd_buffer_store_event (&event);
9254 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9256 ProcessSerialNumber psn;
9257 GetCurrentProcess (&psn);
9258 SetFrontProcess (&psn);
9261 return noErr;
9263 else
9264 return dragNotAcceptedErr;
9266 #endif
9269 #if __profile__
9270 void
9271 profiler_exit_proc ()
9273 ProfilerDump ("\pEmacs.prof");
9274 ProfilerTerm ();
9276 #endif
9278 /* These few functions implement Emacs as a normal Mac application
9279 (almost): set up the heap and the Toolbox, handle necessary system
9280 events plus a few simple menu events. They also set up Emacs's
9281 access to functions defined in the rest of this file. Emacs uses
9282 function hooks to perform all its terminal I/O. A complete list of
9283 these functions appear in termhooks.h. For what they do, read the
9284 comments there and see also w32term.c and xterm.c. What's
9285 noticeably missing here is the event loop, which is normally
9286 present in most Mac application. After performing the necessary
9287 Mac initializations, main passes off control to emacs_main
9288 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9289 (defined further below) to read input. This is where
9290 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9292 #ifdef MAC_OS8
9293 #undef main
9295 main (void)
9297 #if __profile__ /* is the profiler on? */
9298 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
9299 exit(1);
9300 #endif
9302 #if __MWERKS__
9303 /* set creator and type for files created by MSL */
9304 _fcreator = 'EMAx';
9305 _ftype = 'TEXT';
9306 #endif
9308 do_init_managers ();
9310 do_get_menus ();
9312 #ifndef USE_LSB_TAG
9313 do_check_ram_size ();
9314 #endif
9316 init_emacs_passwd_dir ();
9318 init_environ ();
9320 init_coercion_handler ();
9322 initialize_applescript ();
9324 init_apple_event_handler ();
9327 char **argv;
9328 int argc = 0;
9330 /* set up argv array from STR# resource */
9331 get_string_list (&argv, ARGV_STRING_LIST_ID);
9332 while (argv[argc])
9333 argc++;
9335 /* free up AppleScript resources on exit */
9336 atexit (terminate_applescript);
9338 #if __profile__ /* is the profiler on? */
9339 atexit (profiler_exit_proc);
9340 #endif
9342 /* 3rd param "envp" never used in emacs_main */
9343 (void) emacs_main (argc, argv, 0);
9346 /* Never reached - real exit in Fkill_emacs */
9347 return 0;
9349 #endif
9351 /* Table for translating Mac keycode to X keysym values. Contributed
9352 by Sudhir Shenoy.
9353 Mapping for special keys is now identical to that in Apple X11
9354 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9355 on the right of the Cmd key on laptops, and fn + `enter' (->
9356 <linefeed>). */
9357 static unsigned char keycode_to_xkeysym_table[] = {
9358 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9359 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9360 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9362 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9363 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9364 /*0x38*/ 0, 0, 0, 0,
9365 /*0x3C*/ 0, 0, 0, 0,
9367 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9368 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9369 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9370 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9372 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9373 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9374 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9375 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9377 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9378 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9379 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9380 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9382 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9383 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9384 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9385 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9389 static int
9390 keycode_to_xkeysym (int keyCode, int *xKeySym)
9392 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
9393 return *xKeySym != 0;
9396 static unsigned char fn_keycode_to_xkeysym_table[] = {
9397 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9398 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9399 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9401 /*0x30*/ 0, 0, 0, 0,
9402 /*0x34*/ 0, 0, 0, 0,
9403 /*0x38*/ 0, 0, 0, 0,
9404 /*0x3C*/ 0, 0, 0, 0,
9406 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9407 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9408 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9409 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9411 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9412 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9413 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9414 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9416 /*0x60*/ 0, 0, 0, 0,
9417 /*0x64*/ 0, 0, 0, 0,
9418 /*0x68*/ 0, 0, 0, 0,
9419 /*0x6C*/ 0, 0, 0, 0,
9421 /*0x70*/ 0, 0, 0, 0,
9422 /*0x74*/ 0, 0, 0, 0,
9423 /*0x78*/ 0, 0, 0, 0,
9424 /*0x7C*/ 0, 0, 0, 0
9426 static int
9427 convert_fn_keycode (EventRef eventRef, int keyCode, int *newCode)
9429 #ifdef MAC_OSX
9430 /* Use the special map to translate keys when function modifier is
9431 to be caught. KeyTranslate can't be used in that case.
9432 We can't detect the function key using the input_event.modifiers,
9433 because this uses the high word of an UInt32. Therefore,
9434 we'll just read it out of the original eventRef.
9438 /* TODO / known issues
9440 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9441 The above table always translates to lower characters. We need to use
9442 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9444 - The table is meant for English language keyboards, and it will work
9445 for many others with the exception of key combinations like Fn-ö on
9446 a German keyboard, which is currently mapped to Fn-;.
9447 How to solve this without keeping separate tables for all keyboards
9448 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9449 value for keycode with the modifiers in he high byte, i.e. no room for the
9450 Fn modifier. That's why we need the table.
9454 UInt32 mods = 0;
9455 if (!NILP(Vmac_function_modifier))
9457 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
9458 sizeof (UInt32), NULL, &mods);
9459 if (mods & kEventKeyModifierFnMask)
9460 { *newCode = fn_keycode_to_xkeysym_table [keyCode & 0x7f];
9462 return (*newCode != 0);
9465 #endif
9466 return false;
9469 static int
9470 backtranslate_modified_keycode(int mods, int keycode, int def)
9472 EventModifiers mapped_modifiers =
9473 (NILP (Vmac_control_modifier) ? 0 : controlKey)
9474 | (NILP (Vmac_option_modifier) ? 0 : optionKey)
9475 | (NILP (Vmac_command_modifier) ? 0 : cmdKey);
9477 if (mods & mapped_modifiers)
9479 /* This code comes from Keyboard Resource,
9480 Appendix C of IM - Text. This is necessary
9481 since shift is ignored in KCHR table
9482 translation when option or command is pressed.
9483 It also does not translate correctly
9484 control-shift chars like C-% so mask off shift
9485 here also.
9487 Not done for combinations with the option key (alt)
9488 unless it is to be caught by Emacs: this is
9489 to preserve key combinations translated by the OS
9490 such as Alt-3.
9492 /* Mask off modifier keys that are mapped to some Emacs
9493 modifiers. */
9494 int new_modifiers = mods & ~mapped_modifiers;
9495 /* set high byte of keycode to modifier high byte*/
9496 int new_keycode = keycode | new_modifiers;
9497 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9498 unsigned long some_state = 0;
9499 return (int) KeyTranslate (kchr_ptr, new_keycode,
9500 &some_state) & 0xff;
9501 /* TO DO: Recognize two separate resulting characters, "for
9502 example, when the user presses Option-E followed by N, you
9503 can map this through the KeyTranslate function using the
9504 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9505 returns as two characters in the bytes labeled Character code
9506 1 and Character code 2." (from Carbon API doc) */
9509 else
9510 return def;
9514 #if !USE_CARBON_EVENTS
9515 static RgnHandle mouse_region = NULL;
9517 Boolean
9518 mac_wait_next_event (er, sleep_time, dequeue)
9519 EventRecord *er;
9520 UInt32 sleep_time;
9521 Boolean dequeue;
9523 static EventRecord er_buf = {nullEvent};
9524 UInt32 target_tick, current_tick;
9525 EventMask event_mask;
9527 if (mouse_region == NULL)
9528 mouse_region = NewRgn ();
9530 event_mask = everyEvent;
9531 if (!mac_ready_for_apple_events)
9532 event_mask -= highLevelEventMask;
9534 current_tick = TickCount ();
9535 target_tick = current_tick + sleep_time;
9537 if (er_buf.what == nullEvent)
9538 while (!WaitNextEvent (event_mask, &er_buf,
9539 target_tick - current_tick, mouse_region))
9541 current_tick = TickCount ();
9542 if (target_tick <= current_tick)
9543 return false;
9546 *er = er_buf;
9547 if (dequeue)
9548 er_buf.what = nullEvent;
9549 return true;
9551 #endif /* not USE_CARBON_EVENTS */
9553 /* Emacs calls this whenever it wants to read an input event from the
9554 user. */
9556 XTread_socket (sd, expected, hold_quit)
9557 int sd, expected;
9558 struct input_event *hold_quit;
9560 struct input_event inev;
9561 int count = 0;
9562 #if USE_CARBON_EVENTS
9563 EventRef eventRef;
9564 EventTargetRef toolbox_dispatcher;
9565 #endif
9566 EventRecord er;
9567 struct mac_display_info *dpyinfo = &one_mac_display_info;
9569 if (interrupt_input_blocked)
9571 interrupt_input_pending = 1;
9572 return -1;
9575 interrupt_input_pending = 0;
9576 BLOCK_INPUT;
9578 /* So people can tell when we have read the available input. */
9579 input_signal_count++;
9581 #if USE_CARBON_EVENTS
9582 toolbox_dispatcher = GetEventDispatcherTarget ();
9584 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
9585 kEventRemoveFromQueue, &eventRef))
9586 #else /* !USE_CARBON_EVENTS */
9587 while (mac_wait_next_event (&er, 0, true))
9588 #endif /* !USE_CARBON_EVENTS */
9590 int do_help = 0;
9591 struct frame *f;
9592 unsigned long timestamp;
9594 /* It is necessary to set this (additional) argument slot of an
9595 event to nil because keyboard.c protects incompletely
9596 processed event from being garbage collected by placing them
9597 in the kbd_buffer_gcpro vector. */
9598 EVENT_INIT (inev);
9599 inev.kind = NO_EVENT;
9600 inev.arg = Qnil;
9602 #if USE_CARBON_EVENTS
9603 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
9604 #else
9605 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
9606 #endif
9608 #if USE_CARBON_EVENTS
9609 /* Handle new events */
9610 if (!mac_convert_event_ref (eventRef, &er))
9612 /* There used to be a handler for the kEventMouseWheelMoved
9613 event here. But as of Mac OS X 10.4, this kind of event
9614 is not directly posted to the main event queue by
9615 two-finger scrolling on the trackpad. Instead, some
9616 private event is posted and it is converted to a wheel
9617 event by the default handler for the application target.
9618 The converted one can be received by a Carbon event
9619 handler installed on a window target. */
9620 read_socket_inev = &inev;
9621 SendEventToEventTarget (eventRef, toolbox_dispatcher);
9622 read_socket_inev = NULL;
9624 else
9625 #endif /* USE_CARBON_EVENTS */
9626 switch (er.what)
9628 case mouseDown:
9629 case mouseUp:
9631 WindowPtr window_ptr;
9632 ControlPartCode part_code;
9633 int tool_bar_p = 0;
9635 #if USE_CARBON_EVENTS
9636 /* This is needed to send mouse events like aqua window
9637 buttons to the correct handler. */
9638 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9639 != eventNotHandledErr)
9640 break;
9641 #endif
9642 last_mouse_glyph_frame = 0;
9644 if (dpyinfo->grabbed && last_mouse_frame
9645 && FRAME_LIVE_P (last_mouse_frame))
9647 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
9648 part_code = inContent;
9650 else
9652 part_code = FindWindow (er.where, &window_ptr);
9653 if (tip_window && window_ptr == tip_window)
9655 HideWindow (tip_window);
9656 part_code = FindWindow (er.where, &window_ptr);
9660 if (er.what != mouseDown &&
9661 (part_code != inContent || dpyinfo->grabbed == 0))
9662 break;
9664 switch (part_code)
9666 case inMenuBar:
9667 f = mac_focus_frame (dpyinfo);
9668 saved_menu_event_location = er.where;
9669 inev.kind = MENU_BAR_ACTIVATE_EVENT;
9670 XSETFRAME (inev.frame_or_window, f);
9671 break;
9673 case inContent:
9674 if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
9675 SelectWindow (window_ptr);
9676 else
9678 ControlPartCode control_part_code;
9679 ControlHandle ch;
9680 Point mouse_loc = er.where;
9681 #ifdef MAC_OSX
9682 ControlKind control_kind;
9683 #endif
9685 f = mac_window_to_frame (window_ptr);
9686 /* convert to local coordinates of new window */
9687 SetPortWindowPort (window_ptr);
9689 GlobalToLocal (&mouse_loc);
9690 #if TARGET_API_MAC_CARBON
9691 ch = FindControlUnderMouse (mouse_loc, window_ptr,
9692 &control_part_code);
9693 #ifdef MAC_OSX
9694 if (ch)
9695 GetControlKind (ch, &control_kind);
9696 #endif
9697 #else
9698 control_part_code = FindControl (mouse_loc, window_ptr,
9699 &ch);
9700 #endif
9702 #if USE_CARBON_EVENTS
9703 inev.code = mac_get_mouse_btn (eventRef);
9704 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9705 #else
9706 inev.code = mac_get_emulated_btn (er.modifiers);
9707 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9708 #endif
9709 XSETINT (inev.x, mouse_loc.h);
9710 XSETINT (inev.y, mouse_loc.v);
9712 if (dpyinfo->grabbed && tracked_scroll_bar
9713 || ch != 0
9714 #ifndef USE_TOOLKIT_SCROLL_BARS
9715 /* control_part_code becomes kControlNoPart if
9716 a progress indicator is clicked. */
9717 && control_part_code != kControlNoPart
9718 #else /* USE_TOOLKIT_SCROLL_BARS */
9719 #ifdef MAC_OSX
9720 && control_kind.kind == kControlKindScrollBar
9721 #endif /* MAC_OSX */
9722 #endif /* USE_TOOLKIT_SCROLL_BARS */
9725 struct scroll_bar *bar;
9727 if (dpyinfo->grabbed && tracked_scroll_bar)
9729 bar = tracked_scroll_bar;
9730 #ifndef USE_TOOLKIT_SCROLL_BARS
9731 control_part_code = kControlIndicatorPart;
9732 #endif
9734 else
9735 bar = (struct scroll_bar *) GetControlReference (ch);
9736 #ifdef USE_TOOLKIT_SCROLL_BARS
9737 /* Make the "Ctrl-Mouse-2 splits window" work
9738 for toolkit scroll bars. */
9739 if (er.modifiers & controlKey)
9740 x_scroll_bar_handle_click (bar, control_part_code,
9741 &er, &inev);
9742 else if (er.what == mouseDown)
9743 x_scroll_bar_handle_press (bar, control_part_code,
9744 &inev);
9745 else
9746 x_scroll_bar_handle_release (bar, &inev);
9747 #else /* not USE_TOOLKIT_SCROLL_BARS */
9748 x_scroll_bar_handle_click (bar, control_part_code,
9749 &er, &inev);
9750 if (er.what == mouseDown
9751 && control_part_code == kControlIndicatorPart)
9752 tracked_scroll_bar = bar;
9753 else
9754 tracked_scroll_bar = NULL;
9755 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9757 else
9759 Lisp_Object window;
9760 int x = mouse_loc.h;
9761 int y = mouse_loc.v;
9763 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
9764 if (EQ (window, f->tool_bar_window))
9766 if (er.what == mouseDown)
9767 handle_tool_bar_click (f, x, y, 1, 0);
9768 else
9769 handle_tool_bar_click (f, x, y, 0,
9770 inev.modifiers);
9771 tool_bar_p = 1;
9773 else
9775 XSETFRAME (inev.frame_or_window, f);
9776 inev.kind = MOUSE_CLICK_EVENT;
9780 if (er.what == mouseDown)
9782 dpyinfo->grabbed |= (1 << inev.code);
9783 last_mouse_frame = f;
9785 if (!tool_bar_p)
9786 last_tool_bar_item = -1;
9788 else
9790 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
9791 /* If a button is released though it was not
9792 previously pressed, that would be because
9793 of multi-button emulation. */
9794 dpyinfo->grabbed = 0;
9795 else
9796 dpyinfo->grabbed &= ~(1 << inev.code);
9799 /* Ignore any mouse motion that happened before
9800 this event; any subsequent mouse-movement Emacs
9801 events should reflect only motion after the
9802 ButtonPress. */
9803 if (f != 0)
9804 f->mouse_moved = 0;
9806 #ifdef USE_TOOLKIT_SCROLL_BARS
9807 if (inev.kind == MOUSE_CLICK_EVENT)
9808 #endif
9809 switch (er.what)
9811 case mouseDown:
9812 inev.modifiers |= down_modifier;
9813 break;
9814 case mouseUp:
9815 inev.modifiers |= up_modifier;
9816 break;
9819 break;
9821 case inDrag:
9822 #if TARGET_API_MAC_CARBON
9823 DragWindow (window_ptr, er.where, NULL);
9824 #else /* not TARGET_API_MAC_CARBON */
9825 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
9826 #endif /* not TARGET_API_MAC_CARBON */
9827 /* Update the frame parameters. */
9829 struct frame *f = mac_window_to_frame (window_ptr);
9831 if (f && !f->async_iconified)
9832 x_real_positions (f, &f->left_pos, &f->top_pos);
9834 break;
9836 case inGoAway:
9837 if (TrackGoAway (window_ptr, er.where))
9839 inev.kind = DELETE_WINDOW_EVENT;
9840 XSETFRAME (inev.frame_or_window,
9841 mac_window_to_frame (window_ptr));
9843 break;
9845 /* window resize handling added --ben */
9846 case inGrow:
9847 do_grow_window (window_ptr, &er);
9848 break;
9850 /* window zoom handling added --ben */
9851 case inZoomIn:
9852 case inZoomOut:
9853 if (TrackBox (window_ptr, er.where, part_code))
9854 do_zoom_window (window_ptr, part_code);
9855 break;
9857 default:
9858 break;
9861 break;
9863 case updateEvt:
9864 #if USE_CARBON_EVENTS
9865 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9866 != eventNotHandledErr)
9867 break;
9868 #else
9869 do_window_update ((WindowPtr) er.message);
9870 #endif
9871 break;
9873 case osEvt:
9874 #if USE_CARBON_EVENTS
9875 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9876 != eventNotHandledErr)
9877 break;
9878 #endif
9879 switch ((er.message >> 24) & 0x000000FF)
9881 case suspendResumeMessage:
9882 if ((er.message & resumeFlag) == 1)
9883 do_app_resume ();
9884 else
9885 do_app_suspend ();
9886 break;
9888 case mouseMovedMessage:
9889 #if !USE_CARBON_EVENTS
9890 SetRectRgn (mouse_region, er.where.h, er.where.v,
9891 er.where.h + 1, er.where.v + 1);
9892 #endif
9893 previous_help_echo_string = help_echo_string;
9894 help_echo_string = Qnil;
9896 if (dpyinfo->grabbed && last_mouse_frame
9897 && FRAME_LIVE_P (last_mouse_frame))
9898 f = last_mouse_frame;
9899 else
9900 f = dpyinfo->x_focus_frame;
9902 if (dpyinfo->mouse_face_hidden)
9904 dpyinfo->mouse_face_hidden = 0;
9905 clear_mouse_face (dpyinfo);
9908 if (f)
9910 WindowPtr wp = FRAME_MAC_WINDOW (f);
9911 Point mouse_pos = er.where;
9913 SetPortWindowPort (wp);
9915 GlobalToLocal (&mouse_pos);
9917 if (dpyinfo->grabbed && tracked_scroll_bar)
9918 #ifdef USE_TOOLKIT_SCROLL_BARS
9919 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
9920 mouse_pos, &inev);
9921 #else /* not USE_TOOLKIT_SCROLL_BARS */
9922 x_scroll_bar_note_movement (tracked_scroll_bar,
9923 mouse_pos.v
9924 - XINT (tracked_scroll_bar->top),
9925 er.when * (1000 / 60));
9926 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9927 else
9929 /* Generate SELECT_WINDOW_EVENTs when needed. */
9930 if (mouse_autoselect_window)
9932 Lisp_Object window;
9934 window = window_from_coordinates (f,
9935 mouse_pos.h,
9936 mouse_pos.v,
9937 0, 0, 0, 0);
9939 /* Window will be selected only when it is
9940 not selected now and last mouse movement
9941 event was not in it. Minibuffer window
9942 will be selected iff it is active. */
9943 if (WINDOWP (window)
9944 && !EQ (window, last_window)
9945 && !EQ (window, selected_window))
9947 inev.kind = SELECT_WINDOW_EVENT;
9948 inev.frame_or_window = window;
9951 last_window=window;
9953 if (!note_mouse_movement (f, &mouse_pos))
9954 help_echo_string = previous_help_echo_string;
9958 /* If the contents of the global variable
9959 help_echo_string has changed, generate a
9960 HELP_EVENT. */
9961 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
9962 do_help = 1;
9963 break;
9965 break;
9967 case activateEvt:
9969 WindowPtr window_ptr = (WindowPtr) er.message;
9971 #if USE_CARBON_EVENTS
9972 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9973 != eventNotHandledErr)
9974 break;
9975 #endif
9976 if (window_ptr == tip_window)
9978 HideWindow (tip_window);
9979 break;
9982 if (!is_emacs_window (window_ptr))
9983 break;
9985 if ((er.modifiers & activeFlag) != 0)
9987 /* A window has been activated */
9988 Point mouse_loc = er.where;
9990 x_detect_focus_change (dpyinfo, &er, &inev);
9992 SetPortWindowPort (window_ptr);
9993 GlobalToLocal (&mouse_loc);
9994 /* Window-activated event counts as mouse movement,
9995 so update things that depend on mouse position. */
9996 note_mouse_movement (mac_window_to_frame (window_ptr),
9997 &mouse_loc);
9999 else
10001 /* A window has been deactivated */
10002 #if USE_TOOLKIT_SCROLL_BARS
10003 if (dpyinfo->grabbed && tracked_scroll_bar)
10005 struct input_event event;
10007 EVENT_INIT (event);
10008 event.kind = NO_EVENT;
10009 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
10010 if (event.kind != NO_EVENT)
10012 event.timestamp = timestamp;
10013 kbd_buffer_store_event_hold (&event, hold_quit);
10014 count++;
10017 #endif
10018 dpyinfo->grabbed = 0;
10020 x_detect_focus_change (dpyinfo, &er, &inev);
10022 f = mac_window_to_frame (window_ptr);
10023 if (f == dpyinfo->mouse_face_mouse_frame)
10025 /* If we move outside the frame, then we're
10026 certainly no longer on any text in the
10027 frame. */
10028 clear_mouse_face (dpyinfo);
10029 dpyinfo->mouse_face_mouse_frame = 0;
10032 /* Generate a nil HELP_EVENT to cancel a help-echo.
10033 Do it only if there's something to cancel.
10034 Otherwise, the startup message is cleared when the
10035 mouse leaves the frame. */
10036 if (any_help_event_p)
10037 do_help = -1;
10040 break;
10042 case keyDown:
10043 case autoKey:
10045 int keycode = (er.message & keyCodeMask) >> 8;
10046 int xkeysym;
10048 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10049 /* When using Carbon Events, we need to pass raw keyboard
10050 events to the TSM ourselves. If TSM handles it, it
10051 will pass back noErr, otherwise it will pass back
10052 "eventNotHandledErr" and we can process it
10053 normally. */
10054 if ((mac_pass_command_to_system
10055 || !(er.modifiers & cmdKey))
10056 && (mac_pass_control_to_system
10057 || !(er.modifiers & controlKey))
10058 && (NILP (Vmac_option_modifier)
10059 || !(er.modifiers & optionKey)))
10060 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
10061 != eventNotHandledErr)
10062 break;
10063 #endif
10065 #if 0
10066 if (dpyinfo->x_focus_frame == NULL)
10068 /* Beep if keyboard input occurs when all the frames
10069 are invisible. */
10070 SysBeep (1);
10071 break;
10073 #endif
10076 static SInt16 last_key_script = -1;
10077 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
10079 if (last_key_script != current_key_script)
10081 struct input_event event;
10083 EVENT_INIT (event);
10084 event.kind = LANGUAGE_CHANGE_EVENT;
10085 event.arg = Qnil;
10086 event.code = current_key_script;
10087 event.timestamp = timestamp;
10088 kbd_buffer_store_event (&event);
10089 count++;
10091 last_key_script = current_key_script;
10094 ObscureCursor ();
10096 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
10098 clear_mouse_face (dpyinfo);
10099 dpyinfo->mouse_face_hidden = 1;
10102 /* translate the keycode back to determine the original key */
10103 /* Convert key code if function key is pressed.
10104 Otherwise, if non-ASCII-event, take care of that
10105 without re-translating the key code. */
10106 #if USE_CARBON_EVENTS
10107 if (convert_fn_keycode (eventRef, keycode, &xkeysym))
10109 inev.code = xkeysym;
10110 /* this doesn't work - tried to add shift modifiers */
10111 inev.code =
10112 backtranslate_modified_keycode(er.modifiers & (~0x2200),
10113 xkeysym | 0x80, xkeysym);
10114 inev.kind = ASCII_KEYSTROKE_EVENT;
10116 else
10117 #endif
10118 if (keycode_to_xkeysym (keycode, &xkeysym))
10120 inev.code = 0xff00 | xkeysym;
10121 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
10123 else
10125 inev.code =
10126 backtranslate_modified_keycode(er.modifiers, keycode,
10127 er.message & charCodeMask);
10128 inev.kind = ASCII_KEYSTROKE_EVENT;
10132 #if USE_CARBON_EVENTS
10133 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
10134 #else
10135 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
10136 #endif
10137 inev.modifiers |= (extra_keyboard_modifiers
10138 & (meta_modifier | alt_modifier
10139 | hyper_modifier | super_modifier));
10140 XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
10141 break;
10143 case kHighLevelEvent:
10144 read_socket_inev = &inev;
10145 AEProcessAppleEvent (&er);
10146 read_socket_inev = NULL;
10147 break;
10149 default:
10150 break;
10152 #if USE_CARBON_EVENTS
10153 ReleaseEvent (eventRef);
10154 #endif
10156 if (inev.kind != NO_EVENT)
10158 inev.timestamp = timestamp;
10159 kbd_buffer_store_event_hold (&inev, hold_quit);
10160 count++;
10163 if (do_help
10164 && !(hold_quit && hold_quit->kind != NO_EVENT))
10166 Lisp_Object frame;
10168 if (f)
10169 XSETFRAME (frame, f);
10170 else
10171 frame = Qnil;
10173 if (do_help > 0)
10175 any_help_event_p = 1;
10176 gen_help_event (help_echo_string, frame, help_echo_window,
10177 help_echo_object, help_echo_pos);
10179 else
10181 help_echo_string = Qnil;
10182 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
10184 count++;
10189 /* If the focus was just given to an autoraising frame,
10190 raise it now. */
10191 /* ??? This ought to be able to handle more than one such frame. */
10192 if (pending_autoraise_frame)
10194 x_raise_frame (pending_autoraise_frame);
10195 pending_autoraise_frame = 0;
10198 #if !USE_CARBON_EVENTS
10199 /* Check which frames are still visible. We do this here because
10200 there doesn't seem to be any direct notification from the Window
10201 Manager that the visibility of a window has changed (at least,
10202 not in all cases). */
10204 Lisp_Object tail, frame;
10206 FOR_EACH_FRAME (tail, frame)
10208 struct frame *f = XFRAME (frame);
10210 /* The tooltip has been drawn already. Avoid the
10211 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10212 if (EQ (frame, tip_frame))
10213 continue;
10215 if (FRAME_MAC_P (f))
10216 mac_handle_visibility_change (f);
10219 #endif
10221 UNBLOCK_INPUT;
10222 return count;
10226 /* Need to override CodeWarrior's input function so no conversion is
10227 done on newlines Otherwise compiled functions in .elc files will be
10228 read incorrectly. Defined in ...:MSL C:MSL
10229 Common:Source:buffer_io.c. */
10230 #ifdef __MWERKS__
10231 void
10232 __convert_to_newlines (unsigned char * p, size_t * n)
10234 #pragma unused(p,n)
10237 void
10238 __convert_from_newlines (unsigned char * p, size_t * n)
10240 #pragma unused(p,n)
10242 #endif
10244 #ifdef MAC_OS8
10245 void
10246 make_mac_terminal_frame (struct frame *f)
10248 Lisp_Object frame;
10249 Rect r;
10251 XSETFRAME (frame, f);
10253 f->output_method = output_mac;
10254 f->output_data.mac = (struct mac_output *)
10255 xmalloc (sizeof (struct mac_output));
10256 bzero (f->output_data.mac, sizeof (struct mac_output));
10258 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
10260 FRAME_COLS (f) = 96;
10261 FRAME_LINES (f) = 4;
10263 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
10264 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
10266 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
10268 f->output_data.mac->cursor_pixel = 0;
10269 f->output_data.mac->border_pixel = 0x00ff00;
10270 f->output_data.mac->mouse_pixel = 0xff00ff;
10271 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
10273 f->output_data.mac->text_cursor = kThemeIBeamCursor;
10274 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
10275 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
10276 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
10277 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
10278 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
10280 FRAME_FONTSET (f) = -1;
10281 f->output_data.mac->explicit_parent = 0;
10282 f->left_pos = 8;
10283 f->top_pos = 32;
10284 f->border_width = 0;
10286 f->internal_border_width = 0;
10288 f->auto_raise = 1;
10289 f->auto_lower = 1;
10291 f->new_text_cols = 0;
10292 f->new_text_lines = 0;
10294 SetRect (&r, f->left_pos, f->top_pos,
10295 f->left_pos + FRAME_PIXEL_WIDTH (f),
10296 f->top_pos + FRAME_PIXEL_HEIGHT (f));
10298 BLOCK_INPUT;
10300 if (!(FRAME_MAC_WINDOW (f) =
10301 NewCWindow (NULL, &r, "\p", true, dBoxProc,
10302 (WindowPtr) -1, 1, (long) f->output_data.mac)))
10303 abort ();
10304 /* so that update events can find this mac_output struct */
10305 f->output_data.mac->mFP = f; /* point back to emacs frame */
10307 UNBLOCK_INPUT;
10309 x_make_gc (f);
10311 /* Need to be initialized for unshow_buffer in window.c. */
10312 selected_window = f->selected_window;
10314 Fmodify_frame_parameters (frame,
10315 Fcons (Fcons (Qfont,
10316 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
10317 Fmodify_frame_parameters (frame,
10318 Fcons (Fcons (Qforeground_color,
10319 build_string ("black")), Qnil));
10320 Fmodify_frame_parameters (frame,
10321 Fcons (Fcons (Qbackground_color,
10322 build_string ("white")), Qnil));
10324 #endif
10327 /***********************************************************************
10328 Initialization
10329 ***********************************************************************/
10331 int mac_initialized = 0;
10333 void
10334 mac_initialize_display_info ()
10336 struct mac_display_info *dpyinfo = &one_mac_display_info;
10337 GDHandle main_device_handle;
10339 bzero (dpyinfo, sizeof (*dpyinfo));
10341 #ifdef MAC_OSX
10342 dpyinfo->mac_id_name
10343 = (char *) xmalloc (SCHARS (Vinvocation_name)
10344 + SCHARS (Vsystem_name)
10345 + 2);
10346 sprintf (dpyinfo->mac_id_name, "%s@%s",
10347 SDATA (Vinvocation_name), SDATA (Vsystem_name));
10348 #else
10349 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
10350 strcpy (dpyinfo->mac_id_name, "Mac Display");
10351 #endif
10353 main_device_handle = LMGetMainDevice();
10355 dpyinfo->reference_count = 0;
10356 dpyinfo->resx = 72.0;
10357 dpyinfo->resy = 72.0;
10358 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
10359 #ifdef MAC_OSX
10360 /* HasDepth returns true if it is possible to have a 32 bit display,
10361 but this may not be what is actually used. Mac OSX can do better.
10362 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10363 header for CGGetActiveDisplayList says that the first display returned
10364 is the active one, so we use that. */
10366 CGDirectDisplayID disp_id[1];
10367 CGDisplayCount disp_count;
10368 CGDisplayErr error_code;
10370 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
10371 if (error_code != 0)
10372 error ("No display found, CGGetActiveDisplayList error %d", error_code);
10374 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
10376 #else
10377 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
10378 if (HasDepth (main_device_handle, dpyinfo->n_planes,
10379 gdDevType, dpyinfo->color_p))
10380 break;
10381 #endif
10382 dpyinfo->height = (**main_device_handle).gdRect.bottom;
10383 dpyinfo->width = (**main_device_handle).gdRect.right;
10384 dpyinfo->grabbed = 0;
10385 dpyinfo->root_window = NULL;
10386 dpyinfo->image_cache = make_image_cache ();
10388 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
10389 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10390 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10391 dpyinfo->mouse_face_window = Qnil;
10392 dpyinfo->mouse_face_overlay = Qnil;
10393 dpyinfo->mouse_face_hidden = 0;
10397 static XrmDatabase
10398 mac_make_rdb (xrm_option)
10399 char *xrm_option;
10401 XrmDatabase database;
10403 database = xrm_get_preference_database (NULL);
10404 if (xrm_option)
10405 xrm_merge_string_database (database, xrm_option);
10407 return database;
10410 struct mac_display_info *
10411 mac_term_init (display_name, xrm_option, resource_name)
10412 Lisp_Object display_name;
10413 char *xrm_option;
10414 char *resource_name;
10416 struct mac_display_info *dpyinfo;
10418 BLOCK_INPUT;
10420 if (!mac_initialized)
10422 mac_initialize ();
10423 mac_initialized = 1;
10426 if (x_display_list)
10427 error ("Sorry, this version can only handle one display");
10429 mac_initialize_display_info ();
10431 dpyinfo = &one_mac_display_info;
10433 dpyinfo->xrdb = mac_make_rdb (xrm_option);
10435 /* Put this display on the chain. */
10436 dpyinfo->next = x_display_list;
10437 x_display_list = dpyinfo;
10439 /* Put it on x_display_name_list. */
10440 x_display_name_list = Fcons (Fcons (display_name,
10441 Fcons (Qnil, dpyinfo->xrdb)),
10442 x_display_name_list);
10443 dpyinfo->name_list_element = XCAR (x_display_name_list);
10445 UNBLOCK_INPUT;
10447 return dpyinfo;
10449 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10451 void
10452 x_delete_display (dpyinfo)
10453 struct mac_display_info *dpyinfo;
10455 int i;
10457 /* Discard this display from x_display_name_list and x_display_list.
10458 We can't use Fdelq because that can quit. */
10459 if (! NILP (x_display_name_list)
10460 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
10461 x_display_name_list = XCDR (x_display_name_list);
10462 else
10464 Lisp_Object tail;
10466 tail = x_display_name_list;
10467 while (CONSP (tail) && CONSP (XCDR (tail)))
10469 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10471 XSETCDR (tail, XCDR (XCDR (tail)));
10472 break;
10474 tail = XCDR (tail);
10478 if (x_display_list == dpyinfo)
10479 x_display_list = dpyinfo->next;
10480 else
10482 struct x_display_info *tail;
10484 for (tail = x_display_list; tail; tail = tail->next)
10485 if (tail->next == dpyinfo)
10486 tail->next = tail->next->next;
10489 /* Free the font names in the font table. */
10490 for (i = 0; i < dpyinfo->n_fonts; i++)
10491 if (dpyinfo->font_table[i].name)
10493 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
10494 xfree (dpyinfo->font_table[i].full_name);
10495 xfree (dpyinfo->font_table[i].name);
10498 if (dpyinfo->font_table->font_encoder)
10499 xfree (dpyinfo->font_table->font_encoder);
10501 xfree (dpyinfo->font_table);
10502 xfree (dpyinfo->mac_id_name);
10504 if (x_display_list == 0)
10506 mac_clear_font_name_table ();
10507 bzero (dpyinfo, sizeof (*dpyinfo));
10512 #ifdef MAC_OSX
10513 void
10514 mac_check_bundle()
10516 extern int inhibit_window_system;
10517 extern int noninteractive;
10518 CFBundleRef appsBundle;
10519 pid_t child;
10521 /* No need to test if already -nw*/
10522 if (inhibit_window_system || noninteractive)
10523 return;
10525 appsBundle = CFBundleGetMainBundle();
10526 if (appsBundle != NULL)
10528 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
10529 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
10530 /* We found the bundle identifier, now we know we are valid. */
10531 if (res != NULL)
10533 CFRelease(res);
10534 return;
10537 /* MAC_TODO: Have this start the bundled executable */
10539 /* For now, prevent the fatal error by bringing it up in the terminal */
10540 inhibit_window_system = 1;
10543 void
10544 MakeMeTheFrontProcess ()
10546 ProcessSerialNumber psn;
10547 OSErr err;
10549 err = GetCurrentProcess (&psn);
10550 if (err == noErr)
10551 (void) SetFrontProcess (&psn);
10554 /***** Code to handle C-g testing *****/
10556 /* Contains the Mac modifier formed from quit_char */
10557 int mac_quit_char_modifiers = 0;
10558 int mac_quit_char_keycode;
10559 extern int quit_char;
10561 static void
10562 mac_determine_quit_char_modifiers()
10564 /* Todo: Determine modifiers from quit_char. */
10565 UInt32 qc_modifiers = ctrl_modifier;
10567 /* Map modifiers */
10568 mac_quit_char_modifiers = 0;
10569 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= controlKey;
10570 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= shiftKey;
10571 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= optionKey;
10574 static void
10575 init_quit_char_handler ()
10577 /* TODO: Let this support keys other the 'g' */
10578 mac_quit_char_keycode = 5;
10579 /* Look at <architecture/adb_kb_map.h> for details */
10580 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10582 mac_determine_quit_char_modifiers();
10584 #endif /* MAC_OSX */
10586 static void
10587 init_menu_bar ()
10589 #ifdef MAC_OSX
10590 OSErr err;
10591 MenuRef menu;
10592 MenuItemIndex menu_index;
10594 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
10595 &menu, &menu_index);
10596 if (err == noErr)
10597 SetMenuItemCommandKey (menu, menu_index, false, 0);
10598 #if USE_CARBON_EVENTS
10599 EnableMenuCommand (NULL, kHICommandPreferences);
10600 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
10601 &menu, &menu_index);
10602 if (err == noErr)
10604 SetMenuItemCommandKey (menu, menu_index, false, 0);
10605 InsertMenuItemTextWithCFString (menu, NULL,
10606 0, kMenuItemAttrSeparator, 0);
10607 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
10608 0, 0, kHICommandAbout);
10610 #endif /* USE_CARBON_EVENTS */
10611 #else /* !MAC_OSX */
10612 #if USE_CARBON_EVENTS
10613 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
10614 #endif
10615 #endif
10619 /* Set up use of X before we make the first connection. */
10621 extern frame_parm_handler mac_frame_parm_handlers[];
10623 static struct redisplay_interface x_redisplay_interface =
10625 mac_frame_parm_handlers,
10626 x_produce_glyphs,
10627 x_write_glyphs,
10628 x_insert_glyphs,
10629 x_clear_end_of_line,
10630 x_scroll_run,
10631 x_after_update_window_line,
10632 x_update_window_begin,
10633 x_update_window_end,
10634 x_cursor_to,
10635 x_flush,
10636 0, /* flush_display_optional */
10637 x_clear_window_mouse_face,
10638 x_get_glyph_overhangs,
10639 x_fix_overlapping_area,
10640 x_draw_fringe_bitmap,
10641 0, /* define_fringe_bitmap */
10642 0, /* destroy_fringe_bitmap */
10643 mac_per_char_metric,
10644 mac_encode_char,
10645 mac_compute_glyph_string_overhangs,
10646 x_draw_glyph_string,
10647 mac_define_frame_cursor,
10648 mac_clear_frame_area,
10649 mac_draw_window_cursor,
10650 mac_draw_vertical_window_border,
10651 mac_shift_glyphs_for_insert
10654 void
10655 mac_initialize ()
10657 rif = &x_redisplay_interface;
10659 clear_frame_hook = x_clear_frame;
10660 ins_del_lines_hook = x_ins_del_lines;
10661 delete_glyphs_hook = x_delete_glyphs;
10662 ring_bell_hook = XTring_bell;
10663 reset_terminal_modes_hook = XTreset_terminal_modes;
10664 set_terminal_modes_hook = XTset_terminal_modes;
10665 update_begin_hook = x_update_begin;
10666 update_end_hook = x_update_end;
10667 set_terminal_window_hook = XTset_terminal_window;
10668 read_socket_hook = XTread_socket;
10669 frame_up_to_date_hook = XTframe_up_to_date;
10670 mouse_position_hook = XTmouse_position;
10671 frame_rehighlight_hook = XTframe_rehighlight;
10672 frame_raise_lower_hook = XTframe_raise_lower;
10674 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10675 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10676 redeem_scroll_bar_hook = XTredeem_scroll_bar;
10677 judge_scroll_bars_hook = XTjudge_scroll_bars;
10679 scroll_region_ok = 1; /* we'll scroll partial frames */
10680 char_ins_del_ok = 1;
10681 line_ins_del_ok = 1; /* we'll just blt 'em */
10682 fast_clear_end_of_line = 1; /* X does this well */
10683 memory_below_frame = 0; /* we don't remember what scrolls
10684 off the bottom */
10685 baud_rate = 19200;
10687 last_tool_bar_item = -1;
10688 any_help_event_p = 0;
10690 /* Try to use interrupt input; if we can't, then start polling. */
10691 Fset_input_mode (Qt, Qnil, Qt, Qnil);
10693 BLOCK_INPUT;
10695 #if TARGET_API_MAC_CARBON
10697 #if USE_CARBON_EVENTS
10698 #ifdef MAC_OSX
10699 init_service_handler ();
10701 init_quit_char_handler ();
10702 #endif /* MAC_OSX */
10704 init_command_handler ();
10706 init_menu_bar ();
10707 #endif /* USE_CARBON_EVENTS */
10709 #ifdef MAC_OSX
10710 init_coercion_handler ();
10712 init_apple_event_handler ();
10714 if (!inhibit_window_system)
10715 MakeMeTheFrontProcess ();
10716 #endif
10717 #endif
10718 UNBLOCK_INPUT;
10722 void
10723 syms_of_macterm ()
10725 #if 0
10726 staticpro (&x_error_message_string);
10727 x_error_message_string = Qnil;
10728 #endif
10730 Qcontrol = intern ("control"); staticpro (&Qcontrol);
10731 Qmeta = intern ("meta"); staticpro (&Qmeta);
10732 Qalt = intern ("alt"); staticpro (&Qalt);
10733 Qhyper = intern ("hyper"); staticpro (&Qhyper);
10734 Qsuper = intern ("super"); staticpro (&Qsuper);
10735 Qmodifier_value = intern ("modifier-value");
10736 staticpro (&Qmodifier_value);
10738 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
10739 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
10740 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10741 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10742 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10744 #if USE_CARBON_EVENTS
10745 Qhicommand = intern ("hicommand"); staticpro (&Qhicommand);
10746 #ifdef MAC_OSX
10747 Qservices = intern ("services"); staticpro (&Qservices);
10748 Qpaste = intern ("paste"); staticpro (&Qpaste);
10749 Qperform = intern ("perform"); staticpro (&Qperform);
10750 #endif
10751 #endif
10753 #ifdef MAC_OSX
10754 Fprovide (intern ("mac-carbon"), Qnil);
10755 #endif
10757 staticpro (&Qreverse);
10758 Qreverse = intern ("reverse");
10760 staticpro (&x_display_name_list);
10761 x_display_name_list = Qnil;
10763 staticpro (&last_mouse_scroll_bar);
10764 last_mouse_scroll_bar = Qnil;
10766 staticpro (&fm_font_family_alist);
10767 fm_font_family_alist = Qnil;
10769 #if USE_ATSUI
10770 staticpro (&atsu_font_id_hash);
10771 atsu_font_id_hash = Qnil;
10772 #endif
10774 /* We don't yet support this, but defining this here avoids whining
10775 from cus-start.el and other places, like "M-x set-variable". */
10776 DEFVAR_BOOL ("x-use-underline-position-properties",
10777 &x_use_underline_position_properties,
10778 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10779 nil means ignore them. If you encounter fonts with bogus
10780 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10781 to 4.1, set this to nil.
10783 NOTE: Not supported on Mac yet. */);
10784 x_use_underline_position_properties = 0;
10786 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10787 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
10788 #ifdef USE_TOOLKIT_SCROLL_BARS
10789 Vx_toolkit_scroll_bars = Qt;
10790 #else
10791 Vx_toolkit_scroll_bars = Qnil;
10792 #endif
10794 staticpro (&last_mouse_motion_frame);
10795 last_mouse_motion_frame = Qnil;
10797 /* Variables to configure modifier key assignment. */
10799 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier,
10800 doc: /* *Modifier key assumed when the Mac control key is pressed.
10801 The value can be `control', `meta', `alt', `hyper', or `super' for the
10802 respective modifier. The default is `control'. */);
10803 Vmac_control_modifier = Qcontrol;
10805 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
10806 doc: /* *Modifier key assumed when the Mac alt/option key is pressed.
10807 The value can be `control', `meta', `alt', `hyper', or `super' for the
10808 respective modifier. If the value is nil then the key will act as the
10809 normal Mac control modifier, and the option key can be used to compose
10810 characters depending on the chosen Mac keyboard setting. */);
10811 Vmac_option_modifier = Qnil;
10813 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier,
10814 doc: /* *Modifier key assumed when the Mac command key is pressed.
10815 The value can be `control', `meta', `alt', `hyper', or `super' for the
10816 respective modifier. The default is `meta'. */);
10817 Vmac_command_modifier = Qmeta;
10819 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier,
10820 doc: /* *Modifier key assumed when the Mac function key is pressed.
10821 The value can be `control', `meta', `alt', `hyper', or `super' for the
10822 respective modifier. Note that remapping the function key may lead to
10823 unexpected results for some keys on non-US/GB keyboards. */);
10824 Vmac_function_modifier = Qnil;
10826 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10827 &Vmac_emulate_three_button_mouse,
10828 doc: /* *Specify a way of three button mouse emulation.
10829 The value can be nil, t, or the symbol `reverse'.
10830 nil means that no emulation should be done and the modifiers should be
10831 placed on the mouse-1 event.
10832 t means that when the option-key is held down while pressing the mouse
10833 button, the click will register as mouse-2 and while the command-key
10834 is held down, the click will register as mouse-3.
10835 The symbol `reverse' means that the option-key will register for
10836 mouse-3 and the command-key will register for mouse-2. */);
10837 Vmac_emulate_three_button_mouse = Qnil;
10839 #if USE_CARBON_EVENTS
10840 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2,
10841 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
10842 Otherwise, the right click will be treated as mouse-2 and the wheel
10843 button will be mouse-3. */);
10844 mac_wheel_button_is_mouse_2 = 1;
10846 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system,
10847 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
10848 mac_pass_command_to_system = 1;
10850 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system,
10851 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
10852 mac_pass_control_to_system = 1;
10854 #endif
10856 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics,
10857 doc: /* *If non-nil, allow anti-aliasing.
10858 The text will be rendered using Core Graphics text rendering which
10859 may anti-alias the text. */);
10860 mac_use_core_graphics = 0;
10862 /* Register an entry for `mac-roman' so that it can be used when
10863 creating the terminal frame on Mac OS 9 before loading
10864 term/mac-win.elc. */
10865 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
10866 doc: /* Alist of Emacs character sets vs text encodings and coding systems.
10867 Each entry should be of the form:
10869 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10871 where CHARSET-NAME is a string used in font names to identify the
10872 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
10873 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
10874 Vmac_charset_info_alist =
10875 Fcons (list3 (build_string ("mac-roman"),
10876 make_number (smRoman), Qnil), Qnil);
10879 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10880 (do not change this comment) */