(Fstring_as_multibyte): Escape backslashes in the
[emacs.git] / src / macterm.c
blob6fddcade274064bccbb13243ed75ff079b179bb9
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
24 #include <signal.h>
26 #include <stdio.h>
28 #include "lisp.h"
29 #include "blockinput.h"
31 #include "macterm.h"
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
37 #if TARGET_API_MAC_CARBON
38 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
40 used instead. */
41 #define USE_CARBON_EVENTS 1
42 #else /* not TARGET_API_MAC_CARBON */
43 #include <Quickdraw.h>
44 #include <ToolUtils.h>
45 #include <Sound.h>
46 #include <Events.h>
47 #include <Script.h>
48 #include <Resources.h>
49 #include <Fonts.h>
50 #include <TextUtils.h>
51 #include <LowMem.h>
52 #include <Controls.h>
53 #include <Windows.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
56 #endif
58 #if __profile__
59 #include <profiler.h>
60 #endif
61 #endif /* not TARGET_API_MAC_CARBON */
63 #include "systty.h"
64 #include "systime.h"
66 #include <ctype.h>
67 #include <errno.h>
68 #include <setjmp.h>
69 #include <sys/stat.h>
70 #include <sys/param.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"
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
95 : controlKey)
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
99 /* Non-nil means Emacs uses toolkit scroll bars. */
101 Lisp_Object Vx_toolkit_scroll_bars;
103 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
104 Lisp_Object Vmac_use_core_graphics;
107 /* Non-zero means that a HELP_EVENT has been generated since Emacs
108 start. */
110 static int any_help_event_p;
112 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
113 static Lisp_Object last_window;
115 /* This is a chain of structures for all the X displays currently in
116 use. */
118 struct x_display_info *x_display_list;
120 /* This is a list of cons cells, each of the form (NAME
121 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
122 x_display_list and in the same order. NAME is the name of the
123 frame. FONT-LIST-CACHE records previous values returned by
124 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
125 equivalent, which is implemented with a Lisp object, for the
126 display. */
128 Lisp_Object x_display_name_list;
130 /* This is display since Mac does not support multiple ones. */
131 struct mac_display_info one_mac_display_info;
133 /* Frame being updated by update_frame. This is declared in term.c.
134 This is set by update_begin and looked at by all the XT functions.
135 It is zero while not inside an update. In that case, the XT
136 functions assume that `selected_frame' is the frame to apply to. */
138 extern struct frame *updating_frame;
140 /* This is a frame waiting to be auto-raised, within XTread_socket. */
142 struct frame *pending_autoraise_frame;
144 /* Mouse movement.
146 Formerly, we used PointerMotionHintMask (in standard_event_mask)
147 so that we would have to call XQueryPointer after each MotionNotify
148 event to ask for another such event. However, this made mouse tracking
149 slow, and there was a bug that made it eventually stop.
151 Simply asking for MotionNotify all the time seems to work better.
153 In order to avoid asking for motion events and then throwing most
154 of them away or busy-polling the server for mouse positions, we ask
155 the server for pointer motion hints. This means that we get only
156 one event per group of mouse movements. "Groups" are delimited by
157 other kinds of events (focus changes and button clicks, for
158 example), or by XQueryPointer calls; when one of these happens, we
159 get another MotionNotify event the next time the mouse moves. This
160 is at least as efficient as getting motion events when mouse
161 tracking is on, and I suspect only negligibly worse when tracking
162 is off. */
164 /* Where the mouse was last time we reported a mouse event. */
166 static Rect last_mouse_glyph;
168 /* The scroll bar in which the last X motion event occurred.
170 If the last X motion event occurred in a scroll bar, we set this so
171 XTmouse_position can know whether to report a scroll bar motion or
172 an ordinary motion.
174 If the last X motion event didn't occur in a scroll bar, we set
175 this to Qnil, to tell XTmouse_position to return an ordinary motion
176 event. */
178 static Lisp_Object last_mouse_scroll_bar;
180 /* This is a hack. We would really prefer that XTmouse_position would
181 return the time associated with the position it returns, but there
182 doesn't seem to be any way to wrest the time-stamp from the server
183 along with the position query. So, we just keep track of the time
184 of the last movement we received, and return that in hopes that
185 it's somewhat accurate. */
187 static Time last_mouse_movement_time;
189 struct scroll_bar *tracked_scroll_bar = NULL;
191 /* Incremented by XTread_socket whenever it really tries to read
192 events. */
194 #ifdef __STDC__
195 static int volatile input_signal_count;
196 #else
197 static int input_signal_count;
198 #endif
200 extern Lisp_Object Vsystem_name;
202 /* A mask of extra modifier bits to put into every keyboard char. */
204 extern EMACS_INT extra_keyboard_modifiers;
206 /* The keysyms to use for the various modifiers. */
208 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
210 extern int inhibit_window_system;
212 #if __MRC__ && !TARGET_API_MAC_CARBON
213 QDGlobals qd; /* QuickDraw global information structure. */
214 #endif
216 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
218 struct mac_display_info *mac_display_info_for_display (Display *);
219 static void x_update_window_end P_ ((struct window *, int, int));
220 static int x_io_error_quitter P_ ((Display *));
221 int x_catch_errors P_ ((Display *));
222 void x_uncatch_errors P_ ((Display *, int));
223 void x_lower_frame P_ ((struct frame *));
224 void x_scroll_bar_clear P_ ((struct frame *));
225 int x_had_errors_p P_ ((Display *));
226 void x_wm_set_size_hint P_ ((struct frame *, long, int));
227 void x_raise_frame P_ ((struct frame *));
228 void x_set_window_size P_ ((struct frame *, int, int, int));
229 void x_wm_set_window_state P_ ((struct frame *, int));
230 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
231 void mac_initialize P_ ((void));
232 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
233 static int x_compute_min_glyph_bounds P_ ((struct frame *));
234 static void x_update_end P_ ((struct frame *));
235 static void XTframe_up_to_date P_ ((struct frame *));
236 static void XTset_terminal_modes P_ ((void));
237 static void XTreset_terminal_modes P_ ((void));
238 static void x_clear_frame P_ ((void));
239 static void frame_highlight P_ ((struct frame *));
240 static void frame_unhighlight P_ ((struct frame *));
241 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
242 static void mac_focus_changed P_ ((int, struct mac_display_info *,
243 struct frame *, struct input_event *));
244 static void x_detect_focus_change P_ ((struct mac_display_info *,
245 EventRecord *, struct input_event *));
246 static void XTframe_rehighlight P_ ((struct frame *));
247 static void x_frame_rehighlight P_ ((struct x_display_info *));
248 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
249 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
250 enum text_cursor_kinds));
252 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
253 static void x_flush P_ ((struct frame *f));
254 static void x_update_begin P_ ((struct frame *));
255 static void x_update_window_begin P_ ((struct window *));
256 static void x_after_update_window_line P_ ((struct glyph_row *));
257 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
258 enum scroll_bar_part *,
259 Lisp_Object *, Lisp_Object *,
260 unsigned long *));
262 static int is_emacs_window P_ ((WindowPtr));
264 static void XSetFont P_ ((Display *, GC, XFontStruct *));
266 /* Defined in macmenu.h. */
267 extern void menubar_selection_callback (FRAME_PTR, int);
269 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
270 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
271 #define GC_FONT(gc) ((gc)->xgcv.font)
272 #define MAC_WINDOW_NORMAL_GC(w) (((mac_output *) GetWRefCon (w))->normal_gc)
275 /* X display function emulation */
277 void
278 XFreePixmap (display, pixmap)
279 Display *display; /* not used */
280 Pixmap pixmap;
282 DisposeGWorld (pixmap);
286 /* Mac version of XDrawLine. */
288 static void
289 XDrawLine (display, w, gc, x1, y1, x2, y2)
290 Display *display;
291 WindowPtr w;
292 GC gc;
293 int x1, y1, x2, y2;
295 SetPortWindowPort (w);
297 RGBForeColor (GC_FORE_COLOR (gc));
299 MoveTo (x1, y1);
300 LineTo (x2, y2);
303 void
304 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
305 Display *display;
306 Pixmap p;
307 GC gc;
308 int x1, y1, x2, y2;
310 CGrafPtr old_port;
311 GDHandle old_gdh;
313 GetGWorld (&old_port, &old_gdh);
314 SetGWorld (p, NULL);
316 RGBForeColor (GC_FORE_COLOR (gc));
318 LockPixels (GetGWorldPixMap (p));
319 MoveTo (x1, y1);
320 LineTo (x2, y2);
321 UnlockPixels (GetGWorldPixMap (p));
323 SetGWorld (old_port, old_gdh);
327 static void
328 mac_erase_rectangle (w, gc, x, y, width, height)
329 WindowPtr w;
330 GC gc;
331 int x, y;
332 unsigned int width, height;
334 Rect r;
336 SetPortWindowPort (w);
338 RGBBackColor (GC_BACK_COLOR (gc));
339 SetRect (&r, x, y, x + width, y + height);
341 EraseRect (&r);
343 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
347 /* Mac version of XClearArea. */
349 void
350 XClearArea (display, w, x, y, width, height, exposures)
351 Display *display;
352 WindowPtr w;
353 int x, y;
354 unsigned int width, height;
355 int exposures;
357 mac_erase_rectangle (w, MAC_WINDOW_NORMAL_GC (w), x, y, width, height);
360 /* Mac version of XClearWindow. */
362 static void
363 XClearWindow (display, w)
364 Display *display;
365 WindowPtr w;
367 SetPortWindowPort (w);
369 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
371 #if TARGET_API_MAC_CARBON
373 Rect r;
375 GetWindowPortBounds (w, &r);
376 EraseRect (&r);
378 #else /* not TARGET_API_MAC_CARBON */
379 EraseRect (&(w->portRect));
380 #endif /* not TARGET_API_MAC_CARBON */
384 /* Mac replacement for XCopyArea. */
386 static void
387 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
388 Display *display;
389 WindowPtr w;
390 GC gc;
391 int x, y, width, height;
392 unsigned short *bits;
393 int overlay_p;
395 BitMap bitmap;
396 Rect r;
398 bitmap.rowBytes = sizeof(unsigned short);
399 bitmap.baseAddr = (char *)bits;
400 SetRect (&(bitmap.bounds), 0, 0, width, height);
402 SetPortWindowPort (w);
404 RGBForeColor (GC_FORE_COLOR (gc));
405 RGBBackColor (GC_BACK_COLOR (gc));
406 SetRect (&r, x, y, x + width, y + height);
408 #if TARGET_API_MAC_CARBON
409 LockPortBits (GetWindowPort (w));
410 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
411 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
412 UnlockPortBits (GetWindowPort (w));
413 #else /* not TARGET_API_MAC_CARBON */
414 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
415 overlay_p ? srcOr : srcCopy, 0);
416 #endif /* not TARGET_API_MAC_CARBON */
418 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
422 /* Mac replacement for XSetClipRectangles. */
424 static void
425 mac_set_clip_rectangle (display, w, r)
426 Display *display;
427 WindowPtr w;
428 Rect *r;
430 SetPortWindowPort (w);
432 ClipRect (r);
436 /* Mac replacement for XSetClipMask. */
438 static void
439 mac_reset_clipping (display, w)
440 Display *display;
441 WindowPtr w;
443 Rect r;
445 SetPortWindowPort (w);
447 SetRect (&r, -32767, -32767, 32767, 32767);
448 ClipRect (&r);
452 /* Mac replacement for XCreateBitmapFromBitmapData. */
454 static void
455 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
456 BitMap *bitmap;
457 char *bits;
458 int w, h;
460 static unsigned char swap_nibble[16]
461 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
462 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
463 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
464 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
465 int i, j, w1;
466 char *p;
468 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
469 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
470 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
471 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
472 for (i = 0; i < h; i++)
474 p = bitmap->baseAddr + i * bitmap->rowBytes;
475 for (j = 0; j < w1; j++)
477 /* Bitswap XBM bytes to match how Mac does things. */
478 unsigned char c = *bits++;
479 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
480 | (swap_nibble[(c>>4) & 0xf]));;
484 SetRect (&(bitmap->bounds), 0, 0, w, h);
488 static void
489 mac_free_bitmap (bitmap)
490 BitMap *bitmap;
492 xfree (bitmap->baseAddr);
496 Pixmap
497 XCreatePixmap (display, w, width, height, depth)
498 Display *display; /* not used */
499 WindowPtr w;
500 unsigned int width, height;
501 unsigned int depth;
503 Pixmap pixmap;
504 Rect r;
505 QDErr err;
507 SetPortWindowPort (w);
509 SetRect (&r, 0, 0, width, height);
510 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
511 if (err != noErr)
512 return NULL;
513 return pixmap;
517 Pixmap
518 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
519 Display *display; /* not used */
520 WindowPtr w;
521 char *data;
522 unsigned int width, height;
523 unsigned long fg, bg;
524 unsigned int depth;
526 Pixmap pixmap;
527 BitMap bitmap;
528 CGrafPtr old_port;
529 GDHandle old_gdh;
530 static GC gc = NULL; /* not reentrant */
532 if (gc == NULL)
533 gc = XCreateGC (display, w, 0, NULL);
535 pixmap = XCreatePixmap (display, w, width, height, depth);
536 if (pixmap == NULL)
537 return NULL;
539 GetGWorld (&old_port, &old_gdh);
540 SetGWorld (pixmap, NULL);
541 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
542 XSetForeground (display, gc, fg);
543 XSetBackground (display, gc, bg);
544 RGBForeColor (GC_FORE_COLOR (gc));
545 RGBBackColor (GC_BACK_COLOR (gc));
546 LockPixels (GetGWorldPixMap (pixmap));
547 #if TARGET_API_MAC_CARBON
548 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
549 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
550 #else /* not TARGET_API_MAC_CARBON */
551 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
552 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
553 #endif /* not TARGET_API_MAC_CARBON */
554 UnlockPixels (GetGWorldPixMap (pixmap));
555 SetGWorld (old_port, old_gdh);
556 mac_free_bitmap (&bitmap);
558 return pixmap;
562 /* Mac replacement for XFillRectangle. */
564 static void
565 XFillRectangle (display, w, gc, x, y, width, height)
566 Display *display;
567 WindowPtr w;
568 GC gc;
569 int x, y;
570 unsigned int width, height;
572 Rect r;
574 SetPortWindowPort (w);
576 RGBForeColor (GC_FORE_COLOR (gc));
577 SetRect (&r, x, y, x + width, y + height);
579 PaintRect (&r); /* using foreground color of gc */
583 #if 0 /* TODO: figure out if we need to do this on Mac. */
584 static void
585 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
586 Display *display;
587 Pixmap p;
588 GC gc;
589 int x, y;
590 unsigned int width, height;
592 CGrafPtr old_port;
593 GDHandle old_gdh;
594 Rect r;
596 GetGWorld (&old_port, &old_gdh);
597 SetGWorld (p, NULL);
598 RGBForeColor (GC_FORE_COLOR (gc));
599 SetRect (&r, x, y, x + width, y + height);
601 LockPixels (GetGWorldPixMap (p));
602 PaintRect (&r); /* using foreground color of gc */
603 UnlockPixels (GetGWorldPixMap (p));
605 SetGWorld (old_port, old_gdh);
607 #endif
610 /* Mac replacement for XDrawRectangle: dest is a window. */
612 static void
613 mac_draw_rectangle (display, w, gc, x, y, width, height)
614 Display *display;
615 WindowPtr w;
616 GC gc;
617 int x, y;
618 unsigned int width, height;
620 Rect r;
622 SetPortWindowPort (w);
624 RGBForeColor (GC_FORE_COLOR (gc));
625 SetRect (&r, x, y, x + width + 1, y + height + 1);
627 FrameRect (&r); /* using foreground color of gc */
631 #if 0 /* TODO: figure out if we need to do this on Mac. */
632 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
634 static void
635 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
636 Display *display;
637 Pixmap p;
638 GC gc;
639 int x, y;
640 unsigned int width, height;
642 CGrafPtr old_port;
643 GDHandle old_gdh;
644 Rect r;
646 GetGWorld (&old_port, &old_gdh);
647 SetGWorld (p, NULL);
648 RGBForeColor (GC_FORE_COLOR (gc));
649 SetRect (&r, x, y, x + width + 1, y + height + 1);
651 LockPixels (GetGWorldPixMap (p));
652 FrameRect (&r); /* using foreground color of gc */
653 UnlockPixels (GetGWorldPixMap (p));
655 SetGWorld (old_port, old_gdh);
657 #endif
660 static void
661 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
662 bytes_per_char)
663 Display *display;
664 WindowPtr w;
665 GC gc;
666 int x, y;
667 char *buf;
668 int nchars, mode, bytes_per_char;
670 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
671 UInt32 textFlags, savedFlags;
672 if (!NILP(Vmac_use_core_graphics)) {
673 textFlags = kQDUseCGTextRendering;
674 savedFlags = SwapQDTextFlags(textFlags);
676 #endif
678 SetPortWindowPort (w);
680 RGBForeColor (GC_FORE_COLOR (gc));
681 if (mode != srcOr)
682 RGBBackColor (GC_BACK_COLOR (gc));
684 TextFont (GC_FONT (gc)->mac_fontnum);
685 TextSize (GC_FONT (gc)->mac_fontsize);
686 TextFace (GC_FONT (gc)->mac_fontface);
687 TextMode (mode);
689 MoveTo (x, y);
690 DrawText (buf, 0, nchars * bytes_per_char);
692 if (mode != srcOr)
693 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
694 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
695 if (!NILP(Vmac_use_core_graphics))
696 SwapQDTextFlags(savedFlags);
697 #endif
701 /* Mac replacement for XDrawString. */
703 static void
704 XDrawString (display, w, gc, x, y, buf, nchars)
705 Display *display;
706 WindowPtr w;
707 GC gc;
708 int x, y;
709 char *buf;
710 int nchars;
712 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
716 /* Mac replacement for XDrawString16. */
718 static void
719 XDrawString16 (display, w, gc, x, y, buf, nchars)
720 Display *display;
721 WindowPtr w;
722 GC gc;
723 int x, y;
724 XChar2b *buf;
725 int nchars;
727 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
732 /* Mac replacement for XDrawImageString. */
734 static void
735 XDrawImageString (display, w, gc, x, y, buf, nchars)
736 Display *display;
737 WindowPtr w;
738 GC gc;
739 int x, y;
740 char *buf;
741 int nchars;
743 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
747 /* Mac replacement for XDrawString16. */
749 static void
750 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
751 Display *display;
752 WindowPtr w;
753 GC gc;
754 int x, y;
755 XChar2b *buf;
756 int nchars;
758 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
763 /* Mac replacement for XCopyArea: dest must be window. */
765 static void
766 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
767 dest_y)
768 Display *display;
769 Pixmap src;
770 WindowPtr dest;
771 GC gc;
772 int src_x, src_y;
773 unsigned int width, height;
774 int dest_x, dest_y;
776 Rect src_r, dest_r;
778 SetPortWindowPort (dest);
780 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
781 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
783 ForeColor (blackColor);
784 BackColor (whiteColor);
786 LockPixels (GetGWorldPixMap (src));
787 #if TARGET_API_MAC_CARBON
788 LockPortBits (GetWindowPort (dest));
789 CopyBits (GetPortBitMapForCopyBits (src),
790 GetPortBitMapForCopyBits (GetWindowPort (dest)),
791 &src_r, &dest_r, srcCopy, 0);
792 UnlockPortBits (GetWindowPort (dest));
793 #else /* not TARGET_API_MAC_CARBON */
794 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
795 &src_r, &dest_r, srcCopy, 0);
796 #endif /* not TARGET_API_MAC_CARBON */
797 UnlockPixels (GetGWorldPixMap (src));
801 static void
802 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
803 width, height, dest_x, dest_y)
804 Display *display;
805 Pixmap src, mask;
806 WindowPtr dest;
807 GC gc;
808 int src_x, src_y;
809 unsigned int width, height;
810 int dest_x, dest_y;
812 Rect src_r, dest_r;
814 SetPortWindowPort (dest);
816 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
817 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
819 ForeColor (blackColor);
820 BackColor (whiteColor);
822 LockPixels (GetGWorldPixMap (src));
823 LockPixels (GetGWorldPixMap (mask));
824 #if TARGET_API_MAC_CARBON
825 LockPortBits (GetWindowPort (dest));
826 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
827 GetPortBitMapForCopyBits (GetWindowPort (dest)),
828 &src_r, &src_r, &dest_r);
829 UnlockPortBits (GetWindowPort (dest));
830 #else /* not TARGET_API_MAC_CARBON */
831 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
832 &(dest->portBits), &src_r, &src_r, &dest_r);
833 #endif /* not TARGET_API_MAC_CARBON */
834 UnlockPixels (GetGWorldPixMap (mask));
835 UnlockPixels (GetGWorldPixMap (src));
839 /* Mac replacement for XCopyArea: used only for scrolling. */
841 static void
842 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
843 Display *display;
844 WindowPtr w;
845 GC gc;
846 int src_x, src_y;
847 unsigned int width, height;
848 int dest_x, dest_y;
850 #if TARGET_API_MAC_CARBON
851 Rect src_r;
852 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
854 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
855 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
856 kScrollWindowNoOptions, dummy);
857 DisposeRgn (dummy);
858 #else /* not TARGET_API_MAC_CARBON */
859 Rect src_r, dest_r;
861 SetPort (w);
863 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
864 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
866 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
867 color mapping in CopyBits. Otherwise, it will be slow. */
868 ForeColor (blackColor);
869 BackColor (whiteColor);
870 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
872 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w)));
873 #endif /* not TARGET_API_MAC_CARBON */
877 #if 0 /* TODO: figure out if we need to do this on Mac. */
878 /* Mac replacement for XCopyArea: dest must be Pixmap. */
880 static void
881 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
882 dest_x, dest_y)
883 Display *display;
884 Pixmap src, dest;
885 GC gc;
886 int src_x, src_y;
887 unsigned int width, height;
888 int dest_x, dest_y;
890 CGrafPtr old_port;
891 GDHandle old_gdh;
892 Rect src_r, dest_r;
894 GetGWorld (&old_port, &old_gdh);
895 SetGWorld (dest, NULL);
896 ForeColor (blackColor);
897 BackColor (whiteColor);
899 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
900 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
902 LockPixels (GetGWorldPixMap (src));
903 LockPixels (GetGWorldPixMap (dest));
904 #if TARGET_API_MAC_CARBON
905 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
906 &src_r, &dest_r, srcCopy, 0);
907 #else /* not TARGET_API_MAC_CARBON */
908 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
909 &src_r, &dest_r, srcCopy, 0);
910 #endif /* not TARGET_API_MAC_CARBON */
911 UnlockPixels (GetGWorldPixMap (dest));
912 UnlockPixels (GetGWorldPixMap (src));
914 SetGWorld (old_port, old_gdh);
918 static void
919 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
920 width, height, dest_x, dest_y)
921 Display *display;
922 Pixmap src, mask, dest;
923 GC gc;
924 int src_x, src_y;
925 unsigned int width, height;
926 int dest_x, dest_y;
928 CGrafPtr old_port;
929 GDHandle old_gdh;
930 Rect src_r, dest_r;
932 GetGWorld (&old_port, &old_gdh);
933 SetGWorld (dest, NULL);
934 ForeColor (blackColor);
935 BackColor (whiteColor);
937 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
938 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
940 LockPixels (GetGWorldPixMap (src));
941 LockPixels (GetGWorldPixMap (mask));
942 LockPixels (GetGWorldPixMap (dest));
943 #if TARGET_API_MAC_CARBON
944 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
945 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
946 #else /* not TARGET_API_MAC_CARBON */
947 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
948 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
949 #endif /* not TARGET_API_MAC_CARBON */
950 UnlockPixels (GetGWorldPixMap (dest));
951 UnlockPixels (GetGWorldPixMap (mask));
952 UnlockPixels (GetGWorldPixMap (src));
954 SetGWorld (old_port, old_gdh);
956 #endif
959 /* Mac replacement for XChangeGC. */
961 static void
962 XChangeGC (display, gc, mask, xgcv)
963 Display *display;
964 GC gc;
965 unsigned long mask;
966 XGCValues *xgcv;
968 if (mask & GCForeground)
969 XSetForeground (display, gc, xgcv->foreground);
970 if (mask & GCBackground)
971 XSetBackground (display, gc, xgcv->background);
972 if (mask & GCFont)
973 XSetFont (display, gc, xgcv->font);
977 /* Mac replacement for XCreateGC. */
980 XCreateGC (display, window, mask, xgcv)
981 Display *display;
982 Window window;
983 unsigned long mask;
984 XGCValues *xgcv;
986 GC gc = xmalloc (sizeof (*gc));
988 if (gc)
990 bzero (gc, sizeof (*gc));
991 XChangeGC (display, gc, mask, xgcv);
994 return gc;
998 /* Used in xfaces.c. */
1000 void
1001 XFreeGC (display, gc)
1002 Display *display;
1003 GC gc;
1005 xfree (gc);
1009 /* Mac replacement for XGetGCValues. */
1011 static void
1012 XGetGCValues (display, gc, mask, xgcv)
1013 Display *display;
1014 GC gc;
1015 unsigned long mask;
1016 XGCValues *xgcv;
1018 if (mask & GCForeground)
1019 xgcv->foreground = gc->xgcv.foreground;
1020 if (mask & GCBackground)
1021 xgcv->background = gc->xgcv.background;
1022 if (mask & GCFont)
1023 xgcv->font = gc->xgcv.font;
1027 /* Mac replacement for XSetForeground. */
1029 void
1030 XSetForeground (display, gc, color)
1031 Display *display;
1032 GC gc;
1033 unsigned long color;
1035 if (gc->xgcv.foreground != color)
1037 gc->xgcv.foreground = color;
1038 gc->fore_color.red = RED16_FROM_ULONG (color);
1039 gc->fore_color.green = GREEN16_FROM_ULONG (color);
1040 gc->fore_color.blue = BLUE16_FROM_ULONG (color);
1045 /* Mac replacement for XSetBackground. */
1047 void
1048 XSetBackground (display, gc, color)
1049 Display *display;
1050 GC gc;
1051 unsigned long color;
1053 if (gc->xgcv.background != color)
1055 gc->xgcv.background = color;
1056 gc->back_color.red = RED16_FROM_ULONG (color);
1057 gc->back_color.green = GREEN16_FROM_ULONG (color);
1058 gc->back_color.blue = BLUE16_FROM_ULONG (color);
1063 /* Mac replacement for XSetFont. */
1065 static void
1066 XSetFont (display, gc, font)
1067 Display *display;
1068 GC gc;
1069 XFontStruct *font;
1071 gc->xgcv.font = font;
1075 /* Mac replacement for XSetWindowBackground. */
1077 void
1078 XSetWindowBackground (display, w, color)
1079 Display *display;
1080 WindowPtr w;
1081 unsigned long color;
1083 #if !TARGET_API_MAC_CARBON
1084 AuxWinHandle aw_handle;
1085 CTabHandle ctab_handle;
1086 ColorSpecPtr ct_table;
1087 short ct_size;
1088 #endif
1089 RGBColor bg_color;
1091 bg_color.red = RED16_FROM_ULONG (color);
1092 bg_color.green = GREEN16_FROM_ULONG (color);
1093 bg_color.blue = BLUE16_FROM_ULONG (color);
1095 #if TARGET_API_MAC_CARBON
1096 SetWindowContentColor (w, &bg_color);
1097 #else
1098 if (GetAuxWin (w, &aw_handle))
1100 ctab_handle = (*aw_handle)->awCTable;
1101 HandToHand ((Handle *) &ctab_handle);
1102 ct_table = (*ctab_handle)->ctTable;
1103 ct_size = (*ctab_handle)->ctSize;
1104 while (ct_size > -1)
1106 if (ct_table->value == 0)
1108 ct_table->rgb = bg_color;
1109 CTabChanged (ctab_handle);
1110 SetWinColor (w, (WCTabHandle) ctab_handle);
1112 ct_size--;
1115 #endif
1118 /* x_sync is a no-op on Mac. */
1119 void
1120 x_sync (f)
1121 void *f;
1126 /* Flush display of frame F, or of all frames if F is null. */
1128 static void
1129 x_flush (f)
1130 struct frame *f;
1132 #if TARGET_API_MAC_CARBON
1133 BLOCK_INPUT;
1134 if (f)
1135 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1136 else
1137 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1138 UNBLOCK_INPUT;
1139 #endif
1143 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1144 Calls to XFlush should be unnecessary because the X output buffer
1145 is flushed automatically as needed by calls to XPending,
1146 XNextEvent, or XWindowEvent according to the XFlush man page.
1147 XTread_socket calls XPending. Removing XFlush improves
1148 performance. */
1150 #define XFlush(DISPLAY) (void) 0
1153 /* Return the struct mac_display_info corresponding to DPY. There's
1154 only one. */
1156 struct mac_display_info *
1157 mac_display_info_for_display (dpy)
1158 Display *dpy;
1160 return &one_mac_display_info;
1165 /***********************************************************************
1166 Starting and ending an update
1167 ***********************************************************************/
1169 /* Start an update of frame F. This function is installed as a hook
1170 for update_begin, i.e. it is called when update_begin is called.
1171 This function is called prior to calls to x_update_window_begin for
1172 each window being updated. */
1174 static void
1175 x_update_begin (f)
1176 struct frame *f;
1178 #if TARGET_API_MAC_CARBON
1179 /* During update of a frame, availability of input events is
1180 periodically checked with ReceiveNextEvent if
1181 redisplay-dont-pause is nil. That normally flushes window buffer
1182 changes for every check, and thus screen update looks waving even
1183 if no input is available. So we disable screen updates during
1184 update of a frame. */
1185 BLOCK_INPUT;
1186 DisableScreenUpdates ();
1187 UNBLOCK_INPUT;
1188 #endif
1192 /* Start update of window W. Set the global variable updated_window
1193 to the window being updated and set output_cursor to the cursor
1194 position of W. */
1196 static void
1197 x_update_window_begin (w)
1198 struct window *w;
1200 struct frame *f = XFRAME (WINDOW_FRAME (w));
1201 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1203 updated_window = w;
1204 set_output_cursor (&w->cursor);
1206 BLOCK_INPUT;
1208 if (f == display_info->mouse_face_mouse_frame)
1210 /* Don't do highlighting for mouse motion during the update. */
1211 display_info->mouse_face_defer = 1;
1213 /* If F needs to be redrawn, simply forget about any prior mouse
1214 highlighting. */
1215 if (FRAME_GARBAGED_P (f))
1216 display_info->mouse_face_window = Qnil;
1218 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1219 their mouse_face_p flag set, which means that they are always
1220 unequal to rows in a desired matrix which never have that
1221 flag set. So, rows containing mouse-face glyphs are never
1222 scrolled, and we don't have to switch the mouse highlight off
1223 here to prevent it from being scrolled. */
1225 /* Can we tell that this update does not affect the window
1226 where the mouse highlight is? If so, no need to turn off.
1227 Likewise, don't do anything if the frame is garbaged;
1228 in that case, the frame's current matrix that we would use
1229 is all wrong, and we will redisplay that line anyway. */
1230 if (!NILP (display_info->mouse_face_window)
1231 && w == XWINDOW (display_info->mouse_face_window))
1233 int i;
1235 for (i = 0; i < w->desired_matrix->nrows; ++i)
1236 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1237 break;
1239 if (i < w->desired_matrix->nrows)
1240 clear_mouse_face (display_info);
1242 #endif /* 0 */
1245 UNBLOCK_INPUT;
1249 /* Draw a vertical window border from (x,y0) to (x,y1) */
1251 static void
1252 mac_draw_vertical_window_border (w, x, y0, y1)
1253 struct window *w;
1254 int x, y0, y1;
1256 struct frame *f = XFRAME (WINDOW_FRAME (w));
1257 struct face *face;
1259 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
1260 if (face)
1261 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
1262 face->foreground);
1264 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1265 f->output_data.mac->normal_gc, x, y0, x, y1);
1268 /* End update of window W (which is equal to updated_window).
1270 Draw vertical borders between horizontally adjacent windows, and
1271 display W's cursor if CURSOR_ON_P is non-zero.
1273 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1274 glyphs in mouse-face were overwritten. In that case we have to
1275 make sure that the mouse-highlight is properly redrawn.
1277 W may be a menu bar pseudo-window in case we don't have X toolkit
1278 support. Such windows don't have a cursor, so don't display it
1279 here. */
1281 static void
1282 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1283 struct window *w;
1284 int cursor_on_p, mouse_face_overwritten_p;
1286 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1288 if (!w->pseudo_window_p)
1290 BLOCK_INPUT;
1292 if (cursor_on_p)
1293 display_and_set_cursor (w, 1, output_cursor.hpos,
1294 output_cursor.vpos,
1295 output_cursor.x, output_cursor.y);
1297 if (draw_window_fringes (w, 1))
1298 x_draw_vertical_border (w);
1300 UNBLOCK_INPUT;
1303 /* If a row with mouse-face was overwritten, arrange for
1304 XTframe_up_to_date to redisplay the mouse highlight. */
1305 if (mouse_face_overwritten_p)
1307 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1308 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1309 dpyinfo->mouse_face_window = Qnil;
1312 updated_window = NULL;
1316 /* End update of frame F. This function is installed as a hook in
1317 update_end. */
1319 static void
1320 x_update_end (f)
1321 struct frame *f;
1323 /* Mouse highlight may be displayed again. */
1324 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1326 BLOCK_INPUT;
1327 #if TARGET_API_MAC_CARBON
1328 EnableScreenUpdates ();
1329 #endif
1330 XFlush (FRAME_MAC_DISPLAY (f));
1331 UNBLOCK_INPUT;
1335 /* This function is called from various places in xdisp.c whenever a
1336 complete update has been performed. The global variable
1337 updated_window is not available here. */
1339 static void
1340 XTframe_up_to_date (f)
1341 struct frame *f;
1343 if (FRAME_MAC_P (f))
1345 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1347 if (dpyinfo->mouse_face_deferred_gc
1348 || f == dpyinfo->mouse_face_mouse_frame)
1350 BLOCK_INPUT;
1351 if (dpyinfo->mouse_face_mouse_frame)
1352 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1353 dpyinfo->mouse_face_mouse_x,
1354 dpyinfo->mouse_face_mouse_y);
1355 dpyinfo->mouse_face_deferred_gc = 0;
1356 UNBLOCK_INPUT;
1362 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1363 arrow bitmaps, or clear the fringes if no bitmaps are required
1364 before DESIRED_ROW is made current. The window being updated is
1365 found in updated_window. This function is called from
1366 update_window_line only if it is known that there are differences
1367 between bitmaps to be drawn between current row and DESIRED_ROW. */
1369 static void
1370 x_after_update_window_line (desired_row)
1371 struct glyph_row *desired_row;
1373 struct window *w = updated_window;
1374 struct frame *f;
1375 int width, height;
1377 xassert (w);
1379 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1380 desired_row->redraw_fringe_bitmaps_p = 1;
1382 /* When a window has disappeared, make sure that no rest of
1383 full-width rows stays visible in the internal border. Could
1384 check here if updated_window is the leftmost/rightmost window,
1385 but I guess it's not worth doing since vertically split windows
1386 are almost never used, internal border is rarely set, and the
1387 overhead is very small. */
1388 if (windows_or_buffers_changed
1389 && desired_row->full_width_p
1390 && (f = XFRAME (w->frame),
1391 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1392 width != 0)
1393 && (height = desired_row->visible_height,
1394 height > 0))
1396 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1398 /* Internal border is drawn below the tool bar. */
1399 if (WINDOWP (f->tool_bar_window)
1400 && w == XWINDOW (f->tool_bar_window))
1401 y -= width;
1403 BLOCK_INPUT;
1404 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1405 0, y, width, height, 0);
1406 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1407 FRAME_PIXEL_WIDTH (f) - width, y,
1408 width, height, 0);
1409 UNBLOCK_INPUT;
1414 /* Draw the bitmap WHICH in one of the left or right fringes of
1415 window W. ROW is the glyph row for which to display the bitmap; it
1416 determines the vertical position at which the bitmap has to be
1417 drawn. */
1419 static void
1420 x_draw_fringe_bitmap (w, row, p)
1421 struct window *w;
1422 struct glyph_row *row;
1423 struct draw_fringe_bitmap_params *p;
1425 struct frame *f = XFRAME (WINDOW_FRAME (w));
1426 Display *display = FRAME_MAC_DISPLAY (f);
1427 WindowPtr window = FRAME_MAC_WINDOW (f);
1428 GC gc = f->output_data.mac->normal_gc;
1429 struct face *face = p->face;
1430 int rowY;
1432 /* Must clip because of partially visible lines. */
1433 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1434 if (p->y < rowY)
1436 /* Adjust position of "bottom aligned" bitmap on partially
1437 visible last row. */
1438 int oldY = row->y;
1439 int oldVH = row->visible_height;
1440 row->visible_height = p->h;
1441 row->y -= rowY - p->y;
1442 x_clip_to_row (w, row, -1, gc);
1443 row->y = oldY;
1444 row->visible_height = oldVH;
1446 else
1447 x_clip_to_row (w, row, -1, gc);
1449 if (p->bx >= 0 && !p->overlay_p)
1451 #if 0 /* MAC_TODO: stipple */
1452 /* In case the same realized face is used for fringes and
1453 for something displayed in the text (e.g. face `region' on
1454 mono-displays, the fill style may have been changed to
1455 FillSolid in x_draw_glyph_string_background. */
1456 if (face->stipple)
1457 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1458 else
1459 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1460 #endif
1462 mac_erase_rectangle (window, face->gc, p->bx, p->by, p->nx, p->ny);
1464 #if 0 /* MAC_TODO: stipple */
1465 if (!face->stipple)
1466 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1467 #endif
1470 if (p->which)
1472 unsigned short *bits = p->bits + p->dh;
1473 XGCValues gcv;
1475 XGetGCValues (display, face->gc, GCForeground, &gcv);
1476 XSetForeground (display, face->gc,
1477 (p->cursor_p
1478 ? (p->overlay_p ? face->background
1479 : f->output_data.mac->cursor_pixel)
1480 : face->foreground));
1481 mac_draw_bitmap (display, window, face->gc, p->x, p->y,
1482 p->wd, p->h, bits, p->overlay_p);
1483 XSetForeground (display, face->gc, gcv.foreground);
1486 mac_reset_clipping (display, window);
1491 /* This is called when starting Emacs and when restarting after
1492 suspend. When starting Emacs, no window is mapped. And nothing
1493 must be done to Emacs's own window if it is suspended (though that
1494 rarely happens). */
1496 static void
1497 XTset_terminal_modes ()
1501 /* This is called when exiting or suspending Emacs. Exiting will make
1502 the windows go away, and suspending requires no action. */
1504 static void
1505 XTreset_terminal_modes ()
1511 /***********************************************************************
1512 Display Iterator
1513 ***********************************************************************/
1515 /* Function prototypes of this page. */
1517 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1518 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1521 /* Return a pointer to per-char metric information in FONT of a
1522 character pointed by B which is a pointer to an XChar2b. */
1524 #define PER_CHAR_METRIC(font, b) \
1525 ((font)->per_char \
1526 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1527 + (((font)->min_byte1 || (font)->max_byte1) \
1528 ? (((b)->byte1 - (font)->min_byte1) \
1529 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1530 : 0)) \
1531 : &((font)->max_bounds))
1534 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1535 is not contained in the font. */
1537 static INLINE XCharStruct *
1538 x_per_char_metric (font, char2b)
1539 XFontStruct *font;
1540 XChar2b *char2b;
1542 /* The result metric information. */
1543 XCharStruct *pcm = NULL;
1545 xassert (font && char2b);
1547 if (font->per_char != NULL)
1549 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1551 /* min_char_or_byte2 specifies the linear character index
1552 corresponding to the first element of the per_char array,
1553 max_char_or_byte2 is the index of the last character. A
1554 character with non-zero CHAR2B->byte1 is not in the font.
1555 A character with byte2 less than min_char_or_byte2 or
1556 greater max_char_or_byte2 is not in the font. */
1557 if (char2b->byte1 == 0
1558 && char2b->byte2 >= font->min_char_or_byte2
1559 && char2b->byte2 <= font->max_char_or_byte2)
1560 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1562 else
1564 /* If either min_byte1 or max_byte1 are nonzero, both
1565 min_char_or_byte2 and max_char_or_byte2 are less than
1566 256, and the 2-byte character index values corresponding
1567 to the per_char array element N (counting from 0) are:
1569 byte1 = N/D + min_byte1
1570 byte2 = N\D + min_char_or_byte2
1572 where:
1574 D = max_char_or_byte2 - min_char_or_byte2 + 1
1575 / = integer division
1576 \ = integer modulus */
1577 if (char2b->byte1 >= font->min_byte1
1578 && char2b->byte1 <= font->max_byte1
1579 && char2b->byte2 >= font->min_char_or_byte2
1580 && char2b->byte2 <= font->max_char_or_byte2)
1582 pcm = (font->per_char
1583 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1584 * (char2b->byte1 - font->min_byte1))
1585 + (char2b->byte2 - font->min_char_or_byte2));
1589 else
1591 /* If the per_char pointer is null, all glyphs between the first
1592 and last character indexes inclusive have the same
1593 information, as given by both min_bounds and max_bounds. */
1594 if (char2b->byte2 >= font->min_char_or_byte2
1595 && char2b->byte2 <= font->max_char_or_byte2)
1596 pcm = &font->max_bounds;
1599 return ((pcm == NULL
1600 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1601 ? NULL : pcm);
1604 /* RIF:
1607 static XCharStruct *
1608 mac_per_char_metric (font, char2b, font_type)
1609 XFontStruct *font;
1610 XChar2b *char2b;
1611 int font_type;
1613 return x_per_char_metric (font, char2b);
1616 /* RIF:
1617 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1618 the two-byte form of C. Encoding is returned in *CHAR2B. */
1620 static int
1621 mac_encode_char (c, char2b, font_info, two_byte_p)
1622 int c;
1623 XChar2b *char2b;
1624 struct font_info *font_info;
1625 int *two_byte_p;
1627 int charset = CHAR_CHARSET (c);
1628 XFontStruct *font = font_info->font;
1630 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1631 This may be either a program in a special encoder language or a
1632 fixed encoding. */
1633 if (font_info->font_encoder)
1635 /* It's a program. */
1636 struct ccl_program *ccl = font_info->font_encoder;
1638 check_ccl_update (ccl);
1639 if (CHARSET_DIMENSION (charset) == 1)
1641 ccl->reg[0] = charset;
1642 ccl->reg[1] = char2b->byte2;
1643 ccl->reg[2] = -1;
1645 else
1647 ccl->reg[0] = charset;
1648 ccl->reg[1] = char2b->byte1;
1649 ccl->reg[2] = char2b->byte2;
1652 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1654 /* We assume that MSBs are appropriately set/reset by CCL
1655 program. */
1656 if (font->max_byte1 == 0) /* 1-byte font */
1657 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1658 else
1659 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1661 else if (font_info->encoding[charset])
1663 /* Fixed encoding scheme. See fontset.h for the meaning of the
1664 encoding numbers. */
1665 int enc = font_info->encoding[charset];
1667 if ((enc == 1 || enc == 2)
1668 && CHARSET_DIMENSION (charset) == 2)
1669 char2b->byte1 |= 0x80;
1671 if (enc == 1 || enc == 3)
1672 char2b->byte2 |= 0x80;
1674 if (enc == 4)
1676 int sjis1, sjis2;
1678 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1679 char2b->byte1 = sjis1;
1680 char2b->byte2 = sjis2;
1684 if (two_byte_p)
1685 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1687 return FONT_TYPE_UNKNOWN;
1692 /***********************************************************************
1693 Glyph display
1694 ***********************************************************************/
1698 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1699 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1700 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1701 int));
1702 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1703 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1704 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1705 static void x_draw_glyph_string P_ ((struct glyph_string *));
1706 static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *));
1707 static void x_set_cursor_gc P_ ((struct glyph_string *));
1708 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1709 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1710 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1711 unsigned long *, double, int));*/
1712 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1713 double, int, unsigned long));
1714 static void x_setup_relief_colors P_ ((struct glyph_string *));
1715 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1716 static void x_draw_image_relief P_ ((struct glyph_string *));
1717 static void x_draw_image_foreground P_ ((struct glyph_string *));
1718 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1719 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1720 int, int, int));
1721 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1722 int, int, int, int, int, int,
1723 Rect *));
1724 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1725 int, int, int, Rect *));
1727 #if GLYPH_DEBUG
1728 static void x_check_font P_ ((struct frame *, XFontStruct *));
1729 #endif
1732 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1733 face. */
1735 static void
1736 x_set_cursor_gc (s)
1737 struct glyph_string *s;
1739 if (s->font == FRAME_FONT (s->f)
1740 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1741 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1742 && !s->cmp)
1743 s->gc = s->f->output_data.mac->cursor_gc;
1744 else
1746 /* Cursor on non-default face: must merge. */
1747 XGCValues xgcv;
1748 unsigned long mask;
1750 xgcv.background = s->f->output_data.mac->cursor_pixel;
1751 xgcv.foreground = s->face->background;
1753 /* If the glyph would be invisible, try a different foreground. */
1754 if (xgcv.foreground == xgcv.background)
1755 xgcv.foreground = s->face->foreground;
1756 if (xgcv.foreground == xgcv.background)
1757 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1758 if (xgcv.foreground == xgcv.background)
1759 xgcv.foreground = s->face->foreground;
1761 /* Make sure the cursor is distinct from text in this face. */
1762 if (xgcv.background == s->face->background
1763 && xgcv.foreground == s->face->foreground)
1765 xgcv.background = s->face->foreground;
1766 xgcv.foreground = s->face->background;
1769 IF_DEBUG (x_check_font (s->f, s->font));
1770 xgcv.font = s->font;
1771 mask = GCForeground | GCBackground | GCFont;
1773 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1774 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1775 mask, &xgcv);
1776 else
1777 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1778 = XCreateGC (s->display, s->window, mask, &xgcv);
1780 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1785 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1787 static void
1788 x_set_mouse_face_gc (s)
1789 struct glyph_string *s;
1791 int face_id;
1792 struct face *face;
1794 /* What face has to be used last for the mouse face? */
1795 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1796 face = FACE_FROM_ID (s->f, face_id);
1797 if (face == NULL)
1798 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1800 if (s->first_glyph->type == CHAR_GLYPH)
1801 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1802 else
1803 face_id = FACE_FOR_CHAR (s->f, face, 0);
1804 s->face = FACE_FROM_ID (s->f, face_id);
1805 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1807 /* If font in this face is same as S->font, use it. */
1808 if (s->font == s->face->font)
1809 s->gc = s->face->gc;
1810 else
1812 /* Otherwise construct scratch_cursor_gc with values from FACE
1813 but font FONT. */
1814 XGCValues xgcv;
1815 unsigned long mask;
1817 xgcv.background = s->face->background;
1818 xgcv.foreground = s->face->foreground;
1819 IF_DEBUG (x_check_font (s->f, s->font));
1820 xgcv.font = s->font;
1821 mask = GCForeground | GCBackground | GCFont;
1823 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1824 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1825 mask, &xgcv);
1826 else
1827 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1828 = XCreateGC (s->display, s->window, mask, &xgcv);
1830 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1833 xassert (s->gc != 0);
1837 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1838 Faces to use in the mode line have already been computed when the
1839 matrix was built, so there isn't much to do, here. */
1841 static INLINE void
1842 x_set_mode_line_face_gc (s)
1843 struct glyph_string *s;
1845 s->gc = s->face->gc;
1849 /* Set S->gc of glyph string S for drawing that glyph string. Set
1850 S->stippled_p to a non-zero value if the face of S has a stipple
1851 pattern. */
1853 static INLINE void
1854 x_set_glyph_string_gc (s)
1855 struct glyph_string *s;
1857 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1859 if (s->hl == DRAW_NORMAL_TEXT)
1861 s->gc = s->face->gc;
1862 s->stippled_p = s->face->stipple != 0;
1864 else if (s->hl == DRAW_INVERSE_VIDEO)
1866 x_set_mode_line_face_gc (s);
1867 s->stippled_p = s->face->stipple != 0;
1869 else if (s->hl == DRAW_CURSOR)
1871 x_set_cursor_gc (s);
1872 s->stippled_p = 0;
1874 else if (s->hl == DRAW_MOUSE_FACE)
1876 x_set_mouse_face_gc (s);
1877 s->stippled_p = s->face->stipple != 0;
1879 else if (s->hl == DRAW_IMAGE_RAISED
1880 || s->hl == DRAW_IMAGE_SUNKEN)
1882 s->gc = s->face->gc;
1883 s->stippled_p = s->face->stipple != 0;
1885 else
1887 s->gc = s->face->gc;
1888 s->stippled_p = s->face->stipple != 0;
1891 /* GC must have been set. */
1892 xassert (s->gc != 0);
1896 /* Set clipping for output of glyph string S. S may be part of a mode
1897 line or menu if we don't have X toolkit support. */
1899 static INLINE void
1900 x_set_glyph_string_clipping (s)
1901 struct glyph_string *s;
1903 Rect r;
1904 get_glyph_string_clip_rect (s, &r);
1905 mac_set_clip_rectangle (s->display, s->window, &r);
1909 /* RIF:
1910 Compute left and right overhang of glyph string S. If S is a glyph
1911 string for a composition, assume overhangs don't exist. */
1913 static void
1914 mac_compute_glyph_string_overhangs (s)
1915 struct glyph_string *s;
1917 if (s->cmp == NULL
1918 && s->first_glyph->type == CHAR_GLYPH)
1920 Rect r;
1921 MacFontStruct *font = s->font;
1923 TextFont (font->mac_fontnum);
1924 TextSize (font->mac_fontsize);
1925 TextFace (font->mac_fontface);
1927 if (s->two_byte_p)
1928 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
1929 else
1931 int i;
1932 char *buf = xmalloc (s->nchars);
1934 if (buf == NULL)
1935 SetRect (&r, 0, 0, 0, 0);
1936 else
1938 for (i = 0; i < s->nchars; ++i)
1939 buf[i] = s->char2b[i].byte2;
1940 QDTextBounds (s->nchars, buf, &r);
1941 xfree (buf);
1945 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
1946 s->left_overhang = r.left < 0 ? -r.left : 0;
1951 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1953 static INLINE void
1954 x_clear_glyph_string_rect (s, x, y, w, h)
1955 struct glyph_string *s;
1956 int x, y, w, h;
1958 mac_erase_rectangle (s->window, s->gc, x, y, w, h);
1962 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
1963 on Mac OS X because:
1964 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1965 into an offscreen graphics world first. So performance gain
1966 cannot be expected.)
1967 - It lowers rendering quality.
1968 - Some fonts leave garbage on cursor movement. */
1970 /* Draw the background of glyph_string S. If S->background_filled_p
1971 is non-zero don't draw it. FORCE_P non-zero means draw the
1972 background even if it wouldn't be drawn normally. This is used
1973 when a string preceding S draws into the background of S, or S
1974 contains the first component of a composition. */
1976 static void
1977 x_draw_glyph_string_background (s, force_p)
1978 struct glyph_string *s;
1979 int force_p;
1981 /* Nothing to do if background has already been drawn or if it
1982 shouldn't be drawn in the first place. */
1983 if (!s->background_filled_p)
1985 int box_line_width = max (s->face->box_line_width, 0);
1987 #if 0 /* MAC_TODO: stipple */
1988 if (s->stippled_p)
1990 /* Fill background with a stipple pattern. */
1991 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1992 XFillRectangle (s->display, s->window, s->gc, s->x,
1993 s->y + box_line_width,
1994 s->background_width,
1995 s->height - 2 * box_line_width);
1996 XSetFillStyle (s->display, s->gc, FillSolid);
1997 s->background_filled_p = 1;
1999 else
2000 #endif
2001 #ifdef MAC_OS8
2002 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2003 || s->font_not_found_p
2004 || s->extends_to_end_of_line_p
2005 || force_p)
2006 #endif
2008 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2009 s->background_width,
2010 s->height - 2 * box_line_width);
2011 s->background_filled_p = 1;
2017 /* Draw the foreground of glyph string S. */
2019 static void
2020 x_draw_glyph_string_foreground (s)
2021 struct glyph_string *s;
2023 int i, x;
2025 /* If first glyph of S has a left box line, start drawing the text
2026 of S to the right of that box line. */
2027 if (s->face->box != FACE_NO_BOX
2028 && s->first_glyph->left_box_line_p)
2029 x = s->x + abs (s->face->box_line_width);
2030 else
2031 x = s->x;
2033 /* Draw characters of S as rectangles if S's font could not be
2034 loaded. */
2035 if (s->font_not_found_p)
2037 for (i = 0; i < s->nchars; ++i)
2039 struct glyph *g = s->first_glyph + i;
2040 mac_draw_rectangle (s->display, s->window,
2041 s->gc, x, s->y, g->pixel_width - 1,
2042 s->height - 1);
2043 x += g->pixel_width;
2046 else
2048 char *char1b = (char *) s->char2b;
2049 int boff = s->font_info->baseline_offset;
2051 if (s->font_info->vertical_centering)
2052 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2054 /* If we can use 8-bit functions, condense S->char2b. */
2055 if (!s->two_byte_p)
2056 for (i = 0; i < s->nchars; ++i)
2057 char1b[i] = s->char2b[i].byte2;
2059 #ifdef MAC_OS8
2060 /* Draw text with XDrawString if background has already been
2061 filled. Otherwise, use XDrawImageString. (Note that
2062 XDrawImageString is usually faster than XDrawString.) Always
2063 use XDrawImageString when drawing the cursor so that there is
2064 no chance that characters under a box cursor are invisible. */
2065 if (s->for_overlaps_p
2066 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2067 #endif
2069 /* Draw characters with 16-bit or 8-bit functions. */
2070 if (s->two_byte_p)
2071 XDrawString16 (s->display, s->window, s->gc, x,
2072 s->ybase - boff, s->char2b, s->nchars);
2073 else
2074 XDrawString (s->display, s->window, s->gc, x,
2075 s->ybase - boff, char1b, s->nchars);
2077 #ifdef MAC_OS8
2078 else
2080 if (s->two_byte_p)
2081 XDrawImageString16 (s->display, s->window, s->gc, x,
2082 s->ybase - boff, s->char2b, s->nchars);
2083 else
2084 XDrawImageString (s->display, s->window, s->gc, x,
2085 s->ybase - boff, char1b, s->nchars);
2087 #endif
2091 /* Draw the foreground of composite glyph string S. */
2093 static void
2094 x_draw_composite_glyph_string_foreground (s)
2095 struct glyph_string *s;
2097 int i, x;
2099 /* If first glyph of S has a left box line, start drawing the text
2100 of S to the right of that box line. */
2101 if (s->face->box != FACE_NO_BOX
2102 && s->first_glyph->left_box_line_p)
2103 x = s->x + abs (s->face->box_line_width);
2104 else
2105 x = s->x;
2107 /* S is a glyph string for a composition. S->gidx is the index of
2108 the first character drawn for glyphs of this composition.
2109 S->gidx == 0 means we are drawing the very first character of
2110 this composition. */
2112 /* Draw a rectangle for the composition if the font for the very
2113 first character of the composition could not be loaded. */
2114 if (s->font_not_found_p)
2116 if (s->gidx == 0)
2117 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2118 s->width - 1, s->height - 1);
2120 else
2122 for (i = 0; i < s->nchars; i++, ++s->gidx)
2123 XDrawString16 (s->display, s->window, s->gc,
2124 x + s->cmp->offsets[s->gidx * 2],
2125 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2126 s->char2b + i, 1);
2131 #ifdef USE_X_TOOLKIT
2133 static struct frame *x_frame_of_widget P_ ((Widget));
2136 /* Return the frame on which widget WIDGET is used.. Abort if frame
2137 cannot be determined. */
2139 static struct frame *
2140 x_frame_of_widget (widget)
2141 Widget widget;
2143 struct x_display_info *dpyinfo;
2144 Lisp_Object tail;
2145 struct frame *f;
2147 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2149 /* Find the top-level shell of the widget. Note that this function
2150 can be called when the widget is not yet realized, so XtWindow
2151 (widget) == 0. That's the reason we can't simply use
2152 x_any_window_to_frame. */
2153 while (!XtIsTopLevelShell (widget))
2154 widget = XtParent (widget);
2156 /* Look for a frame with that top-level widget. Allocate the color
2157 on that frame to get the right gamma correction value. */
2158 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2159 if (GC_FRAMEP (XCAR (tail))
2160 && (f = XFRAME (XCAR (tail)),
2161 (f->output_data.nothing != 1
2162 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2163 && f->output_data.x->widget == widget)
2164 return f;
2166 abort ();
2170 /* Allocate the color COLOR->pixel on the screen and display of
2171 widget WIDGET in colormap CMAP. If an exact match cannot be
2172 allocated, try the nearest color available. Value is non-zero
2173 if successful. This is called from lwlib. */
2176 x_alloc_nearest_color_for_widget (widget, cmap, color)
2177 Widget widget;
2178 Colormap cmap;
2179 XColor *color;
2181 struct frame *f = x_frame_of_widget (widget);
2182 return x_alloc_nearest_color (f, cmap, color);
2186 #endif /* USE_X_TOOLKIT */
2188 #if 0 /* MAC_TODO */
2190 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2191 CMAP. If an exact match can't be allocated, try the nearest color
2192 available. Value is non-zero if successful. Set *COLOR to the
2193 color allocated. */
2196 x_alloc_nearest_color (f, cmap, color)
2197 struct frame *f;
2198 Colormap cmap;
2199 XColor *color;
2201 Display *display = FRAME_X_DISPLAY (f);
2202 Screen *screen = FRAME_X_SCREEN (f);
2203 int rc;
2205 gamma_correct (f, color);
2206 rc = XAllocColor (display, cmap, color);
2207 if (rc == 0)
2209 /* If we got to this point, the colormap is full, so we're going
2210 to try to get the next closest color. The algorithm used is
2211 a least-squares matching, which is what X uses for closest
2212 color matching with StaticColor visuals. */
2213 int nearest, i;
2214 unsigned long nearest_delta = ~0;
2215 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2216 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2218 for (i = 0; i < ncells; ++i)
2219 cells[i].pixel = i;
2220 XQueryColors (display, cmap, cells, ncells);
2222 for (nearest = i = 0; i < ncells; ++i)
2224 long dred = (color->red >> 8) - (cells[i].red >> 8);
2225 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2226 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2227 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2229 if (delta < nearest_delta)
2231 nearest = i;
2232 nearest_delta = delta;
2236 color->red = cells[nearest].red;
2237 color->green = cells[nearest].green;
2238 color->blue = cells[nearest].blue;
2239 rc = XAllocColor (display, cmap, color);
2242 #ifdef DEBUG_X_COLORS
2243 if (rc)
2244 register_color (color->pixel);
2245 #endif /* DEBUG_X_COLORS */
2247 return rc;
2251 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2252 It's necessary to do this instead of just using PIXEL directly to
2253 get color reference counts right. */
2255 unsigned long
2256 x_copy_color (f, pixel)
2257 struct frame *f;
2258 unsigned long pixel;
2260 XColor color;
2262 color.pixel = pixel;
2263 BLOCK_INPUT;
2264 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2265 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2266 UNBLOCK_INPUT;
2267 #ifdef DEBUG_X_COLORS
2268 register_color (pixel);
2269 #endif
2270 return color.pixel;
2274 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2275 It's necessary to do this instead of just using PIXEL directly to
2276 get color reference counts right. */
2278 unsigned long
2279 x_copy_dpy_color (dpy, cmap, pixel)
2280 Display *dpy;
2281 Colormap cmap;
2282 unsigned long pixel;
2284 XColor color;
2286 color.pixel = pixel;
2287 BLOCK_INPUT;
2288 XQueryColor (dpy, cmap, &color);
2289 XAllocColor (dpy, cmap, &color);
2290 UNBLOCK_INPUT;
2291 #ifdef DEBUG_X_COLORS
2292 register_color (pixel);
2293 #endif
2294 return color.pixel;
2297 #endif /* MAC_TODO */
2300 /* Brightness beyond which a color won't have its highlight brightness
2301 boosted.
2303 Nominally, highlight colors for `3d' faces are calculated by
2304 brightening an object's color by a constant scale factor, but this
2305 doesn't yield good results for dark colors, so for colors who's
2306 brightness is less than this value (on a scale of 0-255) have to
2307 use an additional additive factor.
2309 The value here is set so that the default menu-bar/mode-line color
2310 (grey75) will not have its highlights changed at all. */
2311 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2314 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2315 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2316 If this produces the same color as COLOR, try a color where all RGB
2317 values have DELTA added. Return the allocated color in *COLOR.
2318 DISPLAY is the X display, CMAP is the colormap to operate on.
2319 Value is non-zero if successful. */
2321 static int
2322 mac_alloc_lighter_color (f, color, factor, delta)
2323 struct frame *f;
2324 unsigned long *color;
2325 double factor;
2326 int delta;
2328 unsigned long new;
2329 long bright;
2331 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2332 delta /= 256;
2334 /* Change RGB values by specified FACTOR. Avoid overflow! */
2335 xassert (factor >= 0);
2336 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2337 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2338 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2340 /* Calculate brightness of COLOR. */
2341 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2342 + BLUE_FROM_ULONG (*color)) / 6;
2344 /* We only boost colors that are darker than
2345 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2346 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2347 /* Make an additive adjustment to NEW, because it's dark enough so
2348 that scaling by FACTOR alone isn't enough. */
2350 /* How far below the limit this color is (0 - 1, 1 being darker). */
2351 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2352 /* The additive adjustment. */
2353 int min_delta = delta * dimness * factor / 2;
2355 if (factor < 1)
2356 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2357 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2358 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2359 else
2360 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2361 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2362 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2365 if (new == *color)
2366 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2367 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2368 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2370 /* MAC_TODO: Map to palette and retry with delta if same? */
2371 /* MAC_TODO: Free colors (if using palette)? */
2373 if (new == *color)
2374 return 0;
2376 *color = new;
2378 return 1;
2382 /* Set up the foreground color for drawing relief lines of glyph
2383 string S. RELIEF is a pointer to a struct relief containing the GC
2384 with which lines will be drawn. Use a color that is FACTOR or
2385 DELTA lighter or darker than the relief's background which is found
2386 in S->f->output_data.x->relief_background. If such a color cannot
2387 be allocated, use DEFAULT_PIXEL, instead. */
2389 static void
2390 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2391 struct frame *f;
2392 struct relief *relief;
2393 double factor;
2394 int delta;
2395 unsigned long default_pixel;
2397 XGCValues xgcv;
2398 struct mac_output *di = f->output_data.mac;
2399 unsigned long mask = GCForeground;
2400 unsigned long pixel;
2401 unsigned long background = di->relief_background;
2402 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2404 /* MAC_TODO: Free colors (if using palette)? */
2406 /* Allocate new color. */
2407 xgcv.foreground = default_pixel;
2408 pixel = background;
2409 if (dpyinfo->n_planes != 1
2410 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2412 relief->allocated_p = 1;
2413 xgcv.foreground = relief->pixel = pixel;
2416 if (relief->gc == 0)
2418 #if 0 /* MAC_TODO: stipple */
2419 xgcv.stipple = dpyinfo->gray;
2420 mask |= GCStipple;
2421 #endif
2422 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2424 else
2425 XChangeGC (NULL, relief->gc, mask, &xgcv);
2429 /* Set up colors for the relief lines around glyph string S. */
2431 static void
2432 x_setup_relief_colors (s)
2433 struct glyph_string *s;
2435 struct mac_output *di = s->f->output_data.mac;
2436 unsigned long color;
2438 if (s->face->use_box_color_for_shadows_p)
2439 color = s->face->box_color;
2440 else if (s->first_glyph->type == IMAGE_GLYPH
2441 && s->img->pixmap
2442 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2443 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2444 else
2446 XGCValues xgcv;
2448 /* Get the background color of the face. */
2449 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2450 color = xgcv.background;
2453 if (di->white_relief.gc == 0
2454 || color != di->relief_background)
2456 di->relief_background = color;
2457 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2458 WHITE_PIX_DEFAULT (s->f));
2459 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2460 BLACK_PIX_DEFAULT (s->f));
2465 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2466 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2467 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2468 relief. LEFT_P non-zero means draw a relief on the left side of
2469 the rectangle. RIGHT_P non-zero means draw a relief on the right
2470 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2471 when drawing. */
2473 static void
2474 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2475 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2476 struct frame *f;
2477 int left_x, top_y, right_x, bottom_y, width;
2478 int top_p, bot_p, left_p, right_p, raised_p;
2479 Rect *clip_rect;
2481 Display *dpy = FRAME_MAC_DISPLAY (f);
2482 Window window = FRAME_MAC_WINDOW (f);
2483 int i;
2484 GC gc;
2486 if (raised_p)
2487 gc = f->output_data.mac->white_relief.gc;
2488 else
2489 gc = f->output_data.mac->black_relief.gc;
2490 mac_set_clip_rectangle (dpy, window, clip_rect);
2492 /* Top. */
2493 if (top_p)
2494 for (i = 0; i < width; ++i)
2495 XDrawLine (dpy, window, gc,
2496 left_x + i * left_p, top_y + i,
2497 right_x - i * right_p, top_y + i);
2499 /* Left. */
2500 if (left_p)
2501 for (i = 0; i < width; ++i)
2502 XDrawLine (dpy, window, gc,
2503 left_x + i, top_y + i, left_x + i, bottom_y - i);
2505 mac_reset_clipping (dpy, window);
2506 if (raised_p)
2507 gc = f->output_data.mac->black_relief.gc;
2508 else
2509 gc = f->output_data.mac->white_relief.gc;
2510 mac_set_clip_rectangle (dpy, window,
2511 clip_rect);
2513 /* Bottom. */
2514 if (bot_p)
2515 for (i = 0; i < width; ++i)
2516 XDrawLine (dpy, window, gc,
2517 left_x + i * left_p, bottom_y - i,
2518 right_x - i * right_p, bottom_y - i);
2520 /* Right. */
2521 if (right_p)
2522 for (i = 0; i < width; ++i)
2523 XDrawLine (dpy, window, gc,
2524 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2526 mac_reset_clipping (dpy, window);
2530 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2531 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2532 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2533 left side of the rectangle. RIGHT_P non-zero means draw a line
2534 on the right side of the rectangle. CLIP_RECT is the clipping
2535 rectangle to use when drawing. */
2537 static void
2538 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2539 left_p, right_p, clip_rect)
2540 struct glyph_string *s;
2541 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2542 Rect *clip_rect;
2544 XGCValues xgcv;
2546 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2547 XSetForeground (s->display, s->gc, s->face->box_color);
2548 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2550 /* Top. */
2551 XFillRectangle (s->display, s->window, s->gc,
2552 left_x, top_y, right_x - left_x + 1, width);
2554 /* Left. */
2555 if (left_p)
2556 XFillRectangle (s->display, s->window, s->gc,
2557 left_x, top_y, width, bottom_y - top_y + 1);
2559 /* Bottom. */
2560 XFillRectangle (s->display, s->window, s->gc,
2561 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2563 /* Right. */
2564 if (right_p)
2565 XFillRectangle (s->display, s->window, s->gc,
2566 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2568 XSetForeground (s->display, s->gc, xgcv.foreground);
2569 mac_reset_clipping (s->display, s->window);
2573 /* Draw a box around glyph string S. */
2575 static void
2576 x_draw_glyph_string_box (s)
2577 struct glyph_string *s;
2579 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2580 int left_p, right_p;
2581 struct glyph *last_glyph;
2582 Rect clip_rect;
2584 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2585 ? WINDOW_RIGHT_EDGE_X (s->w)
2586 : window_box_right (s->w, s->area));
2588 /* The glyph that may have a right box line. */
2589 last_glyph = (s->cmp || s->img
2590 ? s->first_glyph
2591 : s->first_glyph + s->nchars - 1);
2593 width = abs (s->face->box_line_width);
2594 raised_p = s->face->box == FACE_RAISED_BOX;
2595 left_x = s->x;
2596 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2597 ? last_x - 1
2598 : min (last_x, s->x + s->background_width) - 1);
2599 top_y = s->y;
2600 bottom_y = top_y + s->height - 1;
2602 left_p = (s->first_glyph->left_box_line_p
2603 || (s->hl == DRAW_MOUSE_FACE
2604 && (s->prev == NULL
2605 || s->prev->hl != s->hl)));
2606 right_p = (last_glyph->right_box_line_p
2607 || (s->hl == DRAW_MOUSE_FACE
2608 && (s->next == NULL
2609 || s->next->hl != s->hl)));
2611 get_glyph_string_clip_rect (s, &clip_rect);
2613 if (s->face->box == FACE_SIMPLE_BOX)
2614 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2615 left_p, right_p, &clip_rect);
2616 else
2618 x_setup_relief_colors (s);
2619 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2620 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2625 /* Draw foreground of image glyph string S. */
2627 static void
2628 x_draw_image_foreground (s)
2629 struct glyph_string *s;
2631 int x = s->x;
2632 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2634 /* If first glyph of S has a left box line, start drawing it to the
2635 right of that line. */
2636 if (s->face->box != FACE_NO_BOX
2637 && s->first_glyph->left_box_line_p
2638 && s->slice.x == 0)
2639 x += abs (s->face->box_line_width);
2641 /* If there is a margin around the image, adjust x- and y-position
2642 by that margin. */
2643 if (s->slice.x == 0)
2644 x += s->img->hmargin;
2645 if (s->slice.y == 0)
2646 y += s->img->vmargin;
2648 if (s->img->pixmap)
2650 x_set_glyph_string_clipping (s);
2652 if (s->img->mask)
2653 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2654 s->window, s->gc, s->slice.x, s->slice.y,
2655 s->slice.width, s->slice.height, x, y);
2656 else
2658 mac_copy_area (s->display, s->img->pixmap,
2659 s->window, s->gc, s->slice.x, s->slice.y,
2660 s->slice.width, s->slice.height, x, y);
2662 /* When the image has a mask, we can expect that at
2663 least part of a mouse highlight or a block cursor will
2664 be visible. If the image doesn't have a mask, make
2665 a block cursor visible by drawing a rectangle around
2666 the image. I believe it's looking better if we do
2667 nothing here for mouse-face. */
2668 if (s->hl == DRAW_CURSOR)
2670 int r = s->img->relief;
2671 if (r < 0) r = -r;
2672 mac_draw_rectangle (s->display, s->window, s->gc,
2673 x - r, y - r,
2674 s->slice.width + r*2 - 1,
2675 s->slice.height + r*2 - 1);
2679 else
2680 /* Draw a rectangle if image could not be loaded. */
2681 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2682 s->slice.width - 1, s->slice.height - 1);
2686 /* Draw a relief around the image glyph string S. */
2688 static void
2689 x_draw_image_relief (s)
2690 struct glyph_string *s;
2692 int x0, y0, x1, y1, thick, raised_p;
2693 Rect r;
2694 int x = s->x;
2695 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2697 /* If first glyph of S has a left box line, start drawing it to the
2698 right of that line. */
2699 if (s->face->box != FACE_NO_BOX
2700 && s->first_glyph->left_box_line_p
2701 && s->slice.x == 0)
2702 x += abs (s->face->box_line_width);
2704 /* If there is a margin around the image, adjust x- and y-position
2705 by that margin. */
2706 if (s->slice.x == 0)
2707 x += s->img->hmargin;
2708 if (s->slice.y == 0)
2709 y += s->img->vmargin;
2711 if (s->hl == DRAW_IMAGE_SUNKEN
2712 || s->hl == DRAW_IMAGE_RAISED)
2714 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2715 raised_p = s->hl == DRAW_IMAGE_RAISED;
2717 else
2719 thick = abs (s->img->relief);
2720 raised_p = s->img->relief > 0;
2723 x0 = x - thick;
2724 y0 = y - thick;
2725 x1 = x + s->slice.width + thick - 1;
2726 y1 = y + s->slice.height + thick - 1;
2728 x_setup_relief_colors (s);
2729 get_glyph_string_clip_rect (s, &r);
2730 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2731 s->slice.y == 0,
2732 s->slice.y + s->slice.height == s->img->height,
2733 s->slice.x == 0,
2734 s->slice.x + s->slice.width == s->img->width,
2735 &r);
2739 #if 0 /* TODO: figure out if we need to do this on Mac. */
2740 /* Draw the foreground of image glyph string S to PIXMAP. */
2742 static void
2743 x_draw_image_foreground_1 (s, pixmap)
2744 struct glyph_string *s;
2745 Pixmap pixmap;
2747 int x = 0;
2748 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2750 /* If first glyph of S has a left box line, start drawing it to the
2751 right of that line. */
2752 if (s->face->box != FACE_NO_BOX
2753 && s->first_glyph->left_box_line_p
2754 && s->slice.x == 0)
2755 x += abs (s->face->box_line_width);
2757 /* If there is a margin around the image, adjust x- and y-position
2758 by that margin. */
2759 if (s->slice.x == 0)
2760 x += s->img->hmargin;
2761 if (s->slice.y == 0)
2762 y += s->img->vmargin;
2764 if (s->img->pixmap)
2766 if (s->img->mask)
2767 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2768 s->img->mask, pixmap, s->gc,
2769 s->slice.x, s->slice.y,
2770 s->slice.width, s->slice.height,
2771 x, y);
2772 else
2774 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2775 s->slice.x, s->slice.y,
2776 s->slice.width, s->slice.height,
2777 x, y);
2779 /* When the image has a mask, we can expect that at
2780 least part of a mouse highlight or a block cursor will
2781 be visible. If the image doesn't have a mask, make
2782 a block cursor visible by drawing a rectangle around
2783 the image. I believe it's looking better if we do
2784 nothing here for mouse-face. */
2785 if (s->hl == DRAW_CURSOR)
2787 int r = s->img->relief;
2788 if (r < 0) r = -r;
2789 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2790 s->slice.width + r*2 - 1,
2791 s->slice.height + r*2 - 1);
2795 else
2796 /* Draw a rectangle if image could not be loaded. */
2797 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2798 s->slice.width - 1, s->slice.height - 1);
2800 #endif
2803 /* Draw part of the background of glyph string S. X, Y, W, and H
2804 give the rectangle to draw. */
2806 static void
2807 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2808 struct glyph_string *s;
2809 int x, y, w, h;
2811 #if 0 /* MAC_TODO: stipple */
2812 if (s->stippled_p)
2814 /* Fill background with a stipple pattern. */
2815 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2816 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2817 XSetFillStyle (s->display, s->gc, FillSolid);
2819 else
2820 #endif /* MAC_TODO */
2821 x_clear_glyph_string_rect (s, x, y, w, h);
2825 /* Draw image glyph string S.
2827 s->y
2828 s->x +-------------------------
2829 | s->face->box
2831 | +-------------------------
2832 | | s->img->margin
2834 | | +-------------------
2835 | | | the image
2839 static void
2840 x_draw_image_glyph_string (s)
2841 struct glyph_string *s;
2843 int x, y;
2844 int box_line_hwidth = abs (s->face->box_line_width);
2845 int box_line_vwidth = max (s->face->box_line_width, 0);
2846 int height;
2847 Pixmap pixmap = 0;
2849 height = s->height - 2 * box_line_vwidth;
2852 /* Fill background with face under the image. Do it only if row is
2853 taller than image or if image has a clip mask to reduce
2854 flickering. */
2855 s->stippled_p = s->face->stipple != 0;
2856 if (height > s->slice.height
2857 || s->img->hmargin
2858 || s->img->vmargin
2859 || s->img->mask
2860 || s->img->pixmap == 0
2861 || s->width != s->background_width)
2863 x = s->x;
2864 if (s->first_glyph->left_box_line_p
2865 && s->slice.x == 0)
2866 x += box_line_hwidth;
2868 y = s->y;
2869 if (s->slice.y == 0)
2870 y += box_line_vwidth;
2872 #if 0 /* TODO: figure out if we need to do this on Mac. */
2873 if (s->img->mask)
2875 /* Create a pixmap as large as the glyph string. Fill it
2876 with the background color. Copy the image to it, using
2877 its mask. Copy the temporary pixmap to the display. */
2878 int depth = one_mac_display_info.n_planes;
2880 /* Create a pixmap as large as the glyph string. */
2881 pixmap = XCreatePixmap (s->display, s->window,
2882 s->background_width,
2883 s->height, depth);
2885 /* Fill the pixmap with the background color/stipple. */
2886 #if 0 /* TODO: stipple */
2887 if (s->stippled_p)
2889 /* Fill background with a stipple pattern. */
2890 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2891 XFillRectangle (s->display, pixmap, s->gc,
2892 0, 0, s->background_width, s->height);
2893 XSetFillStyle (s->display, s->gc, FillSolid);
2895 else
2896 #endif
2898 XGCValues xgcv;
2899 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2900 &xgcv);
2901 XSetForeground (s->display, s->gc, xgcv.background);
2902 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2903 0, 0, s->background_width,
2904 s->height);
2905 XSetForeground (s->display, s->gc, xgcv.foreground);
2908 else
2909 #endif
2910 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2912 s->background_filled_p = 1;
2915 /* Draw the foreground. */
2916 #if 0 /* TODO: figure out if we need to do this on Mac. */
2917 if (pixmap != 0)
2919 x_draw_image_foreground_1 (s, pixmap);
2920 x_set_glyph_string_clipping (s);
2921 mac_copy_area (s->display, pixmap, s->window, s->gc,
2922 0, 0, s->background_width, s->height, s->x, s->y);
2923 mac_reset_clipping (s->display, s->window);
2924 XFreePixmap (s->display, pixmap);
2926 else
2927 #endif
2928 x_draw_image_foreground (s);
2930 /* If we must draw a relief around the image, do it. */
2931 if (s->img->relief
2932 || s->hl == DRAW_IMAGE_RAISED
2933 || s->hl == DRAW_IMAGE_SUNKEN)
2934 x_draw_image_relief (s);
2938 /* Draw stretch glyph string S. */
2940 static void
2941 x_draw_stretch_glyph_string (s)
2942 struct glyph_string *s;
2944 xassert (s->first_glyph->type == STRETCH_GLYPH);
2945 s->stippled_p = s->face->stipple != 0;
2947 if (s->hl == DRAW_CURSOR
2948 && !x_stretch_cursor_p)
2950 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2951 as wide as the stretch glyph. */
2952 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2954 /* Draw cursor. */
2955 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2957 /* Clear rest using the GC of the original non-cursor face. */
2958 if (width < s->background_width)
2960 int x = s->x + width, y = s->y;
2961 int w = s->background_width - width, h = s->height;
2962 Rect r;
2963 GC gc;
2965 if (s->row->mouse_face_p
2966 && cursor_in_mouse_face_p (s->w))
2968 x_set_mouse_face_gc (s);
2969 gc = s->gc;
2971 else
2972 gc = s->face->gc;
2974 get_glyph_string_clip_rect (s, &r);
2975 mac_set_clip_rectangle (s->display, s->window, &r);
2977 #if 0 /* MAC_TODO: stipple */
2978 if (s->face->stipple)
2980 /* Fill background with a stipple pattern. */
2981 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2982 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2983 XSetFillStyle (s->display, gc, FillSolid);
2985 else
2986 #endif /* MAC_TODO */
2987 mac_erase_rectangle (s->window, gc, x, y, w, h);
2989 mac_reset_clipping (s->display, s->window);
2992 else if (!s->background_filled_p)
2993 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2994 s->height);
2996 s->background_filled_p = 1;
3000 /* Draw glyph string S. */
3002 static void
3003 x_draw_glyph_string (s)
3004 struct glyph_string *s;
3006 int relief_drawn_p = 0;
3008 /* If S draws into the background of its successor that does not
3009 draw a cursor, draw the background of the successor first so that
3010 S can draw into it. This makes S->next use XDrawString instead
3011 of XDrawImageString. */
3012 if (s->next && s->right_overhang && !s->for_overlaps_p
3013 && s->next->hl != DRAW_CURSOR)
3015 xassert (s->next->img == NULL);
3016 x_set_glyph_string_gc (s->next);
3017 x_set_glyph_string_clipping (s->next);
3018 x_draw_glyph_string_background (s->next, 1);
3021 /* Set up S->gc, set clipping and draw S. */
3022 x_set_glyph_string_gc (s);
3024 /* Draw relief (if any) in advance for char/composition so that the
3025 glyph string can be drawn over it. */
3026 if (!s->for_overlaps_p
3027 && s->face->box != FACE_NO_BOX
3028 && (s->first_glyph->type == CHAR_GLYPH
3029 || s->first_glyph->type == COMPOSITE_GLYPH))
3032 x_set_glyph_string_clipping (s);
3033 x_draw_glyph_string_background (s, 1);
3034 x_draw_glyph_string_box (s);
3035 x_set_glyph_string_clipping (s);
3036 relief_drawn_p = 1;
3038 else
3039 x_set_glyph_string_clipping (s);
3041 switch (s->first_glyph->type)
3043 case IMAGE_GLYPH:
3044 x_draw_image_glyph_string (s);
3045 break;
3047 case STRETCH_GLYPH:
3048 x_draw_stretch_glyph_string (s);
3049 break;
3051 case CHAR_GLYPH:
3052 if (s->for_overlaps_p)
3053 s->background_filled_p = 1;
3054 else
3055 x_draw_glyph_string_background (s, 0);
3056 x_draw_glyph_string_foreground (s);
3057 break;
3059 case COMPOSITE_GLYPH:
3060 if (s->for_overlaps_p || s->gidx > 0)
3061 s->background_filled_p = 1;
3062 else
3063 x_draw_glyph_string_background (s, 1);
3064 x_draw_composite_glyph_string_foreground (s);
3065 break;
3067 default:
3068 abort ();
3071 if (!s->for_overlaps_p)
3073 /* Draw underline. */
3074 if (s->face->underline_p)
3076 unsigned long h = 1;
3077 unsigned long dy = s->height - h;
3079 if (s->face->underline_defaulted_p)
3080 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3081 s->width, h);
3082 else
3084 XGCValues xgcv;
3085 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3086 XSetForeground (s->display, s->gc, s->face->underline_color);
3087 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3088 s->width, h);
3089 XSetForeground (s->display, s->gc, xgcv.foreground);
3093 /* Draw overline. */
3094 if (s->face->overline_p)
3096 unsigned long dy = 0, h = 1;
3098 if (s->face->overline_color_defaulted_p)
3099 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3100 s->width, h);
3101 else
3103 XGCValues xgcv;
3104 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3105 XSetForeground (s->display, s->gc, s->face->overline_color);
3106 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3107 s->width, h);
3108 XSetForeground (s->display, s->gc, xgcv.foreground);
3112 /* Draw strike-through. */
3113 if (s->face->strike_through_p)
3115 unsigned long h = 1;
3116 unsigned long dy = (s->height - h) / 2;
3118 if (s->face->strike_through_color_defaulted_p)
3119 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3120 s->width, h);
3121 else
3123 XGCValues xgcv;
3124 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3125 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3126 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3127 s->width, h);
3128 XSetForeground (s->display, s->gc, xgcv.foreground);
3132 /* Draw relief if not yet drawn. */
3133 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3134 x_draw_glyph_string_box (s);
3137 /* Reset clipping. */
3138 mac_reset_clipping (s->display, s->window);
3141 /* Shift display to make room for inserted glyphs. */
3143 void
3144 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3145 struct frame *f;
3146 int x, y, width, height, shift_by;
3148 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3149 f->output_data.mac->normal_gc,
3150 x, y, width, height,
3151 x + shift_by, y);
3154 /* Delete N glyphs at the nominal cursor position. Not implemented
3155 for X frames. */
3157 static void
3158 x_delete_glyphs (n)
3159 register int n;
3161 abort ();
3165 /* Clear entire frame. If updating_frame is non-null, clear that
3166 frame. Otherwise clear the selected frame. */
3168 static void
3169 x_clear_frame ()
3171 struct frame *f;
3173 if (updating_frame)
3174 f = updating_frame;
3175 else
3176 f = SELECTED_FRAME ();
3178 /* Clearing the frame will erase any cursor, so mark them all as no
3179 longer visible. */
3180 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3181 output_cursor.hpos = output_cursor.vpos = 0;
3182 output_cursor.x = -1;
3184 /* We don't set the output cursor here because there will always
3185 follow an explicit cursor_to. */
3186 BLOCK_INPUT;
3187 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3189 /* We have to clear the scroll bars, too. If we have changed
3190 colors or something like that, then they should be notified. */
3191 x_scroll_bar_clear (f);
3193 XFlush (FRAME_MAC_DISPLAY (f));
3194 UNBLOCK_INPUT;
3199 /* Invert the middle quarter of the frame for .15 sec. */
3201 /* We use the select system call to do the waiting, so we have to make
3202 sure it's available. If it isn't, we just won't do visual bells. */
3204 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3207 /* Subtract the `struct timeval' values X and Y, storing the result in
3208 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3210 static int
3211 timeval_subtract (result, x, y)
3212 struct timeval *result, x, y;
3214 /* Perform the carry for the later subtraction by updating y. This
3215 is safer because on some systems the tv_sec member is unsigned. */
3216 if (x.tv_usec < y.tv_usec)
3218 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3219 y.tv_usec -= 1000000 * nsec;
3220 y.tv_sec += nsec;
3223 if (x.tv_usec - y.tv_usec > 1000000)
3225 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3226 y.tv_usec += 1000000 * nsec;
3227 y.tv_sec -= nsec;
3230 /* Compute the time remaining to wait. tv_usec is certainly
3231 positive. */
3232 result->tv_sec = x.tv_sec - y.tv_sec;
3233 result->tv_usec = x.tv_usec - y.tv_usec;
3235 /* Return indication of whether the result should be considered
3236 negative. */
3237 return x.tv_sec < y.tv_sec;
3240 void
3241 XTflash (f)
3242 struct frame *f;
3244 BLOCK_INPUT;
3246 FlashMenuBar (0);
3249 struct timeval wakeup;
3251 EMACS_GET_TIME (wakeup);
3253 /* Compute time to wait until, propagating carry from usecs. */
3254 wakeup.tv_usec += 150000;
3255 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3256 wakeup.tv_usec %= 1000000;
3258 /* Keep waiting until past the time wakeup. */
3259 while (1)
3261 struct timeval timeout;
3263 EMACS_GET_TIME (timeout);
3265 /* In effect, timeout = wakeup - timeout.
3266 Break if result would be negative. */
3267 if (timeval_subtract (&timeout, wakeup, timeout))
3268 break;
3270 /* Try to wait that long--but we might wake up sooner. */
3271 select (0, NULL, NULL, NULL, &timeout);
3275 FlashMenuBar (0);
3277 UNBLOCK_INPUT;
3280 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3283 /* Make audible bell. */
3285 void
3286 XTring_bell ()
3288 struct frame *f = SELECTED_FRAME ();
3290 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3291 if (visible_bell)
3292 XTflash (f);
3293 else
3294 #endif
3296 BLOCK_INPUT;
3297 SysBeep (1);
3298 XFlush (FRAME_MAC_DISPLAY (f));
3299 UNBLOCK_INPUT;
3304 /* Specify how many text lines, from the top of the window,
3305 should be affected by insert-lines and delete-lines operations.
3306 This, and those operations, are used only within an update
3307 that is bounded by calls to x_update_begin and x_update_end. */
3309 static void
3310 XTset_terminal_window (n)
3311 register int n;
3313 /* This function intentionally left blank. */
3318 /***********************************************************************
3319 Line Dance
3320 ***********************************************************************/
3322 /* Perform an insert-lines or delete-lines operation, inserting N
3323 lines or deleting -N lines at vertical position VPOS. */
3325 static void
3326 x_ins_del_lines (vpos, n)
3327 int vpos, n;
3329 abort ();
3333 /* Scroll part of the display as described by RUN. */
3335 static void
3336 x_scroll_run (w, run)
3337 struct window *w;
3338 struct run *run;
3340 struct frame *f = XFRAME (w->frame);
3341 int x, y, width, height, from_y, to_y, bottom_y;
3343 /* Get frame-relative bounding box of the text display area of W,
3344 without mode lines. Include in this box the left and right
3345 fringe of W. */
3346 window_box (w, -1, &x, &y, &width, &height);
3348 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3349 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3350 bottom_y = y + height;
3352 if (to_y < from_y)
3354 /* Scrolling up. Make sure we don't copy part of the mode
3355 line at the bottom. */
3356 if (from_y + run->height > bottom_y)
3357 height = bottom_y - from_y;
3358 else
3359 height = run->height;
3361 else
3363 /* Scolling down. Make sure we don't copy over the mode line.
3364 at the bottom. */
3365 if (to_y + run->height > bottom_y)
3366 height = bottom_y - to_y;
3367 else
3368 height = run->height;
3371 BLOCK_INPUT;
3373 /* Cursor off. Will be switched on again in x_update_window_end. */
3374 updated_window = w;
3375 x_clear_cursor (w);
3377 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3378 f->output_data.mac->normal_gc,
3379 x, from_y,
3380 width, height,
3381 x, to_y);
3383 UNBLOCK_INPUT;
3388 /***********************************************************************
3389 Exposure Events
3390 ***********************************************************************/
3393 static void
3394 frame_highlight (f)
3395 struct frame *f;
3397 OSErr err;
3398 ControlRef root_control;
3400 BLOCK_INPUT;
3401 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
3402 if (err == noErr)
3403 ActivateControl (root_control);
3404 UNBLOCK_INPUT;
3405 x_update_cursor (f, 1);
3408 static void
3409 frame_unhighlight (f)
3410 struct frame *f;
3412 OSErr err;
3413 ControlRef root_control;
3415 BLOCK_INPUT;
3416 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
3417 if (err == noErr)
3418 DeactivateControl (root_control);
3419 UNBLOCK_INPUT;
3420 x_update_cursor (f, 1);
3423 /* The focus has changed. Update the frames as necessary to reflect
3424 the new situation. Note that we can't change the selected frame
3425 here, because the Lisp code we are interrupting might become confused.
3426 Each event gets marked with the frame in which it occurred, so the
3427 Lisp code can tell when the switch took place by examining the events. */
3429 static void
3430 x_new_focus_frame (dpyinfo, frame)
3431 struct x_display_info *dpyinfo;
3432 struct frame *frame;
3434 struct frame *old_focus = dpyinfo->x_focus_frame;
3436 if (frame != dpyinfo->x_focus_frame)
3438 /* Set this before calling other routines, so that they see
3439 the correct value of x_focus_frame. */
3440 dpyinfo->x_focus_frame = frame;
3442 if (old_focus && old_focus->auto_lower)
3443 x_lower_frame (old_focus);
3445 #if 0
3446 selected_frame = frame;
3447 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3448 selected_frame);
3449 Fselect_window (selected_frame->selected_window, Qnil);
3450 choose_minibuf_frame ();
3451 #endif /* ! 0 */
3453 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3454 pending_autoraise_frame = dpyinfo->x_focus_frame;
3455 else
3456 pending_autoraise_frame = 0;
3459 x_frame_rehighlight (dpyinfo);
3462 /* Handle FocusIn and FocusOut state changes for FRAME.
3463 If FRAME has focus and there exists more than one frame, puts
3464 a FOCUS_IN_EVENT into *BUFP. */
3466 static void
3467 mac_focus_changed (type, dpyinfo, frame, bufp)
3468 int type;
3469 struct mac_display_info *dpyinfo;
3470 struct frame *frame;
3471 struct input_event *bufp;
3473 if (type == activeFlag)
3475 if (dpyinfo->x_focus_event_frame != frame)
3477 x_new_focus_frame (dpyinfo, frame);
3478 dpyinfo->x_focus_event_frame = frame;
3480 /* Don't stop displaying the initial startup message
3481 for a switch-frame event we don't need. */
3482 if (GC_NILP (Vterminal_frame)
3483 && GC_CONSP (Vframe_list)
3484 && !GC_NILP (XCDR (Vframe_list)))
3486 bufp->kind = FOCUS_IN_EVENT;
3487 XSETFRAME (bufp->frame_or_window, frame);
3491 else
3493 if (dpyinfo->x_focus_event_frame == frame)
3495 dpyinfo->x_focus_event_frame = 0;
3496 x_new_focus_frame (dpyinfo, 0);
3501 /* The focus may have changed. Figure out if it is a real focus change,
3502 by checking both FocusIn/Out and Enter/LeaveNotify events.
3504 Returns FOCUS_IN_EVENT event in *BUFP. */
3506 static void
3507 x_detect_focus_change (dpyinfo, event, bufp)
3508 struct mac_display_info *dpyinfo;
3509 EventRecord *event;
3510 struct input_event *bufp;
3512 struct frame *frame;
3514 frame = mac_window_to_frame ((WindowPtr) event->message);
3515 if (! frame)
3516 return;
3518 /* On Mac, this is only called from focus events, so no switch needed. */
3519 mac_focus_changed ((event->modifiers & activeFlag),
3520 dpyinfo, frame, bufp);
3524 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3526 void
3527 x_mouse_leave (dpyinfo)
3528 struct x_display_info *dpyinfo;
3530 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3533 /* The focus has changed, or we have redirected a frame's focus to
3534 another frame (this happens when a frame uses a surrogate
3535 mini-buffer frame). Shift the highlight as appropriate.
3537 The FRAME argument doesn't necessarily have anything to do with which
3538 frame is being highlighted or un-highlighted; we only use it to find
3539 the appropriate X display info. */
3541 static void
3542 XTframe_rehighlight (frame)
3543 struct frame *frame;
3545 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3548 static void
3549 x_frame_rehighlight (dpyinfo)
3550 struct x_display_info *dpyinfo;
3552 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3554 if (dpyinfo->x_focus_frame)
3556 dpyinfo->x_highlight_frame
3557 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3558 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3559 : dpyinfo->x_focus_frame);
3560 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3562 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3563 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3566 else
3567 dpyinfo->x_highlight_frame = 0;
3569 if (dpyinfo->x_highlight_frame != old_highlight)
3571 if (old_highlight)
3572 frame_unhighlight (old_highlight);
3573 if (dpyinfo->x_highlight_frame)
3574 frame_highlight (dpyinfo->x_highlight_frame);
3580 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3582 #if 0 /* MAC_TODO */
3583 /* Initialize mode_switch_bit and modifier_meaning. */
3584 static void
3585 x_find_modifier_meanings (dpyinfo)
3586 struct x_display_info *dpyinfo;
3588 int min_code, max_code;
3589 KeySym *syms;
3590 int syms_per_code;
3591 XModifierKeymap *mods;
3593 dpyinfo->meta_mod_mask = 0;
3594 dpyinfo->shift_lock_mask = 0;
3595 dpyinfo->alt_mod_mask = 0;
3596 dpyinfo->super_mod_mask = 0;
3597 dpyinfo->hyper_mod_mask = 0;
3599 #ifdef HAVE_X11R4
3600 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3601 #else
3602 min_code = dpyinfo->display->min_keycode;
3603 max_code = dpyinfo->display->max_keycode;
3604 #endif
3606 syms = XGetKeyboardMapping (dpyinfo->display,
3607 min_code, max_code - min_code + 1,
3608 &syms_per_code);
3609 mods = XGetModifierMapping (dpyinfo->display);
3611 /* Scan the modifier table to see which modifier bits the Meta and
3612 Alt keysyms are on. */
3614 int row, col; /* The row and column in the modifier table. */
3616 for (row = 3; row < 8; row++)
3617 for (col = 0; col < mods->max_keypermod; col++)
3619 KeyCode code
3620 = mods->modifiermap[(row * mods->max_keypermod) + col];
3622 /* Zeroes are used for filler. Skip them. */
3623 if (code == 0)
3624 continue;
3626 /* Are any of this keycode's keysyms a meta key? */
3628 int code_col;
3630 for (code_col = 0; code_col < syms_per_code; code_col++)
3632 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3634 switch (sym)
3636 case XK_Meta_L:
3637 case XK_Meta_R:
3638 dpyinfo->meta_mod_mask |= (1 << row);
3639 break;
3641 case XK_Alt_L:
3642 case XK_Alt_R:
3643 dpyinfo->alt_mod_mask |= (1 << row);
3644 break;
3646 case XK_Hyper_L:
3647 case XK_Hyper_R:
3648 dpyinfo->hyper_mod_mask |= (1 << row);
3649 break;
3651 case XK_Super_L:
3652 case XK_Super_R:
3653 dpyinfo->super_mod_mask |= (1 << row);
3654 break;
3656 case XK_Shift_Lock:
3657 /* Ignore this if it's not on the lock modifier. */
3658 if ((1 << row) == LockMask)
3659 dpyinfo->shift_lock_mask = LockMask;
3660 break;
3667 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3668 if (! dpyinfo->meta_mod_mask)
3670 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3671 dpyinfo->alt_mod_mask = 0;
3674 /* If some keys are both alt and meta,
3675 make them just meta, not alt. */
3676 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3678 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3681 XFree ((char *) syms);
3682 XFreeModifiermap (mods);
3685 #endif /* MAC_TODO */
3687 /* Convert between the modifier bits X uses and the modifier bits
3688 Emacs uses. */
3690 static unsigned int
3691 x_mac_to_emacs_modifiers (dpyinfo, state)
3692 struct x_display_info *dpyinfo;
3693 unsigned short state;
3695 return (((state & shiftKey) ? shift_modifier : 0)
3696 | ((state & controlKey) ? ctrl_modifier : 0)
3697 | ((state & cmdKey) ? meta_modifier : 0)
3698 | ((state & optionKey) ? alt_modifier : 0));
3701 #if 0 /* MAC_TODO */
3702 static unsigned short
3703 x_emacs_to_x_modifiers (dpyinfo, state)
3704 struct x_display_info *dpyinfo;
3705 unsigned int state;
3707 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3708 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3709 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3710 | ((state & shift_modifier) ? ShiftMask : 0)
3711 | ((state & ctrl_modifier) ? ControlMask : 0)
3712 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3714 #endif /* MAC_TODO */
3716 /* Convert a keysym to its name. */
3718 char *
3719 x_get_keysym_name (keysym)
3720 int keysym;
3722 char *value;
3724 BLOCK_INPUT;
3725 #if 0
3726 value = XKeysymToString (keysym);
3727 #else
3728 value = 0;
3729 #endif
3730 UNBLOCK_INPUT;
3732 return value;
3737 /* Function to report a mouse movement to the mainstream Emacs code.
3738 The input handler calls this.
3740 We have received a mouse movement event, which is given in *event.
3741 If the mouse is over a different glyph than it was last time, tell
3742 the mainstream emacs code by setting mouse_moved. If not, ask for
3743 another motion event, so we can check again the next time it moves. */
3745 static Point last_mouse_motion_position;
3746 static Lisp_Object last_mouse_motion_frame;
3748 static void
3749 note_mouse_movement (frame, pos)
3750 FRAME_PTR frame;
3751 Point *pos;
3753 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3754 #if TARGET_API_MAC_CARBON
3755 Rect r;
3756 #endif
3758 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3759 last_mouse_motion_position = *pos;
3760 XSETFRAME (last_mouse_motion_frame, frame);
3762 #if TARGET_API_MAC_CARBON
3763 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3764 #else
3765 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3766 #endif
3768 if (frame == dpyinfo->mouse_face_mouse_frame)
3769 /* This case corresponds to LeaveNotify in X11. */
3771 /* If we move outside the frame, then we're certainly no
3772 longer on any text in the frame. */
3773 clear_mouse_face (dpyinfo);
3774 dpyinfo->mouse_face_mouse_frame = 0;
3775 if (!dpyinfo->grabbed)
3776 rif->define_frame_cursor (frame,
3777 frame->output_data.mac->nontext_cursor);
3780 /* Has the mouse moved off the glyph it was on at the last sighting? */
3781 else if (pos->h < last_mouse_glyph.left
3782 || pos->h >= last_mouse_glyph.right
3783 || pos->v < last_mouse_glyph.top
3784 || pos->v >= last_mouse_glyph.bottom)
3786 frame->mouse_moved = 1;
3787 last_mouse_scroll_bar = Qnil;
3788 note_mouse_highlight (frame, pos->h, pos->v);
3793 /************************************************************************
3794 Mouse Face
3795 ************************************************************************/
3797 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3800 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3802 static void
3803 redo_mouse_highlight ()
3805 if (!NILP (last_mouse_motion_frame)
3806 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3807 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3808 last_mouse_motion_position.h,
3809 last_mouse_motion_position.v);
3813 /* Try to determine frame pixel position and size of the glyph under
3814 frame pixel coordinates X/Y on frame F . Return the position and
3815 size in *RECT. Value is non-zero if we could compute these
3816 values. */
3818 static int
3819 glyph_rect (f, x, y, rect)
3820 struct frame *f;
3821 int x, y;
3822 Rect *rect;
3824 Lisp_Object window;
3826 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3828 if (!NILP (window))
3830 struct window *w = XWINDOW (window);
3831 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3832 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3834 for (; r < end && r->enabled_p; ++r)
3835 if (r->y <= y && r->y + r->height > y)
3837 /* Found the row at y. */
3838 struct glyph *g = r->glyphs[TEXT_AREA];
3839 struct glyph *end = g + r->used[TEXT_AREA];
3840 int gx;
3842 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3843 rect->bottom = rect->top + r->height;
3845 if (x < r->x)
3847 /* x is to the left of the first glyph in the row. */
3848 /* Shouldn't this be a pixel value?
3849 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3850 ++KFS */
3851 rect->left = WINDOW_LEFT_EDGE_COL (w);
3852 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3853 return 1;
3856 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3857 if (gx <= x && gx + g->pixel_width > x)
3859 /* x is on a glyph. */
3860 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3861 rect->right = rect->left + g->pixel_width;
3862 return 1;
3865 /* x is to the right of the last glyph in the row. */
3866 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3867 /* Shouldn't this be a pixel value?
3868 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3869 ++KFS */
3870 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3871 return 1;
3875 /* The y is not on any row. */
3876 return 0;
3879 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3881 /* Record the position of the mouse in last_mouse_glyph. */
3882 static void
3883 remember_mouse_glyph (f1, gx, gy)
3884 struct frame * f1;
3885 int gx, gy;
3887 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3889 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3890 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3892 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3893 round down even for negative values. */
3894 if (gx < 0)
3895 gx -= width - 1;
3896 if (gy < 0)
3897 gy -= height - 1;
3898 #if 0
3899 /* This was the original code from XTmouse_position, but it seems
3900 to give the position of the glyph diagonally next to the one
3901 the mouse is over. */
3902 gx = (gx + width - 1) / width * width;
3903 gy = (gy + height - 1) / height * height;
3904 #else
3905 gx = gx / width * width;
3906 gy = gy / height * height;
3907 #endif
3909 last_mouse_glyph.left = gx;
3910 last_mouse_glyph.top = gy;
3911 last_mouse_glyph.right = gx + width;
3912 last_mouse_glyph.bottom = gy + height;
3917 static struct frame *
3918 mac_focus_frame (dpyinfo)
3919 struct mac_display_info *dpyinfo;
3921 if (dpyinfo->x_focus_frame)
3922 return dpyinfo->x_focus_frame;
3923 else
3924 /* Mac version may get events, such as a menu bar click, even when
3925 all the frames are invisible. In this case, we regard the
3926 event came to the selected frame. */
3927 return SELECTED_FRAME ();
3931 /* Return the current position of the mouse.
3932 *fp should be a frame which indicates which display to ask about.
3934 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3935 and *part to the frame, window, and scroll bar part that the mouse
3936 is over. Set *x and *y to the portion and whole of the mouse's
3937 position on the scroll bar.
3939 If the mouse movement started elsewhere, set *fp to the frame the
3940 mouse is on, *bar_window to nil, and *x and *y to the character cell
3941 the mouse is over.
3943 Set *time to the server time-stamp for the time at which the mouse
3944 was at this position.
3946 Don't store anything if we don't have a valid set of values to report.
3948 This clears the mouse_moved flag, so we can wait for the next mouse
3949 movement. */
3951 static void
3952 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3953 FRAME_PTR *fp;
3954 int insist;
3955 Lisp_Object *bar_window;
3956 enum scroll_bar_part *part;
3957 Lisp_Object *x, *y;
3958 unsigned long *time;
3960 Point mouse_pos;
3961 int ignore1, ignore2;
3962 struct frame *f = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
3963 WindowPtr wp = FRAME_MAC_WINDOW (f);
3964 Lisp_Object frame, tail;
3966 BLOCK_INPUT;
3968 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3969 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3970 else
3972 /* Clear the mouse-moved flag for every frame on this display. */
3973 FOR_EACH_FRAME (tail, frame)
3974 XFRAME (frame)->mouse_moved = 0;
3976 last_mouse_scroll_bar = Qnil;
3978 SetPortWindowPort (wp);
3980 GetMouse (&mouse_pos);
3982 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3983 &last_mouse_glyph, insist);
3985 *bar_window = Qnil;
3986 *part = scroll_bar_handle;
3987 *fp = f;
3988 XSETINT (*x, mouse_pos.h);
3989 XSETINT (*y, mouse_pos.v);
3990 *time = last_mouse_movement_time;
3993 UNBLOCK_INPUT;
3997 /************************************************************************
3998 Toolkit scroll bars
3999 ************************************************************************/
4001 #ifdef USE_TOOLKIT_SCROLL_BARS
4003 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4004 static OSStatus install_scroll_bar_timer P_ ((void));
4005 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4006 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4007 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4008 struct input_event *));
4009 static OSErr get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
4010 Rect *));
4011 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4012 ControlPartCode,
4013 struct input_event *));
4014 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4015 struct input_event *));
4016 static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
4017 Point, struct input_event *));
4018 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4019 int, int, int));
4021 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4023 static int last_scroll_bar_part;
4025 static EventLoopTimerRef scroll_bar_timer;
4027 static int scroll_bar_timer_event_posted_p;
4029 #define SCROLL_BAR_FIRST_DELAY 0.5
4030 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4032 static pascal void
4033 scroll_bar_timer_callback (timer, data)
4034 EventLoopTimerRef timer;
4035 void *data;
4037 EventRef event = NULL;
4038 OSErr err;
4040 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
4041 kEventAttributeNone, &event);
4042 if (err == noErr)
4044 Point mouse_pos;
4046 GetMouse (&mouse_pos);
4047 LocalToGlobal (&mouse_pos);
4048 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
4049 sizeof (Point), &mouse_pos);
4051 if (err == noErr)
4053 UInt32 modifiers = GetCurrentKeyModifiers ();
4055 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
4056 sizeof (UInt32), &modifiers);
4058 if (err == noErr)
4059 err = PostEventToQueue (GetCurrentEventQueue (), event,
4060 kEventPriorityStandard);
4061 if (err == noErr)
4062 scroll_bar_timer_event_posted_p = 1;
4064 if (event)
4065 ReleaseEvent (event);
4068 static OSStatus
4069 install_scroll_bar_timer ()
4071 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4073 if (scroll_bar_timer_callbackUPP == NULL)
4074 scroll_bar_timer_callbackUPP =
4075 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4077 if (scroll_bar_timer == NULL)
4078 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4079 kEventDurationForever as delays. */
4080 return
4081 InstallEventLoopTimer (GetCurrentEventLoop (),
4082 kEventDurationForever, kEventDurationForever,
4083 scroll_bar_timer_callbackUPP, NULL,
4084 &scroll_bar_timer);
4087 static OSStatus
4088 set_scroll_bar_timer (delay)
4089 EventTimerInterval delay;
4091 if (scroll_bar_timer == NULL)
4092 install_scroll_bar_timer ();
4094 scroll_bar_timer_event_posted_p = 0;
4096 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4099 static int
4100 control_part_code_to_scroll_bar_part (part_code)
4101 ControlPartCode part_code;
4103 switch (part_code)
4105 case kControlUpButtonPart: return scroll_bar_up_arrow;
4106 case kControlDownButtonPart: return scroll_bar_down_arrow;
4107 case kControlPageUpPart: return scroll_bar_above_handle;
4108 case kControlPageDownPart: return scroll_bar_below_handle;
4109 case kControlIndicatorPart: return scroll_bar_handle;
4112 return -1;
4115 static void
4116 construct_scroll_bar_click (bar, part, bufp)
4117 struct scroll_bar *bar;
4118 int part;
4119 struct input_event *bufp;
4121 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4122 bufp->frame_or_window = bar->window;
4123 bufp->arg = Qnil;
4124 bufp->part = part;
4125 bufp->code = 0;
4126 XSETINT (bufp->x, 0);
4127 XSETINT (bufp->y, 0);
4128 bufp->modifiers = 0;
4131 static OSErr
4132 get_control_part_bounds (ch, part_code, rect)
4133 ControlHandle ch;
4134 ControlPartCode part_code;
4135 Rect *rect;
4137 RgnHandle region = NewRgn ();
4138 OSStatus err;
4140 err = GetControlRegion (ch, part_code, region);
4141 if (err == noErr)
4142 GetRegionBounds (region, rect);
4143 DisposeRgn (region);
4145 return err;
4148 static void
4149 x_scroll_bar_handle_press (bar, part_code, bufp)
4150 struct scroll_bar *bar;
4151 ControlPartCode part_code;
4152 struct input_event *bufp;
4154 int part = control_part_code_to_scroll_bar_part (part_code);
4156 if (part < 0)
4157 return;
4159 if (part != scroll_bar_handle)
4161 construct_scroll_bar_click (bar, part, bufp);
4162 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4163 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4166 last_scroll_bar_part = part;
4167 bar->dragging = Qnil;
4168 tracked_scroll_bar = bar;
4171 static void
4172 x_scroll_bar_handle_release (bar, bufp)
4173 struct scroll_bar *bar;
4174 struct input_event *bufp;
4176 if (last_scroll_bar_part != scroll_bar_handle
4177 || !GC_NILP (bar->dragging))
4178 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp);
4180 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4181 set_scroll_bar_timer (kEventDurationForever);
4183 last_scroll_bar_part = -1;
4184 bar->dragging = Qnil;
4185 tracked_scroll_bar = NULL;
4188 static void
4189 x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp)
4190 WindowPtr win;
4191 struct scroll_bar *bar;
4192 Point mouse_pos;
4193 struct input_event *bufp;
4195 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4197 if (last_scroll_bar_part == scroll_bar_handle)
4199 int top, top_range;
4200 Rect r;
4202 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4203 kControlIndicatorPart, &r);
4205 if (GC_NILP (bar->dragging))
4206 XSETINT (bar->dragging, mouse_pos.v - r.top);
4208 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4209 top_range = (XINT (bar->track_height) - (r.bottom - r.top)) *
4210 (1.0 + (float) GetControlViewSize (ch) / GetControl32BitMaximum (ch))
4211 + .5;
4213 if (top < 0)
4214 top = 0;
4215 if (top > top_range)
4216 top = top_range;
4218 construct_scroll_bar_click (bar, scroll_bar_handle, bufp);
4219 XSETINT (bufp->x, top);
4220 XSETINT (bufp->y, top_range);
4222 else
4224 ControlPartCode part_code;
4225 int unhilite_p = 0, part;
4227 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4228 unhilite_p = 1;
4229 else
4231 part = control_part_code_to_scroll_bar_part (part_code);
4233 switch (last_scroll_bar_part)
4235 case scroll_bar_above_handle:
4236 case scroll_bar_below_handle:
4237 if (part != scroll_bar_above_handle
4238 && part != scroll_bar_below_handle)
4239 unhilite_p = 1;
4240 break;
4242 case scroll_bar_up_arrow:
4243 case scroll_bar_down_arrow:
4244 if (part != scroll_bar_up_arrow
4245 && part != scroll_bar_down_arrow)
4246 unhilite_p = 1;
4247 break;
4251 if (unhilite_p)
4252 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4253 else if (part != last_scroll_bar_part
4254 || scroll_bar_timer_event_posted_p)
4256 construct_scroll_bar_click (bar, part, bufp);
4257 last_scroll_bar_part = part;
4258 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4259 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4264 /* Set the thumb size and position of scroll bar BAR. We are currently
4265 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4267 static void
4268 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4269 struct scroll_bar *bar;
4270 int portion, position, whole;
4272 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4274 int value, viewsize, maximum;
4276 if (whole == 0 || XINT (bar->track_height) == 0)
4277 value = 0, viewsize = 1, maximum = 0;
4278 else
4280 value = position;
4281 viewsize = portion;
4282 maximum = max (0, whole - portion);
4285 BLOCK_INPUT;
4287 SetControl32BitMinimum (ch, 0);
4288 SetControl32BitMaximum (ch, maximum);
4289 SetControl32BitValue (ch, value);
4290 SetControlViewSize (ch, viewsize);
4292 UNBLOCK_INPUT;
4295 #endif /* USE_TOOLKIT_SCROLL_BARS */
4299 /************************************************************************
4300 Scroll bars, general
4301 ************************************************************************/
4303 /* Create a scroll bar and return the scroll bar vector for it. W is
4304 the Emacs window on which to create the scroll bar. TOP, LEFT,
4305 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4306 scroll bar. */
4308 static struct scroll_bar *
4309 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4310 struct window *w;
4311 int top, left, width, height, disp_top, disp_height;
4313 struct frame *f = XFRAME (w->frame);
4314 struct scroll_bar *bar
4315 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4316 Rect r;
4317 ControlHandle ch;
4319 BLOCK_INPUT;
4321 r.left = left;
4322 r.top = disp_top;
4323 r.right = left + width;
4324 r.bottom = disp_top + disp_height;
4326 #if TARGET_API_MAC_CARBON
4327 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4328 0, 0, 0, kControlScrollBarProc, (long) bar);
4329 #else
4330 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height,
4331 0, 0, 0, scrollBarProc, (long) bar);
4332 #endif
4333 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4335 XSETWINDOW (bar->window, w);
4336 XSETINT (bar->top, top);
4337 XSETINT (bar->left, left);
4338 XSETINT (bar->width, width);
4339 XSETINT (bar->height, height);
4340 XSETINT (bar->start, 0);
4341 XSETINT (bar->end, 0);
4342 bar->dragging = Qnil;
4343 #ifdef USE_TOOLKIT_SCROLL_BARS
4344 bar->track_top = Qnil;
4345 bar->track_height = Qnil;
4346 #endif
4348 /* Add bar to its frame's list of scroll bars. */
4349 bar->next = FRAME_SCROLL_BARS (f);
4350 bar->prev = Qnil;
4351 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4352 if (!NILP (bar->next))
4353 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4355 UNBLOCK_INPUT;
4356 return bar;
4360 /* Draw BAR's handle in the proper position.
4362 If the handle is already drawn from START to END, don't bother
4363 redrawing it, unless REBUILD is non-zero; in that case, always
4364 redraw it. (REBUILD is handy for drawing the handle after expose
4365 events.)
4367 Normally, we want to constrain the start and end of the handle to
4368 fit inside its rectangle, but if the user is dragging the scroll
4369 bar handle, we want to let them drag it down all the way, so that
4370 the bar's top is as far down as it goes; otherwise, there's no way
4371 to move to the very end of the buffer. */
4373 #ifndef USE_TOOLKIT_SCROLL_BARS
4375 static void
4376 x_scroll_bar_set_handle (bar, start, end, rebuild)
4377 struct scroll_bar *bar;
4378 int start, end;
4379 int rebuild;
4381 int dragging = ! NILP (bar->dragging);
4382 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4383 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4384 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4385 int length = end - start;
4387 /* If the display is already accurate, do nothing. */
4388 if (! rebuild
4389 && start == XINT (bar->start)
4390 && end == XINT (bar->end))
4391 return;
4393 BLOCK_INPUT;
4395 /* Make sure the values are reasonable, and try to preserve the
4396 distance between start and end. */
4397 if (start < 0)
4398 start = 0;
4399 else if (start > top_range)
4400 start = top_range;
4401 end = start + length;
4403 if (end < start)
4404 end = start;
4405 else if (end > top_range && ! dragging)
4406 end = top_range;
4408 /* Store the adjusted setting in the scroll bar. */
4409 XSETINT (bar->start, start);
4410 XSETINT (bar->end, end);
4412 /* Clip the end position, just for display. */
4413 if (end > top_range)
4414 end = top_range;
4416 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4417 top positions, to make sure the handle is always at least that
4418 many pixels tall. */
4419 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4421 SetControlMinimum (ch, 0);
4422 /* Don't inadvertently activate deactivated scroll bars */
4423 if (GetControlMaximum (ch) != -1)
4424 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4425 - (end - start));
4426 SetControlValue (ch, start);
4427 #if TARGET_API_MAC_CARBON
4428 SetControlViewSize (ch, end - start);
4429 #endif
4431 UNBLOCK_INPUT;
4434 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4436 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4437 nil. */
4439 static void
4440 x_scroll_bar_remove (bar)
4441 struct scroll_bar *bar;
4443 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4445 BLOCK_INPUT;
4447 /* Destroy the Mac scroll bar control */
4448 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4450 /* Disassociate this scroll bar from its window. */
4451 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4453 UNBLOCK_INPUT;
4457 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4458 that we are displaying PORTION characters out of a total of WHOLE
4459 characters, starting at POSITION. If WINDOW has no scroll bar,
4460 create one. */
4462 static void
4463 XTset_vertical_scroll_bar (w, portion, whole, position)
4464 struct window *w;
4465 int portion, whole, position;
4467 struct frame *f = XFRAME (w->frame);
4468 struct scroll_bar *bar;
4469 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4470 int window_y, window_height;
4472 /* Get window dimensions. */
4473 window_box (w, -1, 0, &window_y, 0, &window_height);
4474 top = window_y;
4475 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4476 height = window_height;
4478 /* Compute the left edge of the scroll bar area. */
4479 left = WINDOW_SCROLL_BAR_AREA_X (w);
4481 /* Compute the width of the scroll bar which might be less than
4482 the width of the area reserved for the scroll bar. */
4483 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4484 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4485 else
4486 sb_width = width;
4488 /* Compute the left edge of the scroll bar. */
4489 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4490 sb_left = left;
4491 else
4492 sb_left = left + width - sb_width;
4494 /* Adjustments according to Inside Macintosh to make it look nice */
4495 disp_top = top;
4496 disp_height = height;
4497 if (disp_top == 0)
4499 disp_top = -1;
4500 disp_height++;
4502 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4504 disp_top++;
4505 disp_height--;
4508 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4509 sb_left++;
4511 /* Does the scroll bar exist yet? */
4512 if (NILP (w->vertical_scroll_bar))
4514 BLOCK_INPUT;
4515 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4516 left, top, width, height, 0);
4517 UNBLOCK_INPUT;
4518 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4519 disp_height);
4520 XSETVECTOR (w->vertical_scroll_bar, bar);
4522 else
4524 /* It may just need to be moved and resized. */
4525 ControlHandle ch;
4527 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4528 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4530 BLOCK_INPUT;
4532 /* If already correctly positioned, do nothing. */
4533 if (!(XINT (bar->left) == sb_left
4534 && XINT (bar->top) == top
4535 && XINT (bar->width) == sb_width
4536 && XINT (bar->height) == height))
4538 /* Since toolkit scroll bars are smaller than the space reserved
4539 for them on the frame, we have to clear "under" them. */
4540 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4541 left, top, width, height, 0);
4543 #if 0
4544 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4545 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4546 sb_left - 1, top, 1, height, 0);
4547 #endif
4549 HideControl (ch);
4550 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4551 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4552 disp_height);
4553 if (sb_width < disp_height)
4554 ShowControl (ch);
4556 /* Remember new settings. */
4557 XSETINT (bar->left, sb_left);
4558 XSETINT (bar->top, top);
4559 XSETINT (bar->width, sb_width);
4560 XSETINT (bar->height, height);
4561 #ifdef USE_TOOLKIT_SCROLL_BARS
4562 bar->track_top = Qnil;
4563 bar->track_height = Qnil;
4564 #endif
4567 UNBLOCK_INPUT;
4570 #ifdef USE_TOOLKIT_SCROLL_BARS
4571 if (NILP (bar->track_top))
4573 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4574 Rect r0, r1;
4576 BLOCK_INPUT;
4578 SetControl32BitMinimum (ch, 0);
4579 SetControl32BitMaximum (ch, 1);
4580 SetControlViewSize (ch, 1);
4582 /* Move the scroll bar thumb to the top. */
4583 SetControl32BitValue (ch, 0);
4584 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
4586 /* Move the scroll bar thumb to the bottom. */
4587 SetControl32BitValue (ch, 1);
4588 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
4590 UnionRect (&r0, &r1, &r0);
4591 XSETINT (bar->track_top, r0.top);
4592 XSETINT (bar->track_height, r0.bottom - r0.top);
4594 UNBLOCK_INPUT;
4597 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4598 #else /* not USE_TOOLKIT_SCROLL_BARS */
4599 /* Set the scroll bar's current state, unless we're currently being
4600 dragged. */
4601 if (NILP (bar->dragging))
4603 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4605 if (whole == 0)
4606 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4607 else
4609 int start = ((double) position * top_range) / whole;
4610 int end = ((double) (position + portion) * top_range) / whole;
4611 x_scroll_bar_set_handle (bar, start, end, 0);
4614 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4618 /* The following three hooks are used when we're doing a thorough
4619 redisplay of the frame. We don't explicitly know which scroll bars
4620 are going to be deleted, because keeping track of when windows go
4621 away is a real pain - "Can you say set-window-configuration, boys
4622 and girls?" Instead, we just assert at the beginning of redisplay
4623 that *all* scroll bars are to be removed, and then save a scroll bar
4624 from the fiery pit when we actually redisplay its window. */
4626 /* Arrange for all scroll bars on FRAME to be removed at the next call
4627 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4628 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4630 static void
4631 XTcondemn_scroll_bars (frame)
4632 FRAME_PTR frame;
4634 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4635 while (! NILP (FRAME_SCROLL_BARS (frame)))
4637 Lisp_Object bar;
4638 bar = FRAME_SCROLL_BARS (frame);
4639 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4640 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4641 XSCROLL_BAR (bar)->prev = Qnil;
4642 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4643 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4644 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4649 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4650 Note that WINDOW isn't necessarily condemned at all. */
4652 static void
4653 XTredeem_scroll_bar (window)
4654 struct window *window;
4656 struct scroll_bar *bar;
4657 struct frame *f;
4659 /* We can't redeem this window's scroll bar if it doesn't have one. */
4660 if (NILP (window->vertical_scroll_bar))
4661 abort ();
4663 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4665 /* Unlink it from the condemned list. */
4666 f = XFRAME (WINDOW_FRAME (window));
4667 if (NILP (bar->prev))
4669 /* If the prev pointer is nil, it must be the first in one of
4670 the lists. */
4671 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4672 /* It's not condemned. Everything's fine. */
4673 return;
4674 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4675 window->vertical_scroll_bar))
4676 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4677 else
4678 /* If its prev pointer is nil, it must be at the front of
4679 one or the other! */
4680 abort ();
4682 else
4683 XSCROLL_BAR (bar->prev)->next = bar->next;
4685 if (! NILP (bar->next))
4686 XSCROLL_BAR (bar->next)->prev = bar->prev;
4688 bar->next = FRAME_SCROLL_BARS (f);
4689 bar->prev = Qnil;
4690 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4691 if (! NILP (bar->next))
4692 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4695 /* Remove all scroll bars on FRAME that haven't been saved since the
4696 last call to `*condemn_scroll_bars_hook'. */
4698 static void
4699 XTjudge_scroll_bars (f)
4700 FRAME_PTR f;
4702 Lisp_Object bar, next;
4704 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4706 /* Clear out the condemned list now so we won't try to process any
4707 more events on the hapless scroll bars. */
4708 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4710 for (; ! NILP (bar); bar = next)
4712 struct scroll_bar *b = XSCROLL_BAR (bar);
4714 x_scroll_bar_remove (b);
4716 next = b->next;
4717 b->next = b->prev = Qnil;
4720 /* Now there should be no references to the condemned scroll bars,
4721 and they should get garbage-collected. */
4725 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4726 is set to something other than NO_EVENT, it is enqueued.
4728 This may be called from a signal handler, so we have to ignore GC
4729 mark bits. */
4731 static void
4732 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4733 struct scroll_bar *bar;
4734 ControlPartCode part_code;
4735 EventRecord *er;
4736 struct input_event *bufp;
4738 int win_y, top_range;
4740 if (! GC_WINDOWP (bar->window))
4741 abort ();
4743 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4744 bufp->frame_or_window = bar->window;
4745 bufp->arg = Qnil;
4747 bar->dragging = Qnil;
4749 switch (part_code)
4751 case kControlUpButtonPart:
4752 bufp->part = scroll_bar_up_arrow;
4753 break;
4754 case kControlDownButtonPart:
4755 bufp->part = scroll_bar_down_arrow;
4756 break;
4757 case kControlPageUpPart:
4758 bufp->part = scroll_bar_above_handle;
4759 break;
4760 case kControlPageDownPart:
4761 bufp->part = scroll_bar_below_handle;
4762 break;
4763 #if TARGET_API_MAC_CARBON
4764 default:
4765 #else
4766 case kControlIndicatorPart:
4767 #endif
4768 if (er->what == mouseDown)
4769 bar->dragging = make_number (0);
4770 XSETVECTOR (last_mouse_scroll_bar, bar);
4771 bufp->part = scroll_bar_handle;
4772 break;
4775 win_y = XINT (bufp->y) - XINT (bar->top);
4776 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4778 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4780 win_y -= 24;
4782 if (! NILP (bar->dragging))
4783 win_y -= XINT (bar->dragging);
4785 if (win_y < 0)
4786 win_y = 0;
4787 if (win_y > top_range)
4788 win_y = top_range;
4790 XSETINT (bufp->x, win_y);
4791 XSETINT (bufp->y, top_range);
4794 #ifndef USE_TOOLKIT_SCROLL_BARS
4796 /* Handle some mouse motion while someone is dragging the scroll bar.
4798 This may be called from a signal handler, so we have to ignore GC
4799 mark bits. */
4801 static void
4802 x_scroll_bar_note_movement (bar, y_pos, t)
4803 struct scroll_bar *bar;
4804 int y_pos;
4805 Time t;
4807 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4809 last_mouse_movement_time = t;
4811 f->mouse_moved = 1;
4812 XSETVECTOR (last_mouse_scroll_bar, bar);
4814 /* If we're dragging the bar, display it. */
4815 if (! GC_NILP (bar->dragging))
4817 /* Where should the handle be now? */
4818 int new_start = y_pos - 24;
4820 if (new_start != XINT (bar->start))
4822 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4824 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4829 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4831 /* Return information to the user about the current position of the mouse
4832 on the scroll bar. */
4834 static void
4835 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4836 FRAME_PTR *fp;
4837 Lisp_Object *bar_window;
4838 enum scroll_bar_part *part;
4839 Lisp_Object *x, *y;
4840 unsigned long *time;
4842 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4843 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4844 #if TARGET_API_MAC_CARBON
4845 WindowPtr wp = GetControlOwner (ch);
4846 #else
4847 WindowPtr wp = (*ch)->contrlOwner;
4848 #endif
4849 Point mouse_pos;
4850 struct frame *f = mac_window_to_frame (wp);
4851 int win_y, top_range;
4853 SetPortWindowPort (wp);
4855 GetMouse (&mouse_pos);
4857 win_y = mouse_pos.v - XINT (bar->top);
4858 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4860 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4862 win_y -= 24;
4864 if (! NILP (bar->dragging))
4865 win_y -= XINT (bar->dragging);
4867 if (win_y < 0)
4868 win_y = 0;
4869 if (win_y > top_range)
4870 win_y = top_range;
4872 *fp = f;
4873 *bar_window = bar->window;
4875 if (! NILP (bar->dragging))
4876 *part = scroll_bar_handle;
4877 else if (win_y < XINT (bar->start))
4878 *part = scroll_bar_above_handle;
4879 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4880 *part = scroll_bar_handle;
4881 else
4882 *part = scroll_bar_below_handle;
4884 XSETINT (*x, win_y);
4885 XSETINT (*y, top_range);
4887 f->mouse_moved = 0;
4888 last_mouse_scroll_bar = Qnil;
4890 *time = last_mouse_movement_time;
4894 /* The screen has been cleared so we may have changed foreground or
4895 background colors, and the scroll bars may need to be redrawn.
4896 Clear out the scroll bars, and ask for expose events, so we can
4897 redraw them. */
4899 void
4900 x_scroll_bar_clear (f)
4901 FRAME_PTR f;
4903 XTcondemn_scroll_bars (f);
4904 XTjudge_scroll_bars (f);
4908 /***********************************************************************
4909 Text Cursor
4910 ***********************************************************************/
4912 /* Set clipping for output in glyph row ROW. W is the window in which
4913 we operate. GC is the graphics context to set clipping in.
4915 ROW may be a text row or, e.g., a mode line. Text rows must be
4916 clipped to the interior of the window dedicated to text display,
4917 mode lines must be clipped to the whole window. */
4919 static void
4920 x_clip_to_row (w, row, area, gc)
4921 struct window *w;
4922 struct glyph_row *row;
4923 int area;
4924 GC gc;
4926 struct frame *f = XFRAME (WINDOW_FRAME (w));
4927 Rect clip_rect;
4928 int window_x, window_y, window_width;
4930 window_box (w, area, &window_x, &window_y, &window_width, 0);
4932 clip_rect.left = window_x;
4933 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4934 clip_rect.top = max (clip_rect.top, window_y);
4935 clip_rect.right = clip_rect.left + window_width;
4936 clip_rect.bottom = clip_rect.top + row->visible_height;
4938 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4942 /* Draw a hollow box cursor on window W in glyph row ROW. */
4944 static void
4945 x_draw_hollow_cursor (w, row)
4946 struct window *w;
4947 struct glyph_row *row;
4949 struct frame *f = XFRAME (WINDOW_FRAME (w));
4950 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4951 Display *dpy = FRAME_MAC_DISPLAY (f);
4952 int x, y, wd, h;
4953 XGCValues xgcv;
4954 struct glyph *cursor_glyph;
4955 GC gc;
4957 /* Get the glyph the cursor is on. If we can't tell because
4958 the current matrix is invalid or such, give up. */
4959 cursor_glyph = get_phys_cursor_glyph (w);
4960 if (cursor_glyph == NULL)
4961 return;
4963 /* Compute frame-relative coordinates for phys cursor. */
4964 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4965 y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
4966 wd = w->phys_cursor_width;
4968 /* The foreground of cursor_gc is typically the same as the normal
4969 background color, which can cause the cursor box to be invisible. */
4970 xgcv.foreground = f->output_data.mac->cursor_pixel;
4971 if (dpyinfo->scratch_cursor_gc)
4972 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4973 else
4974 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4975 GCForeground, &xgcv);
4976 gc = dpyinfo->scratch_cursor_gc;
4978 /* Set clipping, draw the rectangle, and reset clipping again. */
4979 x_clip_to_row (w, row, TEXT_AREA, gc);
4980 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4981 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4985 /* Draw a bar cursor on window W in glyph row ROW.
4987 Implementation note: One would like to draw a bar cursor with an
4988 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4989 Unfortunately, I didn't find a font yet that has this property set.
4990 --gerd. */
4992 static void
4993 x_draw_bar_cursor (w, row, width, kind)
4994 struct window *w;
4995 struct glyph_row *row;
4996 int width;
4997 enum text_cursor_kinds kind;
4999 struct frame *f = XFRAME (w->frame);
5000 struct glyph *cursor_glyph;
5002 /* If cursor is out of bounds, don't draw garbage. This can happen
5003 in mini-buffer windows when switching between echo area glyphs
5004 and mini-buffer. */
5005 cursor_glyph = get_phys_cursor_glyph (w);
5006 if (cursor_glyph == NULL)
5007 return;
5009 /* If on an image, draw like a normal cursor. That's usually better
5010 visible than drawing a bar, esp. if the image is large so that
5011 the bar might not be in the window. */
5012 if (cursor_glyph->type == IMAGE_GLYPH)
5014 struct glyph_row *row;
5015 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5016 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5018 else
5020 Display *dpy = FRAME_MAC_DISPLAY (f);
5021 Window window = FRAME_MAC_WINDOW (f);
5022 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5023 unsigned long mask = GCForeground | GCBackground;
5024 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5025 XGCValues xgcv;
5027 /* If the glyph's background equals the color we normally draw
5028 the bar cursor in, the bar cursor in its normal color is
5029 invisible. Use the glyph's foreground color instead in this
5030 case, on the assumption that the glyph's colors are chosen so
5031 that the glyph is legible. */
5032 if (face->background == f->output_data.mac->cursor_pixel)
5033 xgcv.background = xgcv.foreground = face->foreground;
5034 else
5035 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5037 if (gc)
5038 XChangeGC (dpy, gc, mask, &xgcv);
5039 else
5041 gc = XCreateGC (dpy, window, mask, &xgcv);
5042 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5045 if (width < 0)
5046 width = FRAME_CURSOR_WIDTH (f);
5047 width = min (cursor_glyph->pixel_width, width);
5049 w->phys_cursor_width = width;
5050 x_clip_to_row (w, row, TEXT_AREA, gc);
5052 if (kind == BAR_CURSOR)
5053 XFillRectangle (dpy, window, gc,
5054 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5055 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5056 width, row->height);
5057 else
5058 XFillRectangle (dpy, window, gc,
5059 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5060 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5061 row->height - width),
5062 cursor_glyph->pixel_width,
5063 width);
5065 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
5070 /* RIF: Define cursor CURSOR on frame F. */
5072 static void
5073 mac_define_frame_cursor (f, cursor)
5074 struct frame *f;
5075 Cursor cursor;
5077 SetThemeCursor (cursor);
5081 /* RIF: Clear area on frame F. */
5083 static void
5084 mac_clear_frame_area (f, x, y, width, height)
5085 struct frame *f;
5086 int x, y, width, height;
5088 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5089 x, y, width, height, 0);
5093 /* RIF: Draw cursor on window W. */
5095 static void
5096 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5097 struct window *w;
5098 struct glyph_row *glyph_row;
5099 int x, y;
5100 int cursor_type, cursor_width;
5101 int on_p, active_p;
5103 if (on_p)
5105 w->phys_cursor_type = cursor_type;
5106 w->phys_cursor_on_p = 1;
5108 if (glyph_row->exact_window_width_line_p
5109 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5111 glyph_row->cursor_in_fringe_p = 1;
5112 draw_fringe_bitmap (w, glyph_row, 0);
5114 else
5115 switch (cursor_type)
5117 case HOLLOW_BOX_CURSOR:
5118 x_draw_hollow_cursor (w, glyph_row);
5119 break;
5121 case FILLED_BOX_CURSOR:
5122 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5123 break;
5125 case BAR_CURSOR:
5126 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5127 break;
5129 case HBAR_CURSOR:
5130 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5131 break;
5133 case NO_CURSOR:
5134 w->phys_cursor_width = 0;
5135 break;
5137 default:
5138 abort ();
5144 /* Icons. */
5146 #if 0 /* MAC_TODO: no icon support yet. */
5148 x_bitmap_icon (f, icon)
5149 struct frame *f;
5150 Lisp_Object icon;
5152 HANDLE hicon;
5154 if (FRAME_W32_WINDOW (f) == 0)
5155 return 1;
5157 if (NILP (icon))
5158 hicon = LoadIcon (hinst, EMACS_CLASS);
5159 else if (STRINGP (icon))
5160 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5161 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5162 else if (SYMBOLP (icon))
5164 LPCTSTR name;
5166 if (EQ (icon, intern ("application")))
5167 name = (LPCTSTR) IDI_APPLICATION;
5168 else if (EQ (icon, intern ("hand")))
5169 name = (LPCTSTR) IDI_HAND;
5170 else if (EQ (icon, intern ("question")))
5171 name = (LPCTSTR) IDI_QUESTION;
5172 else if (EQ (icon, intern ("exclamation")))
5173 name = (LPCTSTR) IDI_EXCLAMATION;
5174 else if (EQ (icon, intern ("asterisk")))
5175 name = (LPCTSTR) IDI_ASTERISK;
5176 else if (EQ (icon, intern ("winlogo")))
5177 name = (LPCTSTR) IDI_WINLOGO;
5178 else
5179 return 1;
5181 hicon = LoadIcon (NULL, name);
5183 else
5184 return 1;
5186 if (hicon == NULL)
5187 return 1;
5189 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5190 (LPARAM) hicon);
5192 return 0;
5194 #endif /* MAC_TODO */
5196 /************************************************************************
5197 Handling X errors
5198 ************************************************************************/
5200 /* Display Error Handling functions not used on W32. Listing them here
5201 helps diff stay in step when comparing w32term.c with xterm.c.
5203 x_error_catcher (display, error)
5204 x_catch_errors (dpy)
5205 x_catch_errors_unwind (old_val)
5206 x_check_errors (dpy, format)
5207 x_had_errors_p (dpy)
5208 x_clear_errors (dpy)
5209 x_uncatch_errors (dpy, count)
5210 x_trace_wire ()
5211 x_connection_signal (signalnum)
5212 x_connection_closed (dpy, error_message)
5213 x_error_quitter (display, error)
5214 x_error_handler (display, error)
5215 x_io_error_quitter (display)
5220 /* Changing the font of the frame. */
5222 /* Give frame F the font named FONTNAME as its default font, and
5223 return the full name of that font. FONTNAME may be a wildcard
5224 pattern; in that case, we choose some font that fits the pattern.
5225 The return value shows which font we chose. */
5227 Lisp_Object
5228 x_new_font (f, fontname)
5229 struct frame *f;
5230 register char *fontname;
5232 struct font_info *fontp
5233 = FS_LOAD_FONT (f, 0, fontname, -1);
5235 if (!fontp)
5236 return Qnil;
5238 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5239 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5240 FRAME_FONTSET (f) = -1;
5242 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5243 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5244 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5246 compute_fringe_widths (f, 1);
5248 /* Compute the scroll bar width in character columns. */
5249 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5251 int wid = FRAME_COLUMN_WIDTH (f);
5252 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5253 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5255 else
5257 int wid = FRAME_COLUMN_WIDTH (f);
5258 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5261 /* Now make the frame display the given font. */
5262 if (FRAME_MAC_WINDOW (f) != 0)
5264 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5265 FRAME_FONT (f));
5266 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5267 FRAME_FONT (f));
5268 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5269 FRAME_FONT (f));
5271 /* Don't change the size of a tip frame; there's no point in
5272 doing it because it's done in Fx_show_tip, and it leads to
5273 problems because the tip frame has no widget. */
5274 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5275 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5278 return build_string (fontp->full_name);
5281 /* Give frame F the fontset named FONTSETNAME as its default font, and
5282 return the full name of that fontset. FONTSETNAME may be a wildcard
5283 pattern; in that case, we choose some fontset that fits the pattern.
5284 The return value shows which fontset we chose. */
5286 Lisp_Object
5287 x_new_fontset (f, fontsetname)
5288 struct frame *f;
5289 char *fontsetname;
5291 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5292 Lisp_Object result;
5294 if (fontset < 0)
5295 return Qnil;
5297 if (FRAME_FONTSET (f) == fontset)
5298 /* This fontset is already set in frame F. There's nothing more
5299 to do. */
5300 return fontset_name (fontset);
5302 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5304 if (!STRINGP (result))
5305 /* Can't load ASCII font. */
5306 return Qnil;
5308 /* Since x_new_font doesn't update any fontset information, do it now. */
5309 FRAME_FONTSET (f) = fontset;
5311 return build_string (fontsetname);
5315 /***********************************************************************
5316 TODO: W32 Input Methods
5317 ***********************************************************************/
5318 /* Listing missing functions from xterm.c helps diff stay in step.
5320 xim_destroy_callback (xim, client_data, call_data)
5321 xim_open_dpy (dpyinfo, resource_name)
5322 struct xim_inst_t
5323 xim_instantiate_callback (display, client_data, call_data)
5324 xim_initialize (dpyinfo, resource_name)
5325 xim_close_dpy (dpyinfo)
5330 void
5331 mac_get_window_bounds (f, inner, outer)
5332 struct frame *f;
5333 Rect *inner, *outer;
5335 #if TARGET_API_MAC_CARBON
5336 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5337 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5338 #else /* not TARGET_API_MAC_CARBON */
5339 RgnHandle region = NewRgn ();
5341 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5342 *inner = (*region)->rgnBBox;
5343 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5344 *outer = (*region)->rgnBBox;
5345 DisposeRgn (region);
5346 #endif /* not TARGET_API_MAC_CARBON */
5351 /* Calculate the absolute position in frame F
5352 from its current recorded position values and gravity. */
5354 void
5355 x_calc_absolute_position (f)
5356 struct frame *f;
5358 int width_diff = 0, height_diff = 0;
5359 int flags = f->size_hint_flags;
5360 Rect inner, outer;
5362 /* We have nothing to do if the current position
5363 is already for the top-left corner. */
5364 if (! ((flags & XNegative) || (flags & YNegative)))
5365 return;
5367 /* Find the offsets of the outside upper-left corner of
5368 the inner window, with respect to the outer window. */
5369 mac_get_window_bounds (f, &inner, &outer);
5371 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5372 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5374 /* Treat negative positions as relative to the leftmost bottommost
5375 position that fits on the screen. */
5376 if (flags & XNegative)
5377 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5378 - width_diff
5379 - FRAME_PIXEL_WIDTH (f)
5380 + f->left_pos);
5382 if (flags & YNegative)
5383 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5384 - height_diff
5385 - FRAME_PIXEL_HEIGHT (f)
5386 + f->top_pos);
5388 /* The left_pos and top_pos
5389 are now relative to the top and left screen edges,
5390 so the flags should correspond. */
5391 f->size_hint_flags &= ~ (XNegative | YNegative);
5394 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5395 to really change the position, and 0 when calling from
5396 x_make_frame_visible (in that case, XOFF and YOFF are the current
5397 position values). It is -1 when calling from x_set_frame_parameters,
5398 which means, do adjust for borders but don't change the gravity. */
5400 void
5401 x_set_offset (f, xoff, yoff, change_gravity)
5402 struct frame *f;
5403 register int xoff, yoff;
5404 int change_gravity;
5406 if (change_gravity > 0)
5408 f->top_pos = yoff;
5409 f->left_pos = xoff;
5410 f->size_hint_flags &= ~ (XNegative | YNegative);
5411 if (xoff < 0)
5412 f->size_hint_flags |= XNegative;
5413 if (yoff < 0)
5414 f->size_hint_flags |= YNegative;
5415 f->win_gravity = NorthWestGravity;
5417 x_calc_absolute_position (f);
5419 BLOCK_INPUT;
5420 x_wm_set_size_hint (f, (long) 0, 0);
5422 #if TARGET_API_MAC_CARBON
5423 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5424 /* If the title bar is completely outside the screen, adjust the
5425 position. */
5426 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5427 kWindowConstrainMoveRegardlessOfFit
5428 | kWindowConstrainAllowPartial, NULL, NULL);
5429 x_real_positions (f, &f->left_pos, &f->top_pos);
5430 #else
5432 Rect inner, outer, screen_rect, dummy;
5433 RgnHandle region = NewRgn ();
5435 mac_get_window_bounds (f, &inner, &outer);
5436 f->x_pixels_diff = inner.left - outer.left;
5437 f->y_pixels_diff = inner.top - outer.top;
5438 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5439 f->top_pos + f->y_pixels_diff, false);
5441 /* If the title bar is completely outside the screen, adjust the
5442 position. The variable `outer' holds the title bar rectangle.
5443 The variable `inner' holds slightly smaller one than `outer',
5444 so that the calculation of overlapping may not become too
5445 strict. */
5446 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5447 outer = (*region)->rgnBBox;
5448 DisposeRgn (region);
5449 inner = outer;
5450 InsetRect (&inner, 8, 8);
5451 screen_rect = qd.screenBits.bounds;
5452 screen_rect.top += GetMBarHeight ();
5454 if (!SectRect (&inner, &screen_rect, &dummy))
5456 if (inner.right <= screen_rect.left)
5457 f->left_pos = screen_rect.left;
5458 else if (inner.left >= screen_rect.right)
5459 f->left_pos = screen_rect.right - (outer.right - outer.left);
5461 if (inner.bottom <= screen_rect.top)
5462 f->top_pos = screen_rect.top;
5463 else if (inner.top >= screen_rect.bottom)
5464 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5466 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5467 f->top_pos + f->y_pixels_diff, false);
5470 #endif
5472 UNBLOCK_INPUT;
5475 /* Call this to change the size of frame F's x-window.
5476 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5477 for this size change and subsequent size changes.
5478 Otherwise we leave the window gravity unchanged. */
5480 void
5481 x_set_window_size (f, change_gravity, cols, rows)
5482 struct frame *f;
5483 int change_gravity;
5484 int cols, rows;
5486 int pixelwidth, pixelheight;
5488 BLOCK_INPUT;
5490 check_frame_size (f, &rows, &cols);
5491 f->scroll_bar_actual_width
5492 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5494 compute_fringe_widths (f, 0);
5496 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5497 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5499 f->win_gravity = NorthWestGravity;
5500 x_wm_set_size_hint (f, (long) 0, 0);
5502 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5503 #if TARGET_API_MAC_CARBON
5504 if (f->output_data.mac->hourglass_control)
5505 MoveControl (f->output_data.mac->hourglass_control,
5506 pixelwidth - HOURGLASS_WIDTH, 0);
5507 #endif
5509 /* Now, strictly speaking, we can't be sure that this is accurate,
5510 but the window manager will get around to dealing with the size
5511 change request eventually, and we'll hear how it went when the
5512 ConfigureNotify event gets here.
5514 We could just not bother storing any of this information here,
5515 and let the ConfigureNotify event set everything up, but that
5516 might be kind of confusing to the Lisp code, since size changes
5517 wouldn't be reported in the frame parameters until some random
5518 point in the future when the ConfigureNotify event arrives.
5520 We pass 1 for DELAY since we can't run Lisp code inside of
5521 a BLOCK_INPUT. */
5522 change_frame_size (f, rows, cols, 0, 1, 0);
5523 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5524 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5526 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5527 receive in the ConfigureNotify event; if we get what we asked
5528 for, then the event won't cause the screen to become garbaged, so
5529 we have to make sure to do it here. */
5530 SET_FRAME_GARBAGED (f);
5532 XFlush (FRAME_X_DISPLAY (f));
5534 /* If cursor was outside the new size, mark it as off. */
5535 mark_window_cursors_off (XWINDOW (f->root_window));
5537 /* Clear out any recollection of where the mouse highlighting was,
5538 since it might be in a place that's outside the new frame size.
5539 Actually checking whether it is outside is a pain in the neck,
5540 so don't try--just let the highlighting be done afresh with new size. */
5541 cancel_mouse_face (f);
5543 UNBLOCK_INPUT;
5546 /* Mouse warping. */
5548 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5550 void
5551 x_set_mouse_position (f, x, y)
5552 struct frame *f;
5553 int x, y;
5555 int pix_x, pix_y;
5557 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5558 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5560 if (pix_x < 0) pix_x = 0;
5561 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5563 if (pix_y < 0) pix_y = 0;
5564 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5566 x_set_mouse_pixel_position (f, pix_x, pix_y);
5569 void
5570 x_set_mouse_pixel_position (f, pix_x, pix_y)
5571 struct frame *f;
5572 int pix_x, pix_y;
5574 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5575 BLOCK_INPUT;
5577 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5578 0, 0, 0, 0, pix_x, pix_y);
5579 UNBLOCK_INPUT;
5580 #endif
5583 /* focus shifting, raising and lowering. */
5585 void
5586 x_focus_on_frame (f)
5587 struct frame *f;
5589 #if 0 /* This proves to be unpleasant. */
5590 x_raise_frame (f);
5591 #endif
5592 #if 0
5593 /* I don't think that the ICCCM allows programs to do things like this
5594 without the interaction of the window manager. Whatever you end up
5595 doing with this code, do it to x_unfocus_frame too. */
5596 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5597 RevertToPointerRoot, CurrentTime);
5598 #endif /* ! 0 */
5601 void
5602 x_unfocus_frame (f)
5603 struct frame *f;
5607 /* Raise frame F. */
5609 void
5610 x_raise_frame (f)
5611 struct frame *f;
5613 if (f->async_visible)
5615 BLOCK_INPUT;
5616 SelectWindow (FRAME_MAC_WINDOW (f));
5617 UNBLOCK_INPUT;
5621 /* Lower frame F. */
5623 void
5624 x_lower_frame (f)
5625 struct frame *f;
5627 if (f->async_visible)
5629 BLOCK_INPUT;
5630 SendBehind (FRAME_MAC_WINDOW (f), nil);
5631 UNBLOCK_INPUT;
5635 static void
5636 XTframe_raise_lower (f, raise_flag)
5637 FRAME_PTR f;
5638 int raise_flag;
5640 if (raise_flag)
5641 x_raise_frame (f);
5642 else
5643 x_lower_frame (f);
5646 /* Change of visibility. */
5648 /* This tries to wait until the frame is really visible.
5649 However, if the window manager asks the user where to position
5650 the frame, this will return before the user finishes doing that.
5651 The frame will not actually be visible at that time,
5652 but it will become visible later when the window manager
5653 finishes with it. */
5655 void
5656 x_make_frame_visible (f)
5657 struct frame *f;
5659 Lisp_Object type;
5660 int original_top, original_left;
5662 BLOCK_INPUT;
5664 if (! FRAME_VISIBLE_P (f))
5666 /* We test FRAME_GARBAGED_P here to make sure we don't
5667 call x_set_offset a second time
5668 if we get to x_make_frame_visible a second time
5669 before the window gets really visible. */
5670 if (! FRAME_ICONIFIED_P (f)
5671 && ! f->output_data.mac->asked_for_visible)
5672 x_set_offset (f, f->left_pos, f->top_pos, 0);
5674 f->output_data.mac->asked_for_visible = 1;
5676 #if TARGET_API_MAC_CARBON
5677 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5679 struct frame *sf = SELECTED_FRAME ();
5680 if (!FRAME_MAC_P (sf))
5681 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5682 kWindowCenterOnMainScreen);
5683 else
5684 RepositionWindow (FRAME_MAC_WINDOW (f),
5685 FRAME_MAC_WINDOW (sf),
5686 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5687 kWindowCascadeStartAtParentWindowScreen
5688 #else
5689 kWindowCascadeOnParentWindowScreen
5690 #endif
5692 x_real_positions (f, &f->left_pos, &f->top_pos);
5694 #endif
5695 ShowWindow (FRAME_MAC_WINDOW (f));
5698 XFlush (FRAME_MAC_DISPLAY (f));
5700 /* Synchronize to ensure Emacs knows the frame is visible
5701 before we do anything else. We do this loop with input not blocked
5702 so that incoming events are handled. */
5704 Lisp_Object frame;
5705 int count;
5707 /* This must come after we set COUNT. */
5708 UNBLOCK_INPUT;
5710 XSETFRAME (frame, f);
5712 /* Wait until the frame is visible. Process X events until a
5713 MapNotify event has been seen, or until we think we won't get a
5714 MapNotify at all.. */
5715 for (count = input_signal_count + 10;
5716 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5718 /* Force processing of queued events. */
5719 x_sync (f);
5721 /* Machines that do polling rather than SIGIO have been
5722 observed to go into a busy-wait here. So we'll fake an
5723 alarm signal to let the handler know that there's something
5724 to be read. We used to raise a real alarm, but it seems
5725 that the handler isn't always enabled here. This is
5726 probably a bug. */
5727 if (input_polling_used ())
5729 /* It could be confusing if a real alarm arrives while
5730 processing the fake one. Turn it off and let the
5731 handler reset it. */
5732 extern void poll_for_input_1 P_ ((void));
5733 int old_poll_suppress_count = poll_suppress_count;
5734 poll_suppress_count = 1;
5735 poll_for_input_1 ();
5736 poll_suppress_count = old_poll_suppress_count;
5739 /* See if a MapNotify event has been processed. */
5740 FRAME_SAMPLE_VISIBILITY (f);
5745 /* Change from mapped state to withdrawn state. */
5747 /* Make the frame visible (mapped and not iconified). */
5749 void
5750 x_make_frame_invisible (f)
5751 struct frame *f;
5753 /* Don't keep the highlight on an invisible frame. */
5754 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5755 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5757 BLOCK_INPUT;
5759 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5760 that the current position of the window is user-specified, rather than
5761 program-specified, so that when the window is mapped again, it will be
5762 placed at the same location, without forcing the user to position it
5763 by hand again (they have already done that once for this window.) */
5764 x_wm_set_size_hint (f, (long) 0, 1);
5766 HideWindow (FRAME_MAC_WINDOW (f));
5768 /* We can't distinguish this from iconification
5769 just by the event that we get from the server.
5770 So we can't win using the usual strategy of letting
5771 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5772 and synchronize with the server to make sure we agree. */
5773 f->visible = 0;
5774 FRAME_ICONIFIED_P (f) = 0;
5775 f->async_visible = 0;
5776 f->async_iconified = 0;
5778 UNBLOCK_INPUT;
5781 /* Change window state from mapped to iconified. */
5783 void
5784 x_iconify_frame (f)
5785 struct frame *f;
5787 /* Don't keep the highlight on an invisible frame. */
5788 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5789 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5791 #if 0
5792 /* Review: Since window is still visible in dock, still allow updates? */
5793 if (f->async_iconified)
5794 return;
5795 #endif
5797 BLOCK_INPUT;
5799 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5801 UNBLOCK_INPUT;
5805 /* Free X resources of frame F. */
5807 void
5808 x_free_frame_resources (f)
5809 struct frame *f;
5811 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5812 WindowPtr wp = FRAME_MAC_WINDOW (f);
5814 BLOCK_INPUT;
5816 if (wp != tip_window)
5817 remove_window_handler (wp);
5819 DisposeWindow (wp);
5820 if (wp == tip_window)
5821 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5822 closed' event. So we reset tip_window here. */
5823 tip_window = NULL;
5825 free_frame_menubar (f);
5827 if (FRAME_FACE_CACHE (f))
5828 free_frame_faces (f);
5830 x_free_gcs (f);
5832 if (FRAME_SIZE_HINTS (f))
5833 xfree (FRAME_SIZE_HINTS (f));
5835 xfree (f->output_data.mac);
5836 f->output_data.mac = NULL;
5838 if (f == dpyinfo->x_focus_frame)
5839 dpyinfo->x_focus_frame = 0;
5840 if (f == dpyinfo->x_focus_event_frame)
5841 dpyinfo->x_focus_event_frame = 0;
5842 if (f == dpyinfo->x_highlight_frame)
5843 dpyinfo->x_highlight_frame = 0;
5845 if (f == dpyinfo->mouse_face_mouse_frame)
5847 dpyinfo->mouse_face_beg_row
5848 = dpyinfo->mouse_face_beg_col = -1;
5849 dpyinfo->mouse_face_end_row
5850 = dpyinfo->mouse_face_end_col = -1;
5851 dpyinfo->mouse_face_window = Qnil;
5852 dpyinfo->mouse_face_deferred_gc = 0;
5853 dpyinfo->mouse_face_mouse_frame = 0;
5856 UNBLOCK_INPUT;
5860 /* Destroy the X window of frame F. */
5862 void
5863 x_destroy_window (f)
5864 struct frame *f;
5866 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5868 x_free_frame_resources (f);
5870 dpyinfo->reference_count--;
5874 /* Setting window manager hints. */
5876 /* Set the normal size hints for the window manager, for frame F.
5877 FLAGS is the flags word to use--or 0 meaning preserve the flags
5878 that the window now has.
5879 If USER_POSITION is nonzero, we set the USPosition
5880 flag (this is useful when FLAGS is 0). */
5881 void
5882 x_wm_set_size_hint (f, flags, user_position)
5883 struct frame *f;
5884 long flags;
5885 int user_position;
5887 int base_width, base_height, width_inc, height_inc;
5888 int min_rows = 0, min_cols = 0;
5889 XSizeHints *size_hints;
5891 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5892 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5893 width_inc = FRAME_COLUMN_WIDTH (f);
5894 height_inc = FRAME_LINE_HEIGHT (f);
5896 check_frame_size (f, &min_rows, &min_cols);
5898 size_hints = FRAME_SIZE_HINTS (f);
5899 if (size_hints == NULL)
5901 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
5902 bzero (size_hints, sizeof (XSizeHints));
5905 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
5906 size_hints->width_inc = width_inc;
5907 size_hints->height_inc = height_inc;
5908 size_hints->min_width = base_width + min_cols * width_inc;
5909 size_hints->min_height = base_height + min_rows * height_inc;
5910 size_hints->base_width = base_width;
5911 size_hints->base_height = base_height;
5913 if (flags)
5914 size_hints->flags = flags;
5915 else if (user_position)
5917 size_hints->flags &= ~ PPosition;
5918 size_hints->flags |= USPosition;
5922 #if 0 /* MAC_TODO: hide application instead of iconify? */
5923 /* Used for IconicState or NormalState */
5925 void
5926 x_wm_set_window_state (f, state)
5927 struct frame *f;
5928 int state;
5930 #ifdef USE_X_TOOLKIT
5931 Arg al[1];
5933 XtSetArg (al[0], XtNinitialState, state);
5934 XtSetValues (f->output_data.x->widget, al, 1);
5935 #else /* not USE_X_TOOLKIT */
5936 Window window = FRAME_X_WINDOW (f);
5938 f->output_data.x->wm_hints.flags |= StateHint;
5939 f->output_data.x->wm_hints.initial_state = state;
5941 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5942 #endif /* not USE_X_TOOLKIT */
5945 void
5946 x_wm_set_icon_pixmap (f, pixmap_id)
5947 struct frame *f;
5948 int pixmap_id;
5950 Pixmap icon_pixmap;
5952 #ifndef USE_X_TOOLKIT
5953 Window window = FRAME_X_WINDOW (f);
5954 #endif
5956 if (pixmap_id > 0)
5958 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5959 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5961 else
5963 /* It seems there is no way to turn off use of an icon pixmap.
5964 The following line does it, only if no icon has yet been created,
5965 for some window managers. But with mwm it crashes.
5966 Some people say it should clear the IconPixmapHint bit in this case,
5967 but that doesn't work, and the X consortium said it isn't the
5968 right thing at all. Since there is no way to win,
5969 best to explicitly give up. */
5970 #if 0
5971 f->output_data.x->wm_hints.icon_pixmap = None;
5972 #else
5973 return;
5974 #endif
5977 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5980 Arg al[1];
5981 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5982 XtSetValues (f->output_data.x->widget, al, 1);
5985 #else /* not USE_X_TOOLKIT */
5987 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5988 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5990 #endif /* not USE_X_TOOLKIT */
5993 #endif /* MAC_TODO */
5995 void
5996 x_wm_set_icon_position (f, icon_x, icon_y)
5997 struct frame *f;
5998 int icon_x, icon_y;
6000 #if 0 /* MAC_TODO: no icons on Mac */
6001 #ifdef USE_X_TOOLKIT
6002 Window window = XtWindow (f->output_data.x->widget);
6003 #else
6004 Window window = FRAME_X_WINDOW (f);
6005 #endif
6007 f->output_data.x->wm_hints.flags |= IconPositionHint;
6008 f->output_data.x->wm_hints.icon_x = icon_x;
6009 f->output_data.x->wm_hints.icon_y = icon_y;
6011 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6012 #endif /* MAC_TODO */
6016 /***********************************************************************
6017 Fonts
6018 ***********************************************************************/
6020 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6022 struct font_info *
6023 x_get_font_info (f, font_idx)
6024 FRAME_PTR f;
6025 int font_idx;
6027 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6030 /* the global font name table */
6031 static char **font_name_table = NULL;
6032 static int font_name_table_size = 0;
6033 static int font_name_count = 0;
6035 /* Alist linking character set strings to Mac text encoding and Emacs
6036 coding system. */
6037 static Lisp_Object Vmac_charset_info_alist;
6039 static Lisp_Object
6040 create_text_encoding_info_alist ()
6042 Lisp_Object result = Qnil, rest;
6044 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6046 Lisp_Object charset_info = XCAR (rest);
6047 Lisp_Object charset, coding_system, text_encoding;
6048 Lisp_Object existing_info;
6050 if (!(CONSP (charset_info)
6051 && STRINGP (charset = XCAR (charset_info))
6052 && CONSP (XCDR (charset_info))
6053 && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
6054 && CONSP (XCDR (XCDR (charset_info)))
6055 && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
6056 continue;
6058 existing_info = assq_no_quit (text_encoding, result);
6059 if (NILP (existing_info))
6060 result = Fcons (list3 (text_encoding, coding_system, charset),
6061 result);
6062 else
6063 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6064 XSETCDR (XCDR (existing_info),
6065 Fcons (charset, XCDR (XCDR (existing_info))));
6068 return result;
6072 static void
6073 decode_mac_font_name (name, size, coding_system)
6074 char *name;
6075 int size;
6076 Lisp_Object coding_system;
6078 struct coding_system coding;
6079 char *buf, *p;
6081 for (p = name; *p; p++)
6082 if (!isascii (*p) || iscntrl (*p))
6083 break;
6085 if (*p == '\0'
6086 || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
6087 return;
6089 setup_coding_system (coding_system, &coding);
6090 coding.src_multibyte = 0;
6091 coding.dst_multibyte = 1;
6092 coding.mode |= CODING_MODE_LAST_BLOCK;
6093 coding.composing = COMPOSITION_DISABLED;
6094 buf = (char *) alloca (size);
6096 decode_coding (&coding, name, buf, strlen (name), size - 1);
6097 bcopy (buf, name, coding.produced);
6098 name[coding.produced] = '\0';
6102 static char *
6103 mac_to_x_fontname (name, size, style, charset)
6104 char *name;
6105 int size;
6106 Style style;
6107 char *charset;
6109 Str31 foundry, cs;
6110 Str255 family;
6111 char xf[256], *result, *p;
6113 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3)
6114 charset = cs;
6115 else
6117 strcpy(foundry, "Apple");
6118 strcpy(family, name);
6121 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6122 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r',
6123 size, size * 10, size ? 75 : 0, size ? 75 : 0, size * 10, charset);
6125 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1);
6126 sprintf (result, "-%s-%s-%s", foundry, family, xf);
6127 for (p = result; *p; p++)
6128 *p = tolower(*p);
6129 return result;
6133 /* Convert an X font spec to the corresponding mac font name, which
6134 can then be passed to GetFNum after conversion to a Pascal string.
6135 For ordinary Mac fonts, this should just be their names, like
6136 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6137 collection contain their charset designation in their names, like
6138 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6139 names are handled accordingly. */
6140 static void
6141 x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs)
6142 char *xf, *mf, *mf_decoded;
6143 Style *style;
6144 char *cs;
6146 Str31 foundry;
6147 Str255 family;
6148 char weight[20], slant[2], *p;
6149 Lisp_Object charset_info, coding_system = Qnil;
6150 struct coding_system coding;
6152 strcpy (mf, "");
6154 if (sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6155 foundry, family, weight, slant, cs) != 5 &&
6156 sscanf (xf, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6157 foundry, family, weight, slant, cs) != 5)
6158 return;
6160 *style = normal;
6161 if (strcmp (weight, "bold") == 0)
6162 *style |= bold;
6163 if (*slant == 'i')
6164 *style |= italic;
6166 charset_info = Fassoc (build_string (cs), Vmac_charset_info_alist);
6167 if (!NILP (charset_info))
6169 strcpy (mf_decoded, family);
6170 coding_system = Fcar (Fcdr (Fcdr (charset_info)));
6172 else
6173 sprintf (mf_decoded, "%s-%s-%s", foundry, family, cs);
6175 for (p = mf_decoded; *p; p++)
6176 if (!isascii (*p) || iscntrl (*p))
6177 break;
6179 if (*p == '\0'
6180 || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
6181 strcpy (mf, mf_decoded);
6182 else
6184 setup_coding_system (coding_system, &coding);
6185 coding.src_multibyte = 1;
6186 coding.dst_multibyte = 1;
6187 coding.mode |= CODING_MODE_LAST_BLOCK;
6188 encode_coding (&coding, mf_decoded, mf,
6189 strlen (mf_decoded), sizeof (Str255) - 1);
6190 mf[coding.produced] = '\0';
6195 static void
6196 add_font_name_table_entry (char *font_name)
6198 if (font_name_table_size == 0)
6200 font_name_table_size = 16;
6201 font_name_table = (char **)
6202 xmalloc (font_name_table_size * sizeof (char *));
6204 else if (font_name_count + 1 >= font_name_table_size)
6206 font_name_table_size += 16;
6207 font_name_table = (char **)
6208 xrealloc (font_name_table,
6209 font_name_table_size * sizeof (char *));
6212 font_name_table[font_name_count++] = font_name;
6215 /* Sets up the table font_name_table to contain the list of all fonts
6216 in the system the first time the table is used so that the Resource
6217 Manager need not be accessed every time this information is
6218 needed. */
6220 static void
6221 init_font_name_table ()
6223 #if TARGET_API_MAC_CARBON
6224 FMFontFamilyIterator ffi;
6225 FMFontFamilyInstanceIterator ffii;
6226 FMFontFamily ff;
6227 Lisp_Object text_encoding_info_alist;
6228 struct gcpro gcpro1;
6230 /* Create a dummy instance iterator here to avoid creating and
6231 destroying it in the loop. */
6232 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6233 return;
6234 /* Create an iterator to enumerate the font families. */
6235 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6236 != noErr)
6238 FMDisposeFontFamilyInstanceIterator (&ffii);
6239 return;
6242 text_encoding_info_alist = create_text_encoding_info_alist ();
6244 GCPRO1 (text_encoding_info_alist);
6246 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6248 Str255 name;
6249 FMFont font;
6250 FMFontStyle style;
6251 FMFontSize size;
6252 TextEncoding encoding;
6253 TextEncodingBase sc;
6254 Lisp_Object text_encoding_info;
6256 if (FMGetFontFamilyName (ff, name) != noErr)
6257 break;
6258 p2cstr (name);
6259 if (*name == '.')
6260 continue;
6262 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6263 break;
6264 sc = GetTextEncodingBase (encoding);
6265 text_encoding_info = assq_no_quit (make_number (sc),
6266 text_encoding_info_alist);
6267 if (!NILP (text_encoding_info))
6268 decode_mac_font_name (name, sizeof (name),
6269 XCAR (XCDR (text_encoding_info)));
6270 else
6271 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
6272 text_encoding_info_alist);
6274 /* Point the instance iterator at the current font family. */
6275 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6276 break;
6278 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6279 == noErr)
6281 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
6283 for (; !NILP (rest); rest = XCDR (rest))
6285 char *cs = SDATA (XCAR (rest));
6287 if (size == 0)
6289 add_font_name_table_entry (mac_to_x_fontname (name, size,
6290 style, cs));
6291 add_font_name_table_entry (mac_to_x_fontname (name, size,
6292 italic, cs));
6293 add_font_name_table_entry (mac_to_x_fontname (name, size,
6294 bold, cs));
6295 add_font_name_table_entry (mac_to_x_fontname (name, size,
6296 italic | bold,
6297 cs));
6299 else
6301 add_font_name_table_entry (mac_to_x_fontname (name, size,
6302 style, cs));
6308 UNGCPRO;
6310 /* Dispose of the iterators. */
6311 FMDisposeFontFamilyIterator (&ffi);
6312 FMDisposeFontFamilyInstanceIterator (&ffii);
6313 #else /* !TARGET_API_MAC_CARBON */
6314 GrafPtr port;
6315 SInt16 fontnum, old_fontnum;
6316 int num_mac_fonts = CountResources('FOND');
6317 int i, j;
6318 Handle font_handle, font_handle_2;
6319 short id, scriptcode;
6320 ResType type;
6321 Str255 name;
6322 struct FontAssoc *fat;
6323 struct AsscEntry *assc_entry;
6324 Lisp_Object text_encoding_info_alist, text_encoding_info;
6325 struct gcpro gcpro1;
6327 GetPort (&port); /* save the current font number used */
6328 old_fontnum = port->txFont;
6330 text_encoding_info_alist = create_text_encoding_info_alist ();
6332 GCPRO1 (text_encoding_info_alist);
6334 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6336 font_handle = GetIndResource ('FOND', i);
6337 if (!font_handle)
6338 continue;
6340 GetResInfo (font_handle, &id, &type, name);
6341 GetFNum (name, &fontnum);
6342 p2cstr (name);
6343 if (fontnum == 0)
6344 continue;
6346 TextFont (fontnum);
6347 scriptcode = FontToScript (fontnum);
6348 text_encoding_info = assq_no_quit (make_number (scriptcode),
6349 text_encoding_info_alist);
6350 if (!NILP (text_encoding_info))
6351 decode_mac_font_name (name, sizeof (name),
6352 XCAR (XCDR (text_encoding_info)));
6353 else
6354 text_encoding_info = assq_no_quit (make_number (smRoman),
6355 text_encoding_info_alist);
6358 HLock (font_handle);
6360 if (GetResourceSizeOnDisk (font_handle)
6361 >= sizeof (struct FamRec))
6363 fat = (struct FontAssoc *) (*font_handle
6364 + sizeof (struct FamRec));
6365 assc_entry
6366 = (struct AsscEntry *) (*font_handle
6367 + sizeof (struct FamRec)
6368 + sizeof (struct FontAssoc));
6370 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6372 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
6374 for (; !NILP (rest); rest = XCDR (rest))
6376 char *cs = SDATA (XCAR (rest));
6378 add_font_name_table_entry (mac_to_x_fontname (name,
6379 assc_entry->fontSize,
6380 assc_entry->fontStyle,
6381 cs));
6386 HUnlock (font_handle);
6387 font_handle_2 = GetNextFOND (font_handle);
6388 ReleaseResource (font_handle);
6389 font_handle = font_handle_2;
6391 while (ResError () == noErr && font_handle);
6394 UNGCPRO;
6396 TextFont (old_fontnum);
6397 #endif /* !TARGET_API_MAC_CARBON */
6401 void
6402 mac_clear_font_name_table ()
6404 int i;
6406 for (i = 0; i < font_name_count; i++)
6407 xfree (font_name_table[i]);
6408 xfree (font_name_table);
6409 font_name_table = NULL;
6410 font_name_table_size = font_name_count = 0;
6414 enum xlfd_scalable_field_index
6416 XLFD_SCL_PIXEL_SIZE,
6417 XLFD_SCL_POINT_SIZE,
6418 XLFD_SCL_AVGWIDTH,
6419 XLFD_SCL_LAST
6422 static int xlfd_scalable_fields[] =
6424 6, /* PIXEL_SIZE */
6425 7, /* POINT_SIZE */
6426 11, /* AVGWIDTH */
6430 static Lisp_Object
6431 mac_c_string_match (regexp, string, nonspecial, exact)
6432 Lisp_Object regexp;
6433 const char *string, *nonspecial;
6434 int exact;
6436 if (exact)
6438 if (strcmp (string, nonspecial) == 0)
6439 return build_string (string);
6441 else if (strstr (string, nonspecial))
6443 Lisp_Object str = build_string (string);
6445 if (fast_string_match (regexp, str) >= 0)
6446 return str;
6449 return Qnil;
6452 static Lisp_Object
6453 mac_do_list_fonts (pattern, maxnames)
6454 char *pattern;
6455 int maxnames;
6457 int i, n_fonts = 0;
6458 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6459 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6460 char *scaled, *ptr;
6461 int scl_val[XLFD_SCL_LAST], *field, *val;
6462 char *longest_start, *cur_start, *nonspecial;
6463 int longest_len, exact;
6465 if (font_name_table == NULL) /* Initialize when first used. */
6466 init_font_name_table ();
6468 for (i = 0; i < XLFD_SCL_LAST; i++)
6469 scl_val[i] = -1;
6471 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6472 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6473 fonts are scaled according to the specified size. */
6474 ptr = pattern;
6475 i = 0;
6476 field = xlfd_scalable_fields;
6477 val = scl_val;
6478 if (*ptr == '-')
6481 ptr++;
6482 if (i == *field)
6484 if ('0' <= *ptr && *ptr <= '9')
6486 *val = *ptr++ - '0';
6487 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6488 *val = *val * 10 + *ptr++ - '0';
6489 if (*ptr != '-')
6490 *val = -1;
6492 field++;
6493 val++;
6495 ptr = strchr (ptr, '-');
6496 i++;
6498 while (ptr && i < 14);
6500 if (i == 14 && ptr == NULL)
6502 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
6503 scl_val[XLFD_SCL_PIXEL_SIZE] =
6504 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
6505 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
6506 : -1));
6507 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
6508 scl_val[XLFD_SCL_POINT_SIZE] =
6509 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
6510 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
6511 : -1));
6512 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
6513 scl_val[XLFD_SCL_AVGWIDTH] =
6514 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
6515 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
6516 : -1));
6518 else
6519 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6521 ptr = regex;
6522 *ptr++ = '^';
6524 longest_start = cur_start = ptr;
6525 longest_len = 0;
6526 exact = 1;
6528 /* Turn pattern into a regexp and do a regexp match. Also find the
6529 longest substring containing no special characters. */
6530 for (; *pattern; pattern++)
6532 if (*pattern == '?' || *pattern == '*')
6534 if (ptr - cur_start > longest_len)
6536 longest_start = cur_start;
6537 longest_len = ptr - cur_start;
6539 exact = 0;
6541 if (*pattern == '?')
6542 *ptr++ = '.';
6543 else /* if (*pattern == '*') */
6545 *ptr++ = '.';
6546 *ptr++ = '*';
6548 cur_start = ptr;
6550 else
6551 *ptr++ = tolower (*pattern);
6554 if (ptr - cur_start > longest_len)
6556 longest_start = cur_start;
6557 longest_len = ptr - cur_start;
6560 *ptr = '$';
6561 *(ptr + 1) = '\0';
6563 nonspecial = xmalloc (longest_len + 1);
6564 strncpy (nonspecial, longest_start, longest_len);
6565 nonspecial[longest_len] = '\0';
6567 pattern_regex = build_string (regex);
6569 for (i = 0; i < font_name_count; i++)
6571 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6572 nonspecial, exact);
6573 if (!NILP (fontname))
6575 font_list = Fcons (fontname, font_list);
6576 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6577 break;
6579 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6580 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
6582 int former_len = ptr - font_name_table[i];
6584 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1);
6585 memcpy (scaled, font_name_table[i], former_len);
6586 sprintf (scaled + former_len,
6587 "-%d-%d-75-75-m-%d-%s",
6588 scl_val[XLFD_SCL_PIXEL_SIZE],
6589 scl_val[XLFD_SCL_POINT_SIZE],
6590 scl_val[XLFD_SCL_AVGWIDTH],
6591 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
6592 fontname = mac_c_string_match (pattern_regex, scaled,
6593 nonspecial, exact);
6594 xfree (scaled);
6595 if (!NILP (fontname))
6597 font_list = Fcons (fontname, font_list);
6598 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6599 break;
6604 xfree (nonspecial);
6606 return font_list;
6609 /* Return a list of names of available fonts matching PATTERN on frame F.
6611 Frame F null means we have not yet created any frame on Mac, and
6612 consult the first display in x_display_list. MAXNAMES sets a limit
6613 on how many fonts to match. */
6615 Lisp_Object
6616 x_list_fonts (f, pattern, size, maxnames)
6617 struct frame *f;
6618 Lisp_Object pattern;
6619 int size, maxnames;
6621 Lisp_Object list = Qnil, patterns, tem, key;
6622 struct mac_display_info *dpyinfo
6623 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
6625 xassert (size <= 0);
6627 patterns = Fassoc (pattern, Valternate_fontname_alist);
6628 if (NILP (patterns))
6629 patterns = Fcons (pattern, Qnil);
6631 for (; CONSP (patterns); patterns = XCDR (patterns))
6633 pattern = XCAR (patterns);
6635 if (!STRINGP (pattern))
6636 continue;
6638 tem = XCAR (XCDR (dpyinfo->name_list_element));
6639 key = Fcons (pattern, make_number (maxnames));
6641 list = Fassoc (key, tem);
6642 if (!NILP (list))
6644 list = Fcdr_safe (list);
6645 /* We have a cashed list. Don't have to get the list again. */
6646 goto label_cached;
6649 BLOCK_INPUT;
6650 list = mac_do_list_fonts (SDATA (pattern), maxnames);
6651 UNBLOCK_INPUT;
6653 /* MAC_TODO: add code for matching outline fonts here */
6655 /* Now store the result in the cache. */
6656 XSETCAR (XCDR (dpyinfo->name_list_element),
6657 Fcons (Fcons (key, list),
6658 XCAR (XCDR (dpyinfo->name_list_element))));
6660 label_cached:
6661 if (NILP (list)) continue; /* Try the remaining alternatives. */
6664 return list;
6668 #if GLYPH_DEBUG
6670 /* Check that FONT is valid on frame F. It is if it can be found in F's
6671 font table. */
6673 static void
6674 x_check_font (f, font)
6675 struct frame *f;
6676 XFontStruct *font;
6678 int i;
6679 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6681 xassert (font != NULL);
6683 for (i = 0; i < dpyinfo->n_fonts; i++)
6684 if (dpyinfo->font_table[i].name
6685 && font == dpyinfo->font_table[i].font)
6686 break;
6688 xassert (i < dpyinfo->n_fonts);
6691 #endif /* GLYPH_DEBUG != 0 */
6693 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6694 Note: There are (broken) X fonts out there with invalid XFontStruct
6695 min_bounds contents. For example, handa@etl.go.jp reports that
6696 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6697 have font->min_bounds.width == 0. */
6699 static INLINE void
6700 x_font_min_bounds (font, w, h)
6701 MacFontStruct *font;
6702 int *w, *h;
6704 *h = FONT_HEIGHT (font);
6705 *w = font->min_bounds.width;
6709 /* Compute the smallest character width and smallest font height over
6710 all fonts available on frame F. Set the members smallest_char_width
6711 and smallest_font_height in F's x_display_info structure to
6712 the values computed. Value is non-zero if smallest_font_height or
6713 smallest_char_width become smaller than they were before. */
6715 static int
6716 x_compute_min_glyph_bounds (f)
6717 struct frame *f;
6719 int i;
6720 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6721 MacFontStruct *font;
6722 int old_width = dpyinfo->smallest_char_width;
6723 int old_height = dpyinfo->smallest_font_height;
6725 dpyinfo->smallest_font_height = 100000;
6726 dpyinfo->smallest_char_width = 100000;
6728 for (i = 0; i < dpyinfo->n_fonts; ++i)
6729 if (dpyinfo->font_table[i].name)
6731 struct font_info *fontp = dpyinfo->font_table + i;
6732 int w, h;
6734 font = (MacFontStruct *) fontp->font;
6735 xassert (font != (MacFontStruct *) ~0);
6736 x_font_min_bounds (font, &w, &h);
6738 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6739 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6742 xassert (dpyinfo->smallest_char_width > 0
6743 && dpyinfo->smallest_font_height > 0);
6745 return (dpyinfo->n_fonts == 1
6746 || dpyinfo->smallest_char_width < old_width
6747 || dpyinfo->smallest_font_height < old_height);
6751 /* Determine whether given string is a fully-specified XLFD: all 14
6752 fields are present, none is '*'. */
6754 static int
6755 is_fully_specified_xlfd (char *p)
6757 int i;
6758 char *q;
6760 if (*p != '-')
6761 return 0;
6763 for (i = 0; i < 13; i++)
6765 q = strchr (p + 1, '-');
6766 if (q == NULL)
6767 return 0;
6768 if (q - p == 2 && *(p + 1) == '*')
6769 return 0;
6770 p = q;
6773 if (strchr (p + 1, '-') != NULL)
6774 return 0;
6776 if (*(p + 1) == '*' && *(p + 2) == '\0')
6777 return 0;
6779 return 1;
6783 const int kDefaultFontSize = 12;
6786 /* XLoadQueryFont creates and returns an internal representation for a
6787 font in a MacFontStruct struct. There is really no concept
6788 corresponding to "loading" a font on the Mac. But we check its
6789 existence and find the font number and all other information for it
6790 and store them in the returned MacFontStruct. */
6792 static MacFontStruct *
6793 XLoadQueryFont (Display *dpy, char *fontname)
6795 int i, size, point_size, avgwidth, is_two_byte_font, char_width;
6796 char *name;
6797 GrafPtr port;
6798 SInt16 old_fontnum, old_fontsize;
6799 Style old_fontface;
6800 Str255 mfontname, mfontname_decoded;
6801 Str31 charset;
6802 SInt16 fontnum;
6803 Style fontface;
6804 #if TARGET_API_MAC_CARBON
6805 TextEncoding encoding;
6806 int scriptcode;
6807 #else
6808 short scriptcode;
6809 #endif
6810 MacFontStruct *font;
6811 FontInfo the_fontinfo;
6812 #ifdef MAC_OSX
6813 UInt32 old_flags, new_flags;
6814 #endif
6816 if (is_fully_specified_xlfd (fontname))
6817 name = fontname;
6818 else
6820 Lisp_Object matched_fonts;
6822 matched_fonts = mac_do_list_fonts (fontname, 1);
6823 if (NILP (matched_fonts))
6824 return NULL;
6825 name = SDATA (XCAR (matched_fonts));
6828 GetPort (&port); /* save the current font number used */
6829 #if TARGET_API_MAC_CARBON
6830 old_fontnum = GetPortTextFont (port);
6831 old_fontsize = GetPortTextSize (port);
6832 old_fontface = GetPortTextFace (port);
6833 #else
6834 old_fontnum = port->txFont;
6835 old_fontsize = port->txSize;
6836 old_fontface = port->txFace;
6837 #endif
6839 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size, &point_size, &avgwidth) != 3)
6840 size = 0;
6841 else
6843 if (size == 0)
6844 if (point_size > 0)
6845 size = point_size / 10;
6846 else if (avgwidth > 0)
6847 size = avgwidth / 10;
6849 if (size == 0)
6850 size = kDefaultFontSize;
6852 x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded,
6853 &fontface, charset);
6854 c2pstr (mfontname);
6855 #if TARGET_API_MAC_CARBON
6856 fontnum = FMGetFontFamilyFromName (mfontname);
6857 if (fontnum == kInvalidFontFamily
6858 || FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
6859 return NULL;
6860 scriptcode = GetTextEncodingBase (encoding);
6861 #else
6862 GetFNum (mfontname, &fontnum);
6863 if (fontnum == 0)
6864 return NULL;
6865 scriptcode = FontToScript (fontnum);
6866 #endif
6868 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6870 font->mac_fontnum = fontnum;
6871 font->mac_fontsize = size;
6872 font->mac_fontface = fontface;
6873 font->mac_scriptcode = scriptcode;
6875 /* Apple Japanese (SJIS) font is listed as both
6876 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6877 (Roman script) in init_font_name_table (). The latter should be
6878 treated as a one-byte font. */
6879 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
6880 font->mac_scriptcode = smRoman;
6882 font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset);
6884 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6885 font->mac_scriptcode == smTradChinese ||
6886 font->mac_scriptcode == smSimpChinese ||
6887 font->mac_scriptcode == smKorean;
6889 TextFont (fontnum);
6890 TextSize (size);
6891 TextFace (fontface);
6893 GetFontInfo (&the_fontinfo);
6895 font->ascent = the_fontinfo.ascent;
6896 font->descent = the_fontinfo.descent;
6898 font->min_byte1 = 0;
6899 if (is_two_byte_font)
6900 font->max_byte1 = 1;
6901 else
6902 font->max_byte1 = 0;
6903 font->min_char_or_byte2 = 0x20;
6904 font->max_char_or_byte2 = 0xff;
6906 if (is_two_byte_font)
6908 /* Use the width of an "ideographic space" of that font because
6909 the_fontinfo.widMax returns the wrong width for some fonts. */
6910 switch (font->mac_scriptcode)
6912 case smJapanese:
6913 char_width = StringWidth("\p\x81\x40");
6914 break;
6915 case smTradChinese:
6916 char_width = StringWidth("\p\xa1\x40");
6917 break;
6918 case smSimpChinese:
6919 char_width = StringWidth("\p\xa1\xa1");
6920 break;
6921 case smKorean:
6922 char_width = StringWidth("\p\xa1\xa1");
6923 break;
6926 else
6927 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6928 returns 15 for 12-point Monaco! */
6929 char_width = CharWidth ('m');
6931 if (is_two_byte_font)
6933 font->per_char = NULL;
6935 if (fontface & italic)
6936 font->max_bounds.rbearing = char_width + 1;
6937 else
6938 font->max_bounds.rbearing = char_width;
6939 font->max_bounds.lbearing = 0;
6940 font->max_bounds.width = char_width;
6941 font->max_bounds.ascent = the_fontinfo.ascent;
6942 font->max_bounds.descent = the_fontinfo.descent;
6944 font->min_bounds = font->max_bounds;
6946 else
6948 font->per_char = (XCharStruct *)
6949 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6951 int c, min_width, max_width;
6952 Rect char_bounds, min_bounds, max_bounds;
6953 char ch;
6955 min_width = max_width = char_width;
6956 SetRect (&min_bounds, -32767, -32767, 32767, 32767);
6957 SetRect (&max_bounds, 0, 0, 0, 0);
6958 for (c = 0x20; c <= 0xff; c++)
6960 ch = c;
6961 char_width = CharWidth (ch);
6962 QDTextBounds (1, &ch, &char_bounds);
6963 STORE_XCHARSTRUCT (font->per_char[c - 0x20],
6964 char_width, char_bounds);
6965 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6966 character width of 0x7f. */
6967 if (char_width > 0)
6969 min_width = min (min_width, char_width);
6970 max_width = max (max_width, char_width);
6972 if (!EmptyRect (&char_bounds))
6974 SetRect (&min_bounds,
6975 max (min_bounds.left, char_bounds.left),
6976 max (min_bounds.top, char_bounds.top),
6977 min (min_bounds.right, char_bounds.right),
6978 min (min_bounds.bottom, char_bounds.bottom));
6979 UnionRect (&max_bounds, &char_bounds, &max_bounds);
6982 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
6983 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
6984 if (min_width == max_width
6985 && max_bounds.left >= 0 && max_bounds.right <= max_width)
6987 /* Fixed width and no overhangs. */
6988 xfree (font->per_char);
6989 font->per_char = NULL;
6994 TextFont (old_fontnum); /* restore previous font number, size and face */
6995 TextSize (old_fontsize);
6996 TextFace (old_fontface);
6998 return font;
7002 void
7003 mac_unload_font (dpyinfo, font)
7004 struct mac_display_info *dpyinfo;
7005 XFontStruct *font;
7007 xfree (font->full_name);
7008 if (font->per_char)
7009 xfree (font->per_char);
7010 xfree (font);
7014 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7015 pointer to the structure font_info while allocating it dynamically.
7016 If SIZE is 0, load any size of font.
7017 If loading is failed, return NULL. */
7019 struct font_info *
7020 x_load_font (f, fontname, size)
7021 struct frame *f;
7022 register char *fontname;
7023 int size;
7025 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7026 Lisp_Object font_names;
7028 /* Get a list of all the fonts that match this name. Once we
7029 have a list of matching fonts, we compare them against the fonts
7030 we already have by comparing names. */
7031 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7033 if (!NILP (font_names))
7035 Lisp_Object tail;
7036 int i;
7038 for (i = 0; i < dpyinfo->n_fonts; i++)
7039 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7040 if (dpyinfo->font_table[i].name
7041 && (!strcmp (dpyinfo->font_table[i].name,
7042 SDATA (XCAR (tail)))
7043 || !strcmp (dpyinfo->font_table[i].full_name,
7044 SDATA (XCAR (tail)))))
7045 return (dpyinfo->font_table + i);
7047 else
7048 return NULL;
7050 /* Load the font and add it to the table. */
7052 char *full_name;
7053 struct MacFontStruct *font;
7054 struct font_info *fontp;
7055 unsigned long value;
7056 int i;
7058 fontname = (char *) SDATA (XCAR (font_names));
7060 BLOCK_INPUT;
7061 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
7062 UNBLOCK_INPUT;
7063 if (!font)
7064 return NULL;
7066 /* Find a free slot in the font table. */
7067 for (i = 0; i < dpyinfo->n_fonts; ++i)
7068 if (dpyinfo->font_table[i].name == NULL)
7069 break;
7071 /* If no free slot found, maybe enlarge the font table. */
7072 if (i == dpyinfo->n_fonts
7073 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7075 int sz;
7076 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7077 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
7078 dpyinfo->font_table
7079 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
7082 fontp = dpyinfo->font_table + i;
7083 if (i == dpyinfo->n_fonts)
7084 ++dpyinfo->n_fonts;
7086 /* Now fill in the slots of *FONTP. */
7087 BLOCK_INPUT;
7088 bzero (fontp, sizeof (*fontp));
7089 fontp->font = font;
7090 fontp->font_idx = i;
7091 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
7092 bcopy (fontname, fontp->name, strlen (fontname) + 1);
7094 if (font->min_bounds.width == font->max_bounds.width)
7096 /* Fixed width font. */
7097 fontp->average_width = fontp->space_width = font->min_bounds.width;
7099 else
7101 XChar2b char2b;
7102 XCharStruct *pcm;
7104 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
7105 pcm = mac_per_char_metric (font, &char2b, 0);
7106 if (pcm)
7107 fontp->space_width = pcm->width;
7108 else
7109 fontp->space_width = FONT_WIDTH (font);
7111 if (pcm)
7113 int width = pcm->width;
7114 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
7115 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
7116 width += pcm->width;
7117 fontp->average_width = width / 95;
7119 else
7120 fontp->average_width = FONT_WIDTH (font);
7123 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
7124 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
7126 fontp->size = font->max_bounds.width;
7127 fontp->height = FONT_HEIGHT (font);
7129 /* For some font, ascent and descent in max_bounds field is
7130 larger than the above value. */
7131 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
7132 if (max_height > fontp->height)
7133 fontp->height = max_height;
7136 /* The slot `encoding' specifies how to map a character
7137 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7138 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7139 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7140 2:0xA020..0xFF7F). For the moment, we don't know which charset
7141 uses this font. So, we set information in fontp->encoding[1]
7142 which is never used by any charset. If mapping can't be
7143 decided, set FONT_ENCODING_NOT_DECIDED. */
7144 if (font->mac_scriptcode == smJapanese)
7145 fontp->encoding[1] = 4;
7146 else
7148 fontp->encoding[1]
7149 = (font->max_byte1 == 0
7150 /* 1-byte font */
7151 ? (font->min_char_or_byte2 < 0x80
7152 ? (font->max_char_or_byte2 < 0x80
7153 ? 0 /* 0x20..0x7F */
7154 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
7155 : 1) /* 0xA0..0xFF */
7156 /* 2-byte font */
7157 : (font->min_byte1 < 0x80
7158 ? (font->max_byte1 < 0x80
7159 ? (font->min_char_or_byte2 < 0x80
7160 ? (font->max_char_or_byte2 < 0x80
7161 ? 0 /* 0x2020..0x7F7F */
7162 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
7163 : 3) /* 0x20A0..0x7FFF */
7164 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
7165 : (font->min_char_or_byte2 < 0x80
7166 ? (font->max_char_or_byte2 < 0x80
7167 ? 2 /* 0xA020..0xFF7F */
7168 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
7169 : 1))); /* 0xA0A0..0xFFFF */
7172 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7173 fontp->baseline_offset
7174 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
7175 ? (long) value : 0);
7176 fontp->relative_compose
7177 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
7178 ? (long) value : 0);
7179 fontp->default_ascent
7180 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
7181 ? (long) value : 0);
7182 #else
7183 fontp->baseline_offset = 0;
7184 fontp->relative_compose = 0;
7185 fontp->default_ascent = 0;
7186 #endif
7188 /* Set global flag fonts_changed_p to non-zero if the font loaded
7189 has a character with a smaller width than any other character
7190 before, or if the font loaded has a smalle>r height than any
7191 other font loaded before. If this happens, it will make a
7192 glyph matrix reallocation necessary. */
7193 fonts_changed_p |= x_compute_min_glyph_bounds (f);
7194 UNBLOCK_INPUT;
7195 return fontp;
7200 /* Return a pointer to struct font_info of a font named FONTNAME for
7201 frame F. If no such font is loaded, return NULL. */
7203 struct font_info *
7204 x_query_font (f, fontname)
7205 struct frame *f;
7206 register char *fontname;
7208 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7209 int i;
7211 for (i = 0; i < dpyinfo->n_fonts; i++)
7212 if (dpyinfo->font_table[i].name
7213 && (!strcmp (dpyinfo->font_table[i].name, fontname)
7214 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
7215 return (dpyinfo->font_table + i);
7216 return NULL;
7220 /* Find a CCL program for a font specified by FONTP, and set the member
7221 `encoder' of the structure. */
7223 void
7224 x_find_ccl_program (fontp)
7225 struct font_info *fontp;
7227 Lisp_Object list, elt;
7229 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7231 elt = XCAR (list);
7232 if (CONSP (elt)
7233 && STRINGP (XCAR (elt))
7234 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7235 >= 0))
7236 break;
7238 if (! NILP (list))
7240 struct ccl_program *ccl
7241 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7243 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7244 xfree (ccl);
7245 else
7246 fontp->font_encoder = ccl;
7252 /* The Mac Event loop code */
7254 #if !TARGET_API_MAC_CARBON
7255 #include <Events.h>
7256 #include <Quickdraw.h>
7257 #include <Balloons.h>
7258 #include <Devices.h>
7259 #include <Fonts.h>
7260 #include <Gestalt.h>
7261 #include <Menus.h>
7262 #include <Processes.h>
7263 #include <Sound.h>
7264 #include <ToolUtils.h>
7265 #include <TextUtils.h>
7266 #include <Dialogs.h>
7267 #include <Script.h>
7268 #include <Types.h>
7269 #include <Resources.h>
7271 #if __MWERKS__
7272 #include <unix.h>
7273 #endif
7274 #endif /* ! TARGET_API_MAC_CARBON */
7276 #define M_APPLE 128
7277 #define I_ABOUT 1
7279 #define WINDOW_RESOURCE 128
7280 #define TERM_WINDOW_RESOURCE 129
7282 #define DEFAULT_NUM_COLS 80
7284 #define MIN_DOC_SIZE 64
7285 #define MAX_DOC_SIZE 32767
7287 #define EXTRA_STACK_ALLOC (256 * 1024)
7289 #define ARGV_STRING_LIST_ID 129
7290 #define ABOUT_ALERT_ID 128
7291 #define RAM_TOO_LARGE_ALERT_ID 129
7293 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7294 Lisp_Object Qreverse;
7296 /* True if using command key as meta key. */
7297 Lisp_Object Vmac_command_key_is_meta;
7299 /* Modifier associated with the option key, or nil for normal behavior. */
7300 Lisp_Object Vmac_option_modifier;
7302 /* True if the ctrl and meta keys should be reversed. */
7303 Lisp_Object Vmac_reverse_ctrl_meta;
7305 /* True if the option and command modifiers should be used to emulate
7306 a three button mouse */
7307 Lisp_Object Vmac_emulate_three_button_mouse;
7309 #if USE_CARBON_EVENTS
7310 /* True if the mouse wheel button (i.e. button 4) should map to
7311 mouse-2, instead of mouse-3. */
7312 Lisp_Object Vmac_wheel_button_is_mouse_2;
7314 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7315 for processing before Emacs sees it. */
7316 Lisp_Object Vmac_pass_command_to_system;
7318 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7319 for processing before Emacs sees it. */
7320 Lisp_Object Vmac_pass_control_to_system;
7322 /* Points to the variable `inev' in the function XTread_socket. It is
7323 used for passing an input event to the function back from
7324 Carbon/Apple event handlers. */
7325 static struct input_event *read_socket_inev = NULL;
7326 #endif
7328 /* Set in term/mac-win.el to indicate that event loop can now generate
7329 drag and drop events. */
7330 Lisp_Object Qmac_ready_for_drag_n_drop;
7332 Point saved_menu_event_location;
7334 /* Apple Events */
7335 static void init_required_apple_events (void);
7336 static pascal OSErr
7337 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7338 static pascal OSErr
7339 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7340 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7341 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7343 #if TARGET_API_MAC_CARBON
7344 /* Drag and Drop */
7345 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
7346 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7347 static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
7348 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
7349 #endif
7351 static Lisp_Object Qapplication, Qabout;
7352 #if USE_CARBON_EVENTS
7353 #ifdef MAC_OSX
7354 extern void init_service_handler ();
7355 static Lisp_Object Qpreferences, Qservices, Qpaste, Qperform;
7356 #endif
7357 /* Window Event Handler */
7358 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7359 EventRef, void *);
7360 #endif
7361 OSErr install_window_handler (WindowPtr);
7363 extern void init_emacs_passwd_dir ();
7364 extern int emacs_main (int, char **, char **);
7366 extern void initialize_applescript();
7367 extern void terminate_applescript();
7369 static unsigned int
7370 #if USE_CARBON_EVENTS
7371 mac_to_emacs_modifiers (UInt32 mods)
7372 #else
7373 mac_to_emacs_modifiers (EventModifiers mods)
7374 #endif
7376 unsigned int result = 0;
7377 if (mods & macShiftKey)
7378 result |= shift_modifier;
7379 if (mods & macCtrlKey)
7380 result |= ctrl_modifier;
7381 if (mods & macMetaKey)
7382 result |= meta_modifier;
7383 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7384 result |= alt_modifier;
7385 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7386 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7387 if (!NILP(val))
7388 result |= XUINT(val);
7391 return result;
7394 static int
7395 mac_get_emulated_btn ( UInt32 modifiers )
7397 int result = 0;
7398 if (!NILP (Vmac_emulate_three_button_mouse)) {
7399 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7400 if (modifiers & cmdKey)
7401 result = cmdIs3 ? 2 : 1;
7402 else if (modifiers & optionKey)
7403 result = cmdIs3 ? 1 : 2;
7405 return result;
7408 #if USE_CARBON_EVENTS
7409 /* Obtains the event modifiers from the event ref and then calls
7410 mac_to_emacs_modifiers. */
7411 static int
7412 mac_event_to_emacs_modifiers (EventRef eventRef)
7414 UInt32 mods = 0;
7415 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7416 sizeof (UInt32), NULL, &mods);
7417 if (!NILP (Vmac_emulate_three_button_mouse) &&
7418 GetEventClass(eventRef) == kEventClassMouse)
7420 mods &= ~(optionKey | cmdKey);
7422 return mac_to_emacs_modifiers (mods);
7425 /* Given an event ref, return the code to use for the mouse button
7426 code in the emacs input_event. */
7427 static int
7428 mac_get_mouse_btn (EventRef ref)
7430 EventMouseButton result = kEventMouseButtonPrimary;
7431 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7432 sizeof (EventMouseButton), NULL, &result);
7433 switch (result)
7435 case kEventMouseButtonPrimary:
7436 if (NILP (Vmac_emulate_three_button_mouse))
7437 return 0;
7438 else {
7439 UInt32 mods = 0;
7440 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7441 sizeof (UInt32), NULL, &mods);
7442 return mac_get_emulated_btn(mods);
7444 case kEventMouseButtonSecondary:
7445 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7446 case kEventMouseButtonTertiary:
7447 case 4: /* 4 is the number for the mouse wheel button */
7448 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7449 default:
7450 return 0;
7454 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7455 events. However the click of the mouse wheel is not converted to a
7456 mouseDown or mouseUp event. Likewise for dead key down events.
7457 This calls ConvertEventRef, but then checks to see if it is a mouse
7458 up/down, or a dead key down carbon event that has not been
7459 converted, and if so, converts it by hand (to be picked up in the
7460 XTread_socket loop). */
7461 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7463 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7465 if (result)
7466 return result;
7468 switch (GetEventClass (eventRef))
7470 case kEventClassMouse:
7471 switch (GetEventKind (eventRef))
7473 case kEventMouseDown:
7474 eventRec->what = mouseDown;
7475 result = 1;
7476 break;
7478 case kEventMouseUp:
7479 eventRec->what = mouseUp;
7480 result = 1;
7481 break;
7483 default:
7484 break;
7486 break;
7488 case kEventClassKeyboard:
7489 switch (GetEventKind (eventRef))
7491 case kEventRawKeyDown:
7493 unsigned char char_codes;
7494 UInt32 key_code;
7496 eventRec->what = keyDown;
7497 GetEventParameter (eventRef, kEventParamKeyMacCharCodes, typeChar,
7498 NULL, sizeof (char), NULL, &char_codes);
7499 GetEventParameter (eventRef, kEventParamKeyCode, typeUInt32,
7500 NULL, sizeof (UInt32), NULL, &key_code);
7501 eventRec->message = char_codes | ((key_code & 0xff) << 8);
7502 result = 1;
7504 break;
7506 default:
7507 break;
7509 break;
7511 default:
7512 break;
7515 if (result)
7517 /* Need where and when. */
7518 UInt32 mods;
7520 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint,
7521 NULL, sizeof (Point), NULL, &eventRec->where);
7522 /* Use two step process because new event modifiers are 32-bit
7523 and old are 16-bit. Currently, only loss is NumLock & Fn. */
7524 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32,
7525 NULL, sizeof (UInt32), NULL, &mods);
7526 eventRec->modifiers = mods;
7528 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7531 return result;
7534 #endif
7536 static void
7537 do_get_menus (void)
7539 Handle menubar_handle;
7540 MenuHandle menu_handle;
7542 menubar_handle = GetNewMBar (128);
7543 if(menubar_handle == NULL)
7544 abort ();
7545 SetMenuBar (menubar_handle);
7546 DrawMenuBar ();
7548 #if !TARGET_API_MAC_CARBON
7549 menu_handle = GetMenuHandle (M_APPLE);
7550 if(menu_handle != NULL)
7551 AppendResMenu (menu_handle,'DRVR');
7552 else
7553 abort ();
7554 #endif
7558 static void
7559 do_init_managers (void)
7561 #if !TARGET_API_MAC_CARBON
7562 InitGraf (&qd.thePort);
7563 InitFonts ();
7564 FlushEvents (everyEvent, 0);
7565 InitWindows ();
7566 InitMenus ();
7567 TEInit ();
7568 InitDialogs (NULL);
7569 #endif /* !TARGET_API_MAC_CARBON */
7570 InitCursor ();
7572 #if !TARGET_API_MAC_CARBON
7573 /* set up some extra stack space for use by emacs */
7574 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7576 /* MaxApplZone must be called for AppleScript to execute more
7577 complicated scripts */
7578 MaxApplZone ();
7579 MoreMasters ();
7580 #endif /* !TARGET_API_MAC_CARBON */
7583 static void
7584 do_check_ram_size (void)
7586 SInt32 physical_ram_size, logical_ram_size;
7588 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7589 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7590 || physical_ram_size > (1 << VALBITS)
7591 || logical_ram_size > (1 << VALBITS))
7593 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7594 exit (1);
7598 static void
7599 do_window_update (WindowPtr win)
7601 struct frame *f = mac_window_to_frame (win);
7603 BeginUpdate (win);
7605 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7606 below. */
7607 if (win != tip_window)
7609 if (f->async_visible == 0)
7611 f->async_visible = 1;
7612 f->async_iconified = 0;
7613 SET_FRAME_GARBAGED (f);
7615 /* An update event is equivalent to MapNotify on X, so report
7616 visibility changes properly. */
7617 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7618 /* Force a redisplay sooner or later to update the
7619 frame titles in case this is the second frame. */
7620 record_asynch_buffer_change ();
7622 else
7624 Rect r;
7626 #if TARGET_API_MAC_CARBON
7628 RgnHandle region = NewRgn ();
7630 GetPortVisibleRegion (GetWindowPort (win), region);
7631 GetRegionBounds (region, &r);
7632 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7633 UpdateControls (win, region);
7634 DisposeRgn (region);
7636 #else
7637 r = (*win->visRgn)->rgnBBox;
7638 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7639 UpdateControls (win, win->visRgn);
7640 #endif
7644 EndUpdate (win);
7647 static int
7648 is_emacs_window (WindowPtr win)
7650 Lisp_Object tail, frame;
7652 if (!win)
7653 return 0;
7655 FOR_EACH_FRAME (tail, frame)
7656 if (FRAME_MAC_P (XFRAME (frame)))
7657 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7658 return 1;
7660 return 0;
7663 static void
7664 do_app_resume ()
7666 /* Window-activate events will do the job. */
7669 static void
7670 do_app_suspend ()
7672 /* Window-deactivate events will do the job. */
7676 static void
7677 do_apple_menu (SInt16 menu_item)
7679 #if !TARGET_API_MAC_CARBON
7680 Str255 item_name;
7681 SInt16 da_driver_refnum;
7683 if (menu_item == I_ABOUT)
7684 NoteAlert (ABOUT_ALERT_ID, NULL);
7685 else
7687 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7688 da_driver_refnum = OpenDeskAcc (item_name);
7690 #endif /* !TARGET_API_MAC_CARBON */
7693 void
7694 do_menu_choice (SInt32 menu_choice)
7696 SInt16 menu_id, menu_item;
7698 menu_id = HiWord (menu_choice);
7699 menu_item = LoWord (menu_choice);
7701 switch (menu_id)
7703 case 0:
7704 break;
7706 case M_APPLE:
7707 do_apple_menu (menu_item);
7708 break;
7710 default:
7712 struct frame *f = mac_focus_frame (&one_mac_display_info);
7713 MenuHandle menu = GetMenuHandle (menu_id);
7714 if (menu)
7716 UInt32 refcon;
7718 GetMenuItemRefCon (menu, menu_item, &refcon);
7719 menubar_selection_callback (f, refcon);
7724 HiliteMenu (0);
7728 /* Handle drags in size box. Based on code contributed by Ben
7729 Mesander and IM - Window Manager A. */
7731 static void
7732 do_grow_window (WindowPtr w, EventRecord *e)
7734 Rect limit_rect;
7735 int rows, columns, width, height;
7736 struct frame *f = mac_window_to_frame (w);
7737 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7738 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7739 #if TARGET_API_MAC_CARBON
7740 Rect new_rect;
7741 #else
7742 long grow_size;
7743 #endif
7745 if (size_hints->flags & PMinSize)
7747 min_width = size_hints->min_width;
7748 min_height = size_hints->min_height;
7750 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
7752 #if TARGET_API_MAC_CARBON
7753 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7754 return;
7755 height = new_rect.bottom - new_rect.top;
7756 width = new_rect.right - new_rect.left;
7757 #else
7758 grow_size = GrowWindow (w, e->where, &limit_rect);
7759 /* see if it really changed size */
7760 if (grow_size == 0)
7761 return;
7762 height = HiWord (grow_size);
7763 width = LoWord (grow_size);
7764 #endif
7766 if (width != FRAME_PIXEL_WIDTH (f)
7767 || height != FRAME_PIXEL_HEIGHT (f))
7769 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7770 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7772 x_set_window_size (f, 0, columns, rows);
7777 /* Handle clicks in zoom box. Calculation of "standard state" based
7778 on code in IM - Window Manager A and code contributed by Ben
7779 Mesander. The standard state of an Emacs window is 80-characters
7780 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7782 static void
7783 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7785 GrafPtr save_port;
7786 Rect zoom_rect, port_rect;
7787 Point top_left;
7788 int w_title_height, columns, rows, width, height;
7789 struct frame *f = mac_window_to_frame (w);
7790 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7792 #if TARGET_API_MAC_CARBON
7794 Point standard_size;
7796 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7797 standard_size.v = dpyinfo->height;
7799 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7800 zoom_in_or_out = inZoomIn;
7801 else
7803 /* Adjust the standard size according to character boundaries. */
7805 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7806 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7807 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7808 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7809 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7810 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7811 && port_rect.left == zoom_rect.left
7812 && port_rect.top == zoom_rect.top)
7813 zoom_in_or_out = inZoomIn;
7814 else
7815 zoom_in_or_out = inZoomOut;
7818 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7820 #else /* not TARGET_API_MAC_CARBON */
7821 GetPort (&save_port);
7823 SetPortWindowPort (w);
7825 /* Clear window to avoid flicker. */
7826 EraseRect (&(w->portRect));
7827 if (zoom_in_or_out == inZoomOut)
7829 SetPt (&top_left, w->portRect.left, w->portRect.top);
7830 LocalToGlobal (&top_left);
7832 /* calculate height of window's title bar */
7833 w_title_height = top_left.v - 1
7834 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7836 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7837 zoom_rect = qd.screenBits.bounds;
7838 zoom_rect.top += w_title_height;
7839 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7841 zoom_rect.right = zoom_rect.left
7842 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7844 /* Adjust the standard size according to character boundaries. */
7845 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7846 zoom_rect.bottom =
7847 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7849 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7850 = zoom_rect;
7853 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
7855 SetPort (save_port);
7856 #endif /* not TARGET_API_MAC_CARBON */
7858 /* retrieve window size and update application values */
7859 #if TARGET_API_MAC_CARBON
7860 GetWindowPortBounds (w, &port_rect);
7861 #else
7862 port_rect = w->portRect;
7863 #endif
7864 height = port_rect.bottom - port_rect.top;
7865 width = port_rect.right - port_rect.left;
7867 if (width != FRAME_PIXEL_WIDTH (f)
7868 || height != FRAME_PIXEL_HEIGHT (f))
7870 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7871 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7873 change_frame_size (f, rows, columns, 0, 1, 0);
7874 SET_FRAME_GARBAGED (f);
7875 cancel_mouse_face (f);
7877 FRAME_PIXEL_WIDTH (f) = width;
7878 FRAME_PIXEL_HEIGHT (f) = height;
7880 x_real_positions (f, &f->left_pos, &f->top_pos);
7883 /* Intialize AppleEvent dispatcher table for the required events. */
7884 void
7885 init_required_apple_events ()
7887 OSErr err;
7888 long result;
7890 /* Make sure we have apple events before starting. */
7891 err = Gestalt (gestaltAppleEventsAttr, &result);
7892 if (err != noErr)
7893 abort ();
7895 if (!(result & (1 << gestaltAppleEventsPresent)))
7896 abort ();
7898 #if TARGET_API_MAC_CARBON
7899 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7900 NewAEEventHandlerUPP
7901 ((AEEventHandlerProcPtr) do_ae_open_application),
7902 0L, false);
7903 #else
7904 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7905 NewAEEventHandlerProc
7906 ((AEEventHandlerProcPtr) do_ae_open_application),
7907 0L, false);
7908 #endif
7909 if (err != noErr)
7910 abort ();
7912 #if TARGET_API_MAC_CARBON
7913 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7914 NewAEEventHandlerUPP
7915 ((AEEventHandlerProcPtr) do_ae_open_documents),
7916 0L, false);
7917 #else
7918 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7919 NewAEEventHandlerProc
7920 ((AEEventHandlerProcPtr) do_ae_open_documents),
7921 0L, false);
7922 #endif
7923 if (err != noErr)
7924 abort ();
7926 #if TARGET_API_MAC_CARBON
7927 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7928 NewAEEventHandlerUPP
7929 ((AEEventHandlerProcPtr) do_ae_print_documents),
7930 0L, false);
7931 #else
7932 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7933 NewAEEventHandlerProc
7934 ((AEEventHandlerProcPtr) do_ae_print_documents),
7935 0L, false);
7936 #endif
7937 if (err != noErr)
7938 abort ();
7940 #if TARGET_API_MAC_CARBON
7941 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7942 NewAEEventHandlerUPP
7943 ((AEEventHandlerProcPtr) do_ae_quit_application),
7944 0L, false);
7945 #else
7946 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7947 NewAEEventHandlerProc
7948 ((AEEventHandlerProcPtr) do_ae_quit_application),
7949 0L, false);
7950 #endif
7951 if (err != noErr)
7952 abort ();
7955 void
7956 mac_store_application_menu_event (event)
7957 #if USE_CARBON_EVENTS
7958 EventRef event;
7959 #else
7960 UInt32 event;
7961 #endif
7963 struct input_event buf;
7964 Lisp_Object frame, entry;
7966 EVENT_INIT (buf);
7968 XSETFRAME (frame, mac_focus_frame (&one_mac_display_info));
7969 buf.kind = MENU_BAR_EVENT;
7970 buf.frame_or_window = frame;
7971 buf.arg = frame;
7972 kbd_buffer_store_event (&buf);
7974 buf.arg = Qapplication;
7975 kbd_buffer_store_event (&buf);
7977 #if USE_CARBON_EVENTS
7978 switch (GetEventClass (event))
7980 #ifdef MAC_OSX
7981 case kEventClassService:
7982 buf.arg = Qservices;
7983 kbd_buffer_store_event (&buf);
7984 switch (GetEventKind (event))
7986 case kEventServicePaste:
7987 entry = Qpaste;
7988 break;
7990 case kEventServicePerform:
7992 OSErr err;
7993 CFStringRef message;
7995 err = GetEventParameter (event, kEventParamServiceMessageName,
7996 typeCFStringRef, NULL,
7997 sizeof (CFStringRef), NULL, &message);
7998 buf.arg = Qperform;
7999 kbd_buffer_store_event (&buf);
8000 if (err == noErr && message)
8001 entry = intern (SDATA (cfstring_to_lisp (message)));
8002 else
8003 entry = Qnil;
8005 break;
8007 default:
8008 abort ();
8010 break;
8011 #endif /* MAC_OSX */
8012 case kEventClassCommand:
8014 HICommand command;
8016 GetEventParameter(event, kEventParamDirectObject, typeHICommand,
8017 NULL, sizeof (HICommand), NULL, &command);
8018 switch (command.commandID)
8020 case kHICommandAbout:
8021 entry = Qabout;
8022 break;
8023 #ifdef MAC_OSX
8024 case kHICommandPreferences:
8025 entry = Qpreferences;
8026 break;
8027 #endif /* MAC_OSX */
8028 case kHICommandQuit:
8029 entry = Qquit;
8030 break;
8031 default:
8032 abort ();
8035 break;
8037 default:
8038 abort ();
8040 #else /* USE_CARBON_EVENTS */
8041 switch (event)
8043 case kHICommandAbout:
8044 entry = Qabout;
8045 break;
8046 case kHICommandQuit:
8047 entry = Qquit;
8048 break;
8049 default:
8050 abort ();
8052 #endif
8054 buf.arg = entry;
8055 kbd_buffer_store_event (&buf);
8058 #if USE_CARBON_EVENTS
8059 static pascal OSStatus
8060 mac_handle_command_event (next_handler, event, data)
8061 EventHandlerCallRef next_handler;
8062 EventRef event;
8063 void *data;
8065 HICommand command;
8066 OSErr result;
8068 GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
8069 sizeof (HICommand), NULL, &command);
8071 switch (command.commandID)
8073 case kHICommandAbout:
8074 #ifdef MAC_OSX
8075 case kHICommandPreferences:
8076 #endif /* MAC_OSX */
8077 result = CallNextEventHandler (next_handler, event);
8078 if (result != eventNotHandledErr)
8079 return result;
8081 mac_store_application_menu_event (event);
8082 return noErr;
8084 default:
8085 break;
8088 return eventNotHandledErr;
8091 static OSErr
8092 init_command_handler ()
8094 OSErr err = noErr;
8095 EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
8096 static EventHandlerUPP handle_command_eventUPP = NULL;
8098 if (handle_command_eventUPP == NULL)
8099 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
8100 return InstallApplicationEventHandler (handle_command_eventUPP,
8101 GetEventTypeCount (specs), specs,
8102 NULL, NULL);
8105 static pascal OSStatus
8106 mac_handle_window_event (next_handler, event, data)
8107 EventHandlerCallRef next_handler;
8108 EventRef event;
8109 void *data;
8111 WindowPtr wp;
8112 OSStatus result;
8113 UInt32 attributes;
8114 XSizeHints *size_hints;
8116 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
8117 NULL, sizeof (WindowPtr), NULL, &wp);
8119 switch (GetEventKind (event))
8121 case kEventWindowUpdate:
8122 result = CallNextEventHandler (next_handler, event);
8123 if (result != eventNotHandledErr)
8124 return result;
8126 do_window_update (wp);
8127 return noErr;
8129 case kEventWindowBoundsChanging:
8130 result = CallNextEventHandler (next_handler, event);
8131 if (result != eventNotHandledErr)
8132 return result;
8134 GetEventParameter (event, kEventParamAttributes, typeUInt32,
8135 NULL, sizeof (UInt32), NULL, &attributes);
8136 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
8137 if ((attributes & kWindowBoundsChangeUserResize)
8138 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
8139 == (PResizeInc | PBaseSize | PMinSize)))
8141 Rect bounds;
8142 int width, height;
8144 GetEventParameter (event, kEventParamCurrentBounds,
8145 typeQDRectangle,
8146 NULL, sizeof (Rect), NULL, &bounds);
8147 width = bounds.right - bounds.left;
8148 height = bounds.bottom - bounds.top;
8150 if (width < size_hints->min_width)
8151 width = size_hints->min_width;
8152 else
8153 width = size_hints->base_width
8154 + (int) ((width - size_hints->base_width)
8155 / (float) size_hints->width_inc + .5)
8156 * size_hints->width_inc;
8158 if (height < size_hints->min_height)
8159 height = size_hints->min_height;
8160 else
8161 height = size_hints->base_height
8162 + (int) ((height - size_hints->base_height)
8163 / (float) size_hints->height_inc + .5)
8164 * size_hints->height_inc;
8166 bounds.right = bounds.left + width;
8167 bounds.bottom = bounds.top + height;
8168 SetEventParameter (event, kEventParamCurrentBounds,
8169 typeQDRectangle, sizeof (Rect), &bounds);
8170 return noErr;
8172 break;
8175 return eventNotHandledErr;
8178 static pascal OSStatus
8179 mac_handle_mouse_event (next_handler, event, data)
8180 EventHandlerCallRef next_handler;
8181 EventRef event;
8182 void *data;
8184 OSStatus result;
8186 switch (GetEventKind (event))
8188 case kEventMouseWheelMoved:
8190 WindowPtr wp;
8191 struct frame *f;
8192 EventMouseWheelAxis axis;
8193 SInt32 delta;
8194 Point point;
8196 result = CallNextEventHandler (next_handler, event);
8197 if (result != eventNotHandledErr || read_socket_inev == NULL)
8198 return result;
8200 GetEventParameter (event, kEventParamWindowRef, typeWindowRef,
8201 NULL, sizeof (WindowRef), NULL, &wp);
8202 f = mac_window_to_frame (wp);
8203 if (f != mac_focus_frame (&one_mac_display_info))
8204 break;
8206 GetEventParameter (event, kEventParamMouseWheelAxis,
8207 typeMouseWheelAxis, NULL,
8208 sizeof (EventMouseWheelAxis), NULL, &axis);
8209 if (axis != kEventMouseWheelAxisY)
8210 break;
8212 GetEventParameter (event, kEventParamMouseWheelDelta, typeSInt32,
8213 NULL, sizeof (SInt32), NULL, &delta);
8214 GetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
8215 NULL, sizeof (Point), NULL, &point);
8216 read_socket_inev->kind = WHEEL_EVENT;
8217 read_socket_inev->code = 0;
8218 read_socket_inev->modifiers =
8219 (mac_event_to_emacs_modifiers (event)
8220 | ((delta < 0) ? down_modifier : up_modifier));
8221 SetPortWindowPort (wp);
8222 GlobalToLocal (&point);
8223 XSETINT (read_socket_inev->x, point.h);
8224 XSETINT (read_socket_inev->y, point.v);
8225 XSETFRAME (read_socket_inev->frame_or_window, f);
8227 return noErr;
8229 break;
8231 default:
8232 break;
8235 return eventNotHandledErr;
8237 #endif /* USE_CARBON_EVENTS */
8240 OSErr
8241 install_window_handler (window)
8242 WindowPtr window;
8244 OSErr err = noErr;
8245 #if USE_CARBON_EVENTS
8246 EventTypeSpec specs_window[] =
8247 {{kEventClassWindow, kEventWindowUpdate},
8248 {kEventClassWindow, kEventWindowBoundsChanging}};
8249 EventTypeSpec specs_mouse[] = {{kEventClassMouse, kEventMouseWheelMoved}};
8250 static EventHandlerUPP handle_window_eventUPP = NULL;
8251 static EventHandlerUPP handle_mouse_eventUPP = NULL;
8253 if (handle_window_eventUPP == NULL)
8254 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event);
8255 if (handle_mouse_eventUPP == NULL)
8256 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event);
8257 err = InstallWindowEventHandler (window, handle_window_eventUPP,
8258 GetEventTypeCount (specs_window),
8259 specs_window, NULL, NULL);
8260 if (err == noErr)
8261 err = InstallWindowEventHandler (window, handle_mouse_eventUPP,
8262 GetEventTypeCount (specs_mouse),
8263 specs_mouse, NULL, NULL);
8264 #endif
8265 #if TARGET_API_MAC_CARBON
8266 if (mac_do_track_dragUPP == NULL)
8267 mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
8268 if (mac_do_receive_dragUPP == NULL)
8269 mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
8271 if (err == noErr)
8272 err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
8273 if (err == noErr)
8274 err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
8275 #endif
8276 return err;
8279 void
8280 remove_window_handler (window)
8281 WindowPtr window;
8283 #if TARGET_API_MAC_CARBON
8284 if (mac_do_track_dragUPP)
8285 RemoveTrackingHandler (mac_do_track_dragUPP, window);
8286 if (mac_do_receive_dragUPP)
8287 RemoveReceiveHandler (mac_do_receive_dragUPP, window);
8288 #endif
8291 /* Open Application Apple Event */
8292 static pascal OSErr
8293 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
8295 return noErr;
8299 /* Called when we receive an AppleEvent with an ID of
8300 "kAEOpenDocuments". This routine gets the direct parameter,
8301 extracts the FSSpecs in it, and puts their names on a list. */
8302 #pragma options align=mac68k
8303 typedef struct SelectionRange {
8304 short unused1; // 0 (not used)
8305 short lineNum; // line to select (<0 to specify range)
8306 long startRange; // start of selection range (if line < 0)
8307 long endRange; // end of selection range (if line < 0)
8308 long unused2; // 0 (not used)
8309 long theDate; // modification date/time
8310 } SelectionRange;
8311 #pragma options align=reset
8313 static pascal OSErr
8314 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
8316 OSErr err, err2;
8317 AEDesc the_desc;
8318 AEKeyword keyword;
8319 DescType actual_type;
8320 Size actual_size;
8321 SelectionRange position;
8322 Lisp_Object file_list = Qnil;
8324 xassert (read_socket_inev);
8326 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
8327 if (err != noErr)
8328 goto descriptor_error_exit;
8330 err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
8331 if (err == noErr)
8332 file_list = Fcons (list3 (make_number (position.lineNum + 1),
8333 make_number (position.startRange + 1),
8334 make_number (position.endRange + 1)),
8335 file_list);
8337 /* Check to see that we got all of the required parameters from the
8338 event descriptor. For an 'odoc' event this should just be the
8339 file list. */
8340 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
8341 &actual_type, (Ptr) &keyword,
8342 sizeof (keyword), &actual_size);
8343 /* No error means that we found some unused parameters.
8344 errAEDescNotFound means that there are no more parameters. If we
8345 get an error code other than that, flag it. */
8346 if ((err == noErr) || (err != errAEDescNotFound))
8348 err = errAEEventNotHandled;
8349 goto error_exit;
8351 err = noErr;
8353 /* Got all the parameters we need. Now, go through the direct
8354 object list and parse it up. */
8356 long num_files_to_open;
8358 err = AECountItems (&the_desc, &num_files_to_open);
8359 if (err == noErr)
8361 int i;
8363 /* AE file list is one based so just use that for indexing here. */
8364 for (i = 1; i <= num_files_to_open; i++)
8366 char unix_path_name[MAXPATHLEN];
8367 #ifdef MAC_OSX
8368 FSRef fref;
8370 err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
8371 &actual_type, &fref, sizeof (FSRef),
8372 &actual_size);
8373 if (err != noErr || actual_type != typeFSRef)
8374 continue;
8376 if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
8377 == noErr)
8378 #else
8379 FSSpec fs;
8381 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
8382 (Ptr) &fs, sizeof (fs), &actual_size);
8383 if (err != noErr) continue;
8385 if (fsspec_to_posix_pathname (&fs, unix_path_name,
8386 sizeof (unix_path_name) - 1) == noErr)
8387 #endif
8388 /* x-dnd functions expect undecoded filenames. */
8389 file_list = Fcons (make_unibyte_string (unix_path_name,
8390 strlen (unix_path_name)),
8391 file_list);
8395 /* Build a DRAG_N_DROP_EVENT type event as is done in
8396 constuct_drag_n_drop in w32term.c. */
8397 if (!NILP (file_list))
8399 struct frame *f = mac_focus_frame (&one_mac_display_info);
8400 WindowPtr wp;
8401 Lisp_Object frame;
8403 read_socket_inev->kind = DRAG_N_DROP_EVENT;
8404 read_socket_inev->code = 0;
8405 read_socket_inev->modifiers = 0;
8407 XSETINT (read_socket_inev->x, 0);
8408 XSETINT (read_socket_inev->y, 0);
8410 XSETFRAME (frame, f);
8411 read_socket_inev->frame_or_window = Fcons (frame, file_list);
8413 #if 0
8414 /* Regardless of whether Emacs was suspended or in the
8415 foreground, ask it to redraw its entire screen. Otherwise
8416 parts of the screen can be left in an inconsistent
8417 state. */
8418 wp = FRAME_MAC_WINDOW (f);
8419 if (wp)
8420 #if TARGET_API_MAC_CARBON
8422 Rect r;
8424 GetWindowPortBounds (wp, &r);
8425 InvalWindowRect (wp, &r);
8427 #else /* not TARGET_API_MAC_CARBON */
8428 InvalRect (&(wp->portRect));
8429 #endif /* not TARGET_API_MAC_CARBON */
8430 #endif
8434 error_exit:
8435 /* Nuke the coerced file list in any case */
8436 err2 = AEDisposeDesc(&the_desc);
8438 descriptor_error_exit:
8439 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8440 return err;
8444 #if TARGET_API_MAC_CARBON
8445 static pascal OSErr
8446 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
8447 void *handlerRefCon, DragReference theDrag)
8449 static int can_accept;
8450 short items;
8451 short index;
8452 ItemReference theItem;
8453 FlavorFlags theFlags;
8454 OSErr result;
8456 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8457 return dragNotAcceptedErr;
8459 switch (message)
8461 case kDragTrackingEnterHandler:
8462 CountDragItems (theDrag, &items);
8463 can_accept = 0;
8464 for (index = 1; index <= items; index++)
8466 GetDragItemReferenceNumber (theDrag, index, &theItem);
8467 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8468 if (result == noErr)
8470 can_accept = 1;
8471 break;
8474 break;
8476 case kDragTrackingEnterWindow:
8477 if (can_accept)
8479 RgnHandle hilite_rgn = NewRgn ();
8480 Rect r;
8481 struct frame *f = mac_window_to_frame (window);
8483 GetWindowPortBounds (window, &r);
8484 OffsetRect (&r, -r.left, -r.top);
8485 RectRgn (hilite_rgn, &r);
8486 ShowDragHilite (theDrag, hilite_rgn, true);
8487 DisposeRgn (hilite_rgn);
8488 SetThemeCursor (kThemeCopyArrowCursor);
8490 break;
8492 case kDragTrackingInWindow:
8493 break;
8495 case kDragTrackingLeaveWindow:
8496 if (can_accept)
8498 struct frame *f = mac_window_to_frame (window);
8500 HideDragHilite (theDrag);
8501 SetThemeCursor (kThemeArrowCursor);
8503 break;
8505 case kDragTrackingLeaveHandler:
8506 break;
8509 return noErr;
8512 static pascal OSErr
8513 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8514 DragReference theDrag)
8516 short items;
8517 short index;
8518 FlavorFlags theFlags;
8519 Point mouse;
8520 OSErr result;
8521 ItemReference theItem;
8522 HFSFlavor data;
8523 Size size = sizeof (HFSFlavor);
8524 Lisp_Object file_list;
8526 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8527 return dragNotAcceptedErr;
8529 file_list = Qnil;
8530 GetDragMouse (theDrag, &mouse, 0L);
8531 CountDragItems (theDrag, &items);
8532 for (index = 1; index <= items; index++)
8534 /* Only handle file references. */
8535 GetDragItemReferenceNumber (theDrag, index, &theItem);
8536 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8537 if (result == noErr)
8539 #ifdef MAC_OSX
8540 FSRef fref;
8541 #endif
8542 char unix_path_name[MAXPATHLEN];
8544 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8545 #ifdef MAC_OSX
8546 /* Use Carbon routines, otherwise it converts the file name
8547 to /Macintosh HD/..., which is not correct. */
8548 FSpMakeFSRef (&data.fileSpec, &fref);
8549 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8550 #else
8551 if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
8552 sizeof (unix_path_name) - 1) == noErr)
8553 #endif
8554 /* x-dnd functions expect undecoded filenames. */
8555 file_list = Fcons (make_unibyte_string (unix_path_name,
8556 strlen (unix_path_name)),
8557 file_list);
8560 /* If there are items in the list, construct an event and post it to
8561 the queue like an interrupt using kbd_buffer_store_event. */
8562 if (!NILP (file_list))
8564 struct input_event event;
8565 Lisp_Object frame;
8566 struct frame *f = mac_window_to_frame (window);
8567 SInt16 modifiers;
8569 GlobalToLocal (&mouse);
8570 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
8572 event.kind = DRAG_N_DROP_EVENT;
8573 event.code = 0;
8574 event.modifiers = mac_to_emacs_modifiers (modifiers);
8575 event.timestamp = TickCount () * (1000 / 60);
8576 XSETINT (event.x, mouse.h);
8577 XSETINT (event.y, mouse.v);
8578 XSETFRAME (frame, f);
8579 event.frame_or_window = Fcons (frame, file_list);
8580 event.arg = Qnil;
8581 /* Post to the interrupt queue */
8582 kbd_buffer_store_event (&event);
8583 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8585 ProcessSerialNumber psn;
8586 GetCurrentProcess (&psn);
8587 SetFrontProcess (&psn);
8590 return noErr;
8592 else
8593 return dragNotAcceptedErr;
8595 #endif
8598 /* Print Document Apple Event */
8599 static pascal OSErr
8600 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8602 return errAEEventNotHandled;
8606 static pascal OSErr
8607 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8609 #if USE_CARBON_EVENTS
8610 OSErr err;
8611 EventRef event = NULL;
8612 static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
8614 err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
8615 kEventAttributeUserEvent, &event);
8616 if (err == noErr)
8617 err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
8618 sizeof (HICommand), &quit_command);
8619 if (err == noErr)
8620 mac_store_application_menu_event (event);
8621 if (event)
8622 ReleaseEvent (event);
8624 if (err == noErr)
8625 return noErr;
8626 else
8627 return errAEEventNotHandled;
8628 #else
8629 mac_store_application_menu_event (kHICommandQuit);
8631 return noErr;
8632 #endif
8636 #if __profile__
8637 void
8638 profiler_exit_proc ()
8640 ProfilerDump ("\pEmacs.prof");
8641 ProfilerTerm ();
8643 #endif
8645 /* These few functions implement Emacs as a normal Mac application
8646 (almost): set up the heap and the Toolbox, handle necessary system
8647 events plus a few simple menu events. They also set up Emacs's
8648 access to functions defined in the rest of this file. Emacs uses
8649 function hooks to perform all its terminal I/O. A complete list of
8650 these functions appear in termhooks.h. For what they do, read the
8651 comments there and see also w32term.c and xterm.c. What's
8652 noticeably missing here is the event loop, which is normally
8653 present in most Mac application. After performing the necessary
8654 Mac initializations, main passes off control to emacs_main
8655 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8656 (defined further below) to read input. This is where
8657 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8659 #ifdef MAC_OS8
8660 #undef main
8662 main (void)
8664 #if __profile__ /* is the profiler on? */
8665 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8666 exit(1);
8667 #endif
8669 #if __MWERKS__
8670 /* set creator and type for files created by MSL */
8671 _fcreator = 'EMAx';
8672 _ftype = 'TEXT';
8673 #endif
8675 do_init_managers ();
8677 do_get_menus ();
8679 #ifndef USE_LSB_TAG
8680 do_check_ram_size ();
8681 #endif
8683 init_emacs_passwd_dir ();
8685 init_environ ();
8687 initialize_applescript ();
8689 init_required_apple_events ();
8692 char **argv;
8693 int argc = 0;
8695 /* set up argv array from STR# resource */
8696 get_string_list (&argv, ARGV_STRING_LIST_ID);
8697 while (argv[argc])
8698 argc++;
8700 /* free up AppleScript resources on exit */
8701 atexit (terminate_applescript);
8703 #if __profile__ /* is the profiler on? */
8704 atexit (profiler_exit_proc);
8705 #endif
8707 /* 3rd param "envp" never used in emacs_main */
8708 (void) emacs_main (argc, argv, 0);
8711 /* Never reached - real exit in Fkill_emacs */
8712 return 0;
8714 #endif
8716 /* Table for translating Mac keycode to X keysym values. Contributed
8717 by Sudhir Shenoy.
8718 Mapping for special keys is now identical to that in Apple X11
8719 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8720 on the right of the Cmd key on laptops, and fn + `enter' (->
8721 <linefeed>). */
8722 static unsigned char keycode_to_xkeysym_table[] = {
8723 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8724 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8725 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8727 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8728 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8729 /*0x38*/ 0, 0, 0, 0,
8730 /*0x3C*/ 0, 0, 0, 0,
8732 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8733 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8734 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8735 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8737 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8738 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8739 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8740 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8742 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8743 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8744 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8745 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8747 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8748 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8749 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8750 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8753 static int
8754 keycode_to_xkeysym (int keyCode, int *xKeySym)
8756 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8757 return *xKeySym != 0;
8760 #if !USE_CARBON_EVENTS
8761 static RgnHandle mouse_region = NULL;
8763 Boolean
8764 mac_wait_next_event (er, sleep_time, dequeue)
8765 EventRecord *er;
8766 UInt32 sleep_time;
8767 Boolean dequeue;
8769 static EventRecord er_buf = {nullEvent};
8770 UInt32 target_tick, current_tick;
8771 EventMask event_mask;
8773 if (mouse_region == NULL)
8774 mouse_region = NewRgn ();
8776 event_mask = everyEvent;
8777 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8778 event_mask -= highLevelEventMask;
8780 current_tick = TickCount ();
8781 target_tick = current_tick + sleep_time;
8783 if (er_buf.what == nullEvent)
8784 while (!WaitNextEvent (event_mask, &er_buf,
8785 target_tick - current_tick, mouse_region))
8787 current_tick = TickCount ();
8788 if (target_tick <= current_tick)
8789 return false;
8792 *er = er_buf;
8793 if (dequeue)
8794 er_buf.what = nullEvent;
8795 return true;
8797 #endif /* not USE_CARBON_EVENTS */
8799 /* Emacs calls this whenever it wants to read an input event from the
8800 user. */
8802 XTread_socket (sd, expected, hold_quit)
8803 int sd, expected;
8804 struct input_event *hold_quit;
8806 struct input_event inev;
8807 int count = 0;
8808 #if USE_CARBON_EVENTS
8809 EventRef eventRef;
8810 EventTargetRef toolbox_dispatcher;
8811 #endif
8812 EventRecord er;
8813 struct mac_display_info *dpyinfo = &one_mac_display_info;
8815 if (interrupt_input_blocked)
8817 interrupt_input_pending = 1;
8818 return -1;
8821 interrupt_input_pending = 0;
8822 BLOCK_INPUT;
8824 /* So people can tell when we have read the available input. */
8825 input_signal_count++;
8827 #if USE_CARBON_EVENTS
8828 toolbox_dispatcher = GetEventDispatcherTarget ();
8830 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8831 kEventRemoveFromQueue, &eventRef))
8832 #else /* !USE_CARBON_EVENTS */
8833 while (mac_wait_next_event (&er, 0, true))
8834 #endif /* !USE_CARBON_EVENTS */
8836 int do_help = 0;
8837 struct frame *f;
8838 unsigned long timestamp;
8840 /* It is necessary to set this (additional) argument slot of an
8841 event to nil because keyboard.c protects incompletely
8842 processed event from being garbage collected by placing them
8843 in the kbd_buffer_gcpro vector. */
8844 EVENT_INIT (inev);
8845 inev.kind = NO_EVENT;
8846 inev.arg = Qnil;
8848 #if USE_CARBON_EVENTS
8849 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond;
8850 #else
8851 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8852 #endif
8854 #if USE_CARBON_EVENTS
8855 /* Handle new events */
8856 if (!mac_convert_event_ref (eventRef, &er))
8858 /* There used to be a handler for the kEventMouseWheelMoved
8859 event here. But as of Mac OS X 10.4, this kind of event
8860 is not directly posted to the main event queue by
8861 two-finger scrolling on the trackpad. Instead, some
8862 private event is posted and it is converted to a wheel
8863 event by the default handler for the application target.
8864 The converted one can be received by a Carbon event
8865 handler installed on a window target. */
8866 read_socket_inev = &inev;
8867 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8868 read_socket_inev = NULL;
8870 else
8871 #endif /* USE_CARBON_EVENTS */
8872 switch (er.what)
8874 case mouseDown:
8875 case mouseUp:
8877 WindowPtr window_ptr;
8878 ControlPartCode part_code;
8879 int tool_bar_p = 0;
8881 #if USE_CARBON_EVENTS
8882 /* This is needed to send mouse events like aqua window
8883 buttons to the correct handler. */
8884 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8885 != eventNotHandledErr)
8886 break;
8887 #endif
8889 if (dpyinfo->grabbed && last_mouse_frame
8890 && FRAME_LIVE_P (last_mouse_frame))
8892 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8893 part_code = inContent;
8895 else
8897 part_code = FindWindow (er.where, &window_ptr);
8898 if (tip_window && window_ptr == tip_window)
8900 HideWindow (tip_window);
8901 part_code = FindWindow (er.where, &window_ptr);
8905 if (er.what != mouseDown && part_code != inContent)
8906 break;
8908 switch (part_code)
8910 case inMenuBar:
8911 f = mac_focus_frame (dpyinfo);
8912 saved_menu_event_location = er.where;
8913 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8914 XSETFRAME (inev.frame_or_window, f);
8915 break;
8917 case inContent:
8918 if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
8919 SelectWindow (window_ptr);
8920 else
8922 ControlPartCode control_part_code;
8923 ControlHandle ch;
8924 Point mouse_loc = er.where;
8925 #ifdef MAC_OSX
8926 ControlKind control_kind;
8927 #endif
8929 f = mac_window_to_frame (window_ptr);
8930 /* convert to local coordinates of new window */
8931 SetPortWindowPort (window_ptr);
8933 GlobalToLocal (&mouse_loc);
8934 #if TARGET_API_MAC_CARBON
8935 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8936 &control_part_code);
8937 #ifdef MAC_OSX
8938 if (ch)
8939 GetControlKind (ch, &control_kind);
8940 #endif
8941 #else
8942 control_part_code = FindControl (mouse_loc, window_ptr,
8943 &ch);
8944 #endif
8946 #if USE_CARBON_EVENTS
8947 inev.code = mac_get_mouse_btn (eventRef);
8948 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8949 #else
8950 inev.code = mac_get_emulated_btn (er.modifiers);
8951 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8952 #endif
8953 XSETINT (inev.x, mouse_loc.h);
8954 XSETINT (inev.y, mouse_loc.v);
8956 if (dpyinfo->grabbed && tracked_scroll_bar
8957 || ch != 0
8958 #ifndef USE_TOOLKIT_SCROLL_BARS
8959 /* control_part_code becomes kControlNoPart if
8960 a progress indicator is clicked. */
8961 && control_part_code != kControlNoPart
8962 #else /* USE_TOOLKIT_SCROLL_BARS */
8963 #ifdef MAC_OSX
8964 && control_kind.kind == kControlKindScrollBar
8965 #endif /* MAC_OSX */
8966 #endif /* USE_TOOLKIT_SCROLL_BARS */
8969 struct scroll_bar *bar;
8971 if (dpyinfo->grabbed && tracked_scroll_bar)
8973 bar = tracked_scroll_bar;
8974 #ifndef USE_TOOLKIT_SCROLL_BARS
8975 control_part_code = kControlIndicatorPart;
8976 #endif
8978 else
8979 bar = (struct scroll_bar *) GetControlReference (ch);
8980 #ifdef USE_TOOLKIT_SCROLL_BARS
8981 /* Make the "Ctrl-Mouse-2 splits window" work
8982 for toolkit scroll bars. */
8983 if (er.modifiers & controlKey)
8984 x_scroll_bar_handle_click (bar, control_part_code,
8985 &er, &inev);
8986 else if (er.what == mouseDown)
8987 x_scroll_bar_handle_press (bar, control_part_code,
8988 &inev);
8989 else
8990 x_scroll_bar_handle_release (bar, &inev);
8991 #else /* not USE_TOOLKIT_SCROLL_BARS */
8992 x_scroll_bar_handle_click (bar, control_part_code,
8993 &er, &inev);
8994 if (er.what == mouseDown
8995 && control_part_code == kControlIndicatorPart)
8996 tracked_scroll_bar = bar;
8997 else
8998 tracked_scroll_bar = NULL;
8999 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9001 else
9003 Lisp_Object window;
9004 int x = mouse_loc.h;
9005 int y = mouse_loc.v;
9007 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
9008 if (EQ (window, f->tool_bar_window))
9010 if (er.what == mouseDown)
9011 handle_tool_bar_click (f, x, y, 1, 0);
9012 else
9013 handle_tool_bar_click (f, x, y, 0,
9014 inev.modifiers);
9015 tool_bar_p = 1;
9017 else
9019 XSETFRAME (inev.frame_or_window, f);
9020 inev.kind = MOUSE_CLICK_EVENT;
9024 if (er.what == mouseDown)
9026 dpyinfo->grabbed |= (1 << inev.code);
9027 last_mouse_frame = f;
9028 /* Ignore any mouse motion that happened
9029 before this event; any subsequent
9030 mouse-movement Emacs events should reflect
9031 only motion after the ButtonPress. */
9032 if (f != 0)
9033 f->mouse_moved = 0;
9035 if (!tool_bar_p)
9036 last_tool_bar_item = -1;
9038 else
9040 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
9041 /* If a button is released though it was not
9042 previously pressed, that would be because
9043 of multi-button emulation. */
9044 dpyinfo->grabbed = 0;
9045 else
9046 dpyinfo->grabbed &= ~(1 << inev.code);
9049 #ifdef USE_TOOLKIT_SCROLL_BARS
9050 if (inev.kind == MOUSE_CLICK_EVENT)
9051 #endif
9052 switch (er.what)
9054 case mouseDown:
9055 inev.modifiers |= down_modifier;
9056 break;
9057 case mouseUp:
9058 inev.modifiers |= up_modifier;
9059 break;
9062 break;
9064 case inDrag:
9065 #if TARGET_API_MAC_CARBON
9066 DragWindow (window_ptr, er.where, NULL);
9067 #else /* not TARGET_API_MAC_CARBON */
9068 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
9069 #endif /* not TARGET_API_MAC_CARBON */
9070 /* Update the frame parameters. */
9072 struct frame *f = mac_window_to_frame (window_ptr);
9074 if (f && !f->async_iconified)
9075 x_real_positions (f, &f->left_pos, &f->top_pos);
9077 break;
9079 case inGoAway:
9080 if (TrackGoAway (window_ptr, er.where))
9082 inev.kind = DELETE_WINDOW_EVENT;
9083 XSETFRAME (inev.frame_or_window,
9084 mac_window_to_frame (window_ptr));
9086 break;
9088 /* window resize handling added --ben */
9089 case inGrow:
9090 do_grow_window (window_ptr, &er);
9091 break;
9093 /* window zoom handling added --ben */
9094 case inZoomIn:
9095 case inZoomOut:
9096 if (TrackBox (window_ptr, er.where, part_code))
9097 do_zoom_window (window_ptr, part_code);
9098 break;
9100 default:
9101 break;
9104 break;
9106 case updateEvt:
9107 #if USE_CARBON_EVENTS
9108 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9109 != eventNotHandledErr)
9110 break;
9111 #else
9112 do_window_update ((WindowPtr) er.message);
9113 #endif
9114 break;
9116 case osEvt:
9117 #if USE_CARBON_EVENTS
9118 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9119 != eventNotHandledErr)
9120 break;
9121 #endif
9122 switch ((er.message >> 24) & 0x000000FF)
9124 case suspendResumeMessage:
9125 if ((er.message & resumeFlag) == 1)
9126 do_app_resume ();
9127 else
9128 do_app_suspend ();
9129 break;
9131 case mouseMovedMessage:
9132 #if !USE_CARBON_EVENTS
9133 SetRectRgn (mouse_region, er.where.h, er.where.v,
9134 er.where.h + 1, er.where.v + 1);
9135 #endif
9136 previous_help_echo_string = help_echo_string;
9137 help_echo_string = help_echo_object = help_echo_window = Qnil;
9138 help_echo_pos = -1;
9140 if (dpyinfo->grabbed && last_mouse_frame
9141 && FRAME_LIVE_P (last_mouse_frame))
9142 f = last_mouse_frame;
9143 else
9144 f = dpyinfo->x_focus_frame;
9146 if (dpyinfo->mouse_face_hidden)
9148 dpyinfo->mouse_face_hidden = 0;
9149 clear_mouse_face (dpyinfo);
9152 if (f)
9154 WindowPtr wp = FRAME_MAC_WINDOW (f);
9155 Point mouse_pos = er.where;
9157 SetPortWindowPort (wp);
9159 GlobalToLocal (&mouse_pos);
9161 if (dpyinfo->grabbed && tracked_scroll_bar)
9162 #ifdef USE_TOOLKIT_SCROLL_BARS
9163 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
9164 mouse_pos, &inev);
9165 #else /* not USE_TOOLKIT_SCROLL_BARS */
9166 x_scroll_bar_note_movement (tracked_scroll_bar,
9167 mouse_pos.v
9168 - XINT (tracked_scroll_bar->top),
9169 er.when * (1000 / 60));
9170 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9171 else
9173 /* Generate SELECT_WINDOW_EVENTs when needed. */
9174 if (mouse_autoselect_window)
9176 Lisp_Object window;
9178 window = window_from_coordinates (f,
9179 mouse_pos.h,
9180 mouse_pos.v,
9181 0, 0, 0, 0);
9183 /* Window will be selected only when it is
9184 not selected now and last mouse movement
9185 event was not in it. Minibuffer window
9186 will be selected iff it is active. */
9187 if (WINDOWP (window)
9188 && !EQ (window, last_window)
9189 && !EQ (window, selected_window))
9191 inev.kind = SELECT_WINDOW_EVENT;
9192 inev.frame_or_window = window;
9195 last_window=window;
9197 note_mouse_movement (f, &mouse_pos);
9201 /* If the contents of the global variable
9202 help_echo_string has changed, generate a
9203 HELP_EVENT. */
9204 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
9205 do_help = 1;
9206 break;
9208 break;
9210 case activateEvt:
9212 WindowPtr window_ptr = (WindowPtr) er.message;
9214 #if USE_CARBON_EVENTS
9215 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9216 != eventNotHandledErr)
9217 break;
9218 #endif
9219 if (window_ptr == tip_window)
9221 HideWindow (tip_window);
9222 break;
9225 if (!is_emacs_window (window_ptr))
9226 break;
9228 if ((er.modifiers & activeFlag) != 0)
9230 /* A window has been activated */
9231 Point mouse_loc = er.where;
9233 x_detect_focus_change (dpyinfo, &er, &inev);
9235 SetPortWindowPort (window_ptr);
9236 GlobalToLocal (&mouse_loc);
9237 /* Window-activated event counts as mouse movement,
9238 so update things that depend on mouse position. */
9239 note_mouse_movement (mac_window_to_frame (window_ptr),
9240 &mouse_loc);
9242 else
9244 /* A window has been deactivated */
9245 #if USE_TOOLKIT_SCROLL_BARS
9246 if (dpyinfo->grabbed && tracked_scroll_bar)
9248 struct input_event event;
9250 EVENT_INIT (event);
9251 event.kind = NO_EVENT;
9252 x_scroll_bar_handle_release (tracked_scroll_bar, &event);
9253 if (event.kind != NO_EVENT)
9255 event.timestamp = timestamp;
9256 kbd_buffer_store_event_hold (&event, hold_quit);
9257 count++;
9260 #endif
9261 dpyinfo->grabbed = 0;
9263 x_detect_focus_change (dpyinfo, &er, &inev);
9265 f = mac_window_to_frame (window_ptr);
9266 if (f == dpyinfo->mouse_face_mouse_frame)
9268 /* If we move outside the frame, then we're
9269 certainly no longer on any text in the
9270 frame. */
9271 clear_mouse_face (dpyinfo);
9272 dpyinfo->mouse_face_mouse_frame = 0;
9275 /* Generate a nil HELP_EVENT to cancel a help-echo.
9276 Do it only if there's something to cancel.
9277 Otherwise, the startup message is cleared when the
9278 mouse leaves the frame. */
9279 if (any_help_event_p)
9280 do_help = -1;
9283 break;
9285 case keyDown:
9286 case autoKey:
9288 int keycode = (er.message & keyCodeMask) >> 8;
9289 int xkeysym;
9291 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9292 /* When using Carbon Events, we need to pass raw keyboard
9293 events to the TSM ourselves. If TSM handles it, it
9294 will pass back noErr, otherwise it will pass back
9295 "eventNotHandledErr" and we can process it
9296 normally. */
9297 if ((!NILP (Vmac_pass_command_to_system)
9298 || !(er.modifiers & cmdKey))
9299 && (!NILP (Vmac_pass_control_to_system)
9300 || !(er.modifiers & controlKey))
9301 && (!NILP (Vmac_command_key_is_meta)
9302 && NILP (Vmac_option_modifier)
9303 || !(er.modifiers & optionKey)))
9304 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9305 != eventNotHandledErr)
9306 break;
9307 #endif
9309 #if 0
9310 if (dpyinfo->x_focus_frame == NULL)
9312 /* Beep if keyboard input occurs when all the frames
9313 are invisible. */
9314 SysBeep (1);
9315 break;
9317 #endif
9320 static SInt16 last_key_script = -1;
9321 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
9323 if (last_key_script != current_key_script)
9325 struct input_event event;
9327 EVENT_INIT (event);
9328 event.kind = LANGUAGE_CHANGE_EVENT;
9329 event.arg = Qnil;
9330 event.code = current_key_script;
9331 event.timestamp = timestamp;
9332 kbd_buffer_store_event (&event);
9333 count++;
9335 last_key_script = current_key_script;
9338 ObscureCursor ();
9340 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
9342 clear_mouse_face (dpyinfo);
9343 dpyinfo->mouse_face_hidden = 1;
9346 if (keycode_to_xkeysym (keycode, &xkeysym))
9348 inev.code = 0xff00 | xkeysym;
9349 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
9351 else
9353 if (er.modifiers & (controlKey |
9354 (NILP (Vmac_command_key_is_meta) ? optionKey
9355 : cmdKey)))
9357 /* This code comes from Keyboard Resource,
9358 Appendix C of IM - Text. This is necessary
9359 since shift is ignored in KCHR table
9360 translation when option or command is pressed.
9361 It also does not translate correctly
9362 control-shift chars like C-% so mask off shift
9363 here also */
9364 int new_modifiers = er.modifiers & 0xe600;
9365 /* mask off option and command */
9366 int new_keycode = keycode | new_modifiers;
9367 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9368 unsigned long some_state = 0;
9369 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9370 &some_state) & 0xff;
9372 else if (!NILP (Vmac_option_modifier)
9373 && (er.modifiers & optionKey))
9375 /* When using the option key as an emacs modifier,
9376 convert the pressed key code back to one
9377 without the Mac option modifier applied. */
9378 int new_modifiers = er.modifiers & ~optionKey;
9379 int new_keycode = keycode | new_modifiers;
9380 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9381 unsigned long some_state = 0;
9382 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9383 &some_state) & 0xff;
9385 else
9386 inev.code = er.message & charCodeMask;
9387 inev.kind = ASCII_KEYSTROKE_EVENT;
9391 #if USE_CARBON_EVENTS
9392 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9393 #else
9394 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9395 #endif
9396 inev.modifiers |= (extra_keyboard_modifiers
9397 & (meta_modifier | alt_modifier
9398 | hyper_modifier | super_modifier));
9399 XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
9400 break;
9402 case kHighLevelEvent:
9403 read_socket_inev = &inev;
9404 AEProcessAppleEvent (&er);
9405 read_socket_inev = NULL;
9406 break;
9408 default:
9409 break;
9411 #if USE_CARBON_EVENTS
9412 ReleaseEvent (eventRef);
9413 #endif
9415 if (inev.kind != NO_EVENT)
9417 inev.timestamp = timestamp;
9418 kbd_buffer_store_event_hold (&inev, hold_quit);
9419 count++;
9422 if (do_help
9423 && !(hold_quit && hold_quit->kind != NO_EVENT))
9425 Lisp_Object frame;
9427 if (f)
9428 XSETFRAME (frame, f);
9429 else
9430 frame = Qnil;
9432 if (do_help > 0)
9434 any_help_event_p = 1;
9435 gen_help_event (help_echo_string, frame, help_echo_window,
9436 help_echo_object, help_echo_pos);
9438 else
9440 help_echo_string = Qnil;
9441 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9443 count++;
9448 /* If the focus was just given to an autoraising frame,
9449 raise it now. */
9450 /* ??? This ought to be able to handle more than one such frame. */
9451 if (pending_autoraise_frame)
9453 x_raise_frame (pending_autoraise_frame);
9454 pending_autoraise_frame = 0;
9457 UNBLOCK_INPUT;
9458 return count;
9462 /* Need to override CodeWarrior's input function so no conversion is
9463 done on newlines Otherwise compiled functions in .elc files will be
9464 read incorrectly. Defined in ...:MSL C:MSL
9465 Common:Source:buffer_io.c. */
9466 #ifdef __MWERKS__
9467 void
9468 __convert_to_newlines (unsigned char * p, size_t * n)
9470 #pragma unused(p,n)
9473 void
9474 __convert_from_newlines (unsigned char * p, size_t * n)
9476 #pragma unused(p,n)
9478 #endif
9480 #ifdef MAC_OS8
9481 void
9482 make_mac_terminal_frame (struct frame *f)
9484 Lisp_Object frame;
9485 Rect r;
9487 XSETFRAME (frame, f);
9489 f->output_method = output_mac;
9490 f->output_data.mac = (struct mac_output *)
9491 xmalloc (sizeof (struct mac_output));
9492 bzero (f->output_data.mac, sizeof (struct mac_output));
9494 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9496 FRAME_COLS (f) = 96;
9497 FRAME_LINES (f) = 4;
9499 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9500 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9502 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9504 f->output_data.mac->cursor_pixel = 0;
9505 f->output_data.mac->border_pixel = 0x00ff00;
9506 f->output_data.mac->mouse_pixel = 0xff00ff;
9507 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9509 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9510 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9511 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9512 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9513 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9514 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9516 FRAME_FONTSET (f) = -1;
9517 f->output_data.mac->explicit_parent = 0;
9518 f->left_pos = 8;
9519 f->top_pos = 32;
9520 f->border_width = 0;
9522 f->internal_border_width = 0;
9524 f->auto_raise = 1;
9525 f->auto_lower = 1;
9527 f->new_text_cols = 0;
9528 f->new_text_lines = 0;
9530 SetRect (&r, f->left_pos, f->top_pos,
9531 f->left_pos + FRAME_PIXEL_WIDTH (f),
9532 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9534 BLOCK_INPUT;
9536 if (!(FRAME_MAC_WINDOW (f) =
9537 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9538 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9539 abort ();
9540 /* so that update events can find this mac_output struct */
9541 f->output_data.mac->mFP = f; /* point back to emacs frame */
9543 UNBLOCK_INPUT;
9545 x_make_gc (f);
9547 /* Need to be initialized for unshow_buffer in window.c. */
9548 selected_window = f->selected_window;
9550 Fmodify_frame_parameters (frame,
9551 Fcons (Fcons (Qfont,
9552 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9553 Fmodify_frame_parameters (frame,
9554 Fcons (Fcons (Qforeground_color,
9555 build_string ("black")), Qnil));
9556 Fmodify_frame_parameters (frame,
9557 Fcons (Fcons (Qbackground_color,
9558 build_string ("white")), Qnil));
9560 #endif
9563 /***********************************************************************
9564 Initialization
9565 ***********************************************************************/
9567 int mac_initialized = 0;
9569 void
9570 mac_initialize_display_info ()
9572 struct mac_display_info *dpyinfo = &one_mac_display_info;
9573 GDHandle main_device_handle;
9575 bzero (dpyinfo, sizeof (*dpyinfo));
9577 #ifdef MAC_OSX
9578 dpyinfo->mac_id_name
9579 = (char *) xmalloc (SCHARS (Vinvocation_name)
9580 + SCHARS (Vsystem_name)
9581 + 2);
9582 sprintf (dpyinfo->mac_id_name, "%s@%s",
9583 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9584 #else
9585 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9586 strcpy (dpyinfo->mac_id_name, "Mac Display");
9587 #endif
9589 main_device_handle = LMGetMainDevice();
9591 dpyinfo->reference_count = 0;
9592 dpyinfo->resx = 75.0;
9593 dpyinfo->resy = 75.0;
9594 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
9595 #ifdef MAC_OSX
9596 /* HasDepth returns true if it is possible to have a 32 bit display,
9597 but this may not be what is actually used. Mac OSX can do better.
9598 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9599 header for CGGetActiveDisplayList says that the first display returned
9600 is the active one, so we use that. */
9602 CGDirectDisplayID disp_id[1];
9603 CGDisplayCount disp_count;
9604 CGDisplayErr error_code;
9606 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9607 if (error_code != 0)
9608 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9610 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9612 #else
9613 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9614 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9615 gdDevType, dpyinfo->color_p))
9616 break;
9617 #endif
9618 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9619 dpyinfo->width = (**main_device_handle).gdRect.right;
9620 dpyinfo->grabbed = 0;
9621 dpyinfo->root_window = NULL;
9622 dpyinfo->image_cache = make_image_cache ();
9624 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9625 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9626 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9627 dpyinfo->mouse_face_window = Qnil;
9628 dpyinfo->mouse_face_overlay = Qnil;
9629 dpyinfo->mouse_face_hidden = 0;
9633 static XrmDatabase
9634 mac_make_rdb (xrm_option)
9635 char *xrm_option;
9637 XrmDatabase database;
9639 database = xrm_get_preference_database (NULL);
9640 if (xrm_option)
9641 xrm_merge_string_database (database, xrm_option);
9643 return database;
9646 struct mac_display_info *
9647 mac_term_init (display_name, xrm_option, resource_name)
9648 Lisp_Object display_name;
9649 char *xrm_option;
9650 char *resource_name;
9652 struct mac_display_info *dpyinfo;
9654 BLOCK_INPUT;
9656 if (!mac_initialized)
9658 mac_initialize ();
9659 mac_initialized = 1;
9662 if (x_display_list)
9663 error ("Sorry, this version can only handle one display");
9665 mac_initialize_display_info ();
9667 dpyinfo = &one_mac_display_info;
9669 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9671 /* Put this display on the chain. */
9672 dpyinfo->next = x_display_list;
9673 x_display_list = dpyinfo;
9675 /* Put it on x_display_name_list. */
9676 x_display_name_list = Fcons (Fcons (display_name,
9677 Fcons (Qnil, dpyinfo->xrdb)),
9678 x_display_name_list);
9679 dpyinfo->name_list_element = XCAR (x_display_name_list);
9681 UNBLOCK_INPUT;
9683 return dpyinfo;
9685 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9687 void
9688 x_delete_display (dpyinfo)
9689 struct mac_display_info *dpyinfo;
9691 int i;
9693 /* Discard this display from x_display_name_list and x_display_list.
9694 We can't use Fdelq because that can quit. */
9695 if (! NILP (x_display_name_list)
9696 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9697 x_display_name_list = XCDR (x_display_name_list);
9698 else
9700 Lisp_Object tail;
9702 tail = x_display_name_list;
9703 while (CONSP (tail) && CONSP (XCDR (tail)))
9705 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9707 XSETCDR (tail, XCDR (XCDR (tail)));
9708 break;
9710 tail = XCDR (tail);
9714 if (x_display_list == dpyinfo)
9715 x_display_list = dpyinfo->next;
9716 else
9718 struct x_display_info *tail;
9720 for (tail = x_display_list; tail; tail = tail->next)
9721 if (tail->next == dpyinfo)
9722 tail->next = tail->next->next;
9725 /* Free the font names in the font table. */
9726 for (i = 0; i < dpyinfo->n_fonts; i++)
9727 if (dpyinfo->font_table[i].name)
9729 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9730 xfree (dpyinfo->font_table[i].full_name);
9731 xfree (dpyinfo->font_table[i].name);
9734 if (dpyinfo->font_table->font_encoder)
9735 xfree (dpyinfo->font_table->font_encoder);
9737 xfree (dpyinfo->font_table);
9738 xfree (dpyinfo->mac_id_name);
9740 if (x_display_list == 0)
9742 mac_clear_font_name_table ();
9743 bzero (dpyinfo, sizeof (*dpyinfo));
9748 #ifdef MAC_OSX
9749 void
9750 mac_check_bundle()
9752 extern int inhibit_window_system;
9753 extern int noninteractive;
9754 CFBundleRef appsBundle;
9755 pid_t child;
9757 /* No need to test if already -nw*/
9758 if (inhibit_window_system || noninteractive)
9759 return;
9761 appsBundle = CFBundleGetMainBundle();
9762 if (appsBundle != NULL)
9764 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9765 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9766 /* We found the bundle identifier, now we know we are valid. */
9767 if (res != NULL)
9769 CFRelease(res);
9770 return;
9773 /* MAC_TODO: Have this start the bundled executable */
9775 /* For now, prevent the fatal error by bringing it up in the terminal */
9776 inhibit_window_system = 1;
9779 void
9780 MakeMeTheFrontProcess ()
9782 ProcessSerialNumber psn;
9783 OSErr err;
9785 err = GetCurrentProcess (&psn);
9786 if (err == noErr)
9787 (void) SetFrontProcess (&psn);
9790 /***** Code to handle C-g testing *****/
9792 /* Contains the Mac modifier formed from quit_char */
9793 int mac_quit_char_modifiers = 0;
9794 int mac_quit_char_keycode;
9795 extern int quit_char;
9797 static void
9798 mac_determine_quit_char_modifiers()
9800 /* Todo: Determine modifiers from quit_char. */
9801 UInt32 qc_modifiers = ctrl_modifier;
9803 /* Map modifiers */
9804 mac_quit_char_modifiers = 0;
9805 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9806 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9807 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9808 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9811 static void
9812 init_quit_char_handler ()
9814 /* TODO: Let this support keys other the 'g' */
9815 mac_quit_char_keycode = 5;
9816 /* Look at <architecture/adb_kb_map.h> for details */
9817 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9819 mac_determine_quit_char_modifiers();
9822 static Boolean
9823 quit_char_comp (EventRef inEvent, void *inCompData)
9825 if (GetEventClass(inEvent) != kEventClassKeyboard)
9826 return false;
9827 if (GetEventKind(inEvent) != kEventRawKeyDown)
9828 return false;
9830 UInt32 keyCode;
9831 UInt32 keyModifiers;
9832 GetEventParameter(inEvent, kEventParamKeyCode,
9833 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9834 if (keyCode != mac_quit_char_keycode)
9835 return false;
9836 GetEventParameter(inEvent, kEventParamKeyModifiers,
9837 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9838 if (keyModifiers != mac_quit_char_modifiers)
9839 return false;
9841 return true;
9844 void
9845 mac_check_for_quit_char ()
9847 EventRef event;
9848 static EMACS_TIME last_check_time = { 0, 0 };
9849 static EMACS_TIME one_second = { 1, 0 };
9850 EMACS_TIME now, t;
9852 /* If windows are not initialized, return immediately (keep it bouncin'). */
9853 if (!mac_quit_char_modifiers)
9854 return;
9856 /* Don't check if last check is less than a second ago. */
9857 EMACS_GET_TIME (now);
9858 EMACS_SUB_TIME (t, now, last_check_time);
9859 if (EMACS_TIME_LT (t, one_second))
9860 return;
9861 last_check_time = now;
9863 /* Redetermine modifiers because they are based on lisp variables */
9864 mac_determine_quit_char_modifiers ();
9866 /* Fill the queue with events */
9867 BLOCK_INPUT;
9868 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9869 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9870 NULL);
9871 UNBLOCK_INPUT;
9872 if (event)
9874 struct input_event e;
9876 /* Use an input_event to emulate what the interrupt handler does. */
9877 EVENT_INIT (e);
9878 e.kind = ASCII_KEYSTROKE_EVENT;
9879 e.code = quit_char;
9880 e.arg = Qnil;
9881 e.modifiers = NULL;
9882 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9883 XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info));
9884 /* Remove event from queue to prevent looping. */
9885 RemoveEventFromQueue (GetMainEventQueue (), event);
9886 ReleaseEvent (event);
9887 kbd_buffer_store_event (&e);
9890 #endif /* MAC_OSX */
9892 static void
9893 init_menu_bar ()
9895 #ifdef MAC_OSX
9896 OSErr err;
9897 MenuRef menu;
9898 MenuItemIndex menu_index;
9900 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
9901 &menu, &menu_index);
9902 if (err == noErr)
9903 SetMenuItemCommandKey (menu, menu_index, false, 0);
9904 #if USE_CARBON_EVENTS
9905 EnableMenuCommand (NULL, kHICommandPreferences);
9906 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
9907 &menu, &menu_index);
9908 if (err == noErr)
9910 SetMenuItemCommandKey (menu, menu_index, false, 0);
9911 InsertMenuItemTextWithCFString (menu, NULL,
9912 0, kMenuItemAttrSeparator, 0);
9913 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
9914 0, 0, kHICommandAbout);
9916 #endif /* USE_CARBON_EVENTS */
9917 #else /* !MAC_OSX */
9918 #if USE_CARBON_EVENTS
9919 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
9920 #endif
9921 #endif
9925 /* Set up use of X before we make the first connection. */
9927 extern frame_parm_handler mac_frame_parm_handlers[];
9929 static struct redisplay_interface x_redisplay_interface =
9931 mac_frame_parm_handlers,
9932 x_produce_glyphs,
9933 x_write_glyphs,
9934 x_insert_glyphs,
9935 x_clear_end_of_line,
9936 x_scroll_run,
9937 x_after_update_window_line,
9938 x_update_window_begin,
9939 x_update_window_end,
9940 x_cursor_to,
9941 x_flush,
9942 0, /* flush_display_optional */
9943 x_clear_window_mouse_face,
9944 x_get_glyph_overhangs,
9945 x_fix_overlapping_area,
9946 x_draw_fringe_bitmap,
9947 0, /* define_fringe_bitmap */
9948 0, /* destroy_fringe_bitmap */
9949 mac_per_char_metric,
9950 mac_encode_char,
9951 mac_compute_glyph_string_overhangs,
9952 x_draw_glyph_string,
9953 mac_define_frame_cursor,
9954 mac_clear_frame_area,
9955 mac_draw_window_cursor,
9956 mac_draw_vertical_window_border,
9957 mac_shift_glyphs_for_insert
9960 void
9961 mac_initialize ()
9963 rif = &x_redisplay_interface;
9965 clear_frame_hook = x_clear_frame;
9966 ins_del_lines_hook = x_ins_del_lines;
9967 delete_glyphs_hook = x_delete_glyphs;
9968 ring_bell_hook = XTring_bell;
9969 reset_terminal_modes_hook = XTreset_terminal_modes;
9970 set_terminal_modes_hook = XTset_terminal_modes;
9971 update_begin_hook = x_update_begin;
9972 update_end_hook = x_update_end;
9973 set_terminal_window_hook = XTset_terminal_window;
9974 read_socket_hook = XTread_socket;
9975 frame_up_to_date_hook = XTframe_up_to_date;
9976 mouse_position_hook = XTmouse_position;
9977 frame_rehighlight_hook = XTframe_rehighlight;
9978 frame_raise_lower_hook = XTframe_raise_lower;
9980 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9981 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9982 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9983 judge_scroll_bars_hook = XTjudge_scroll_bars;
9985 scroll_region_ok = 1; /* we'll scroll partial frames */
9986 char_ins_del_ok = 1;
9987 line_ins_del_ok = 1; /* we'll just blt 'em */
9988 fast_clear_end_of_line = 1; /* X does this well */
9989 memory_below_frame = 0; /* we don't remember what scrolls
9990 off the bottom */
9991 baud_rate = 19200;
9993 last_tool_bar_item = -1;
9994 any_help_event_p = 0;
9996 /* Try to use interrupt input; if we can't, then start polling. */
9997 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9999 BLOCK_INPUT;
10001 #if TARGET_API_MAC_CARBON
10002 init_required_apple_events ();
10004 #if USE_CARBON_EVENTS
10005 #ifdef MAC_OSX
10006 init_service_handler ();
10008 init_quit_char_handler ();
10009 #endif /* MAC_OSX */
10011 init_command_handler ();
10013 init_menu_bar ();
10014 #endif /* USE_CARBON_EVENTS */
10016 #ifdef MAC_OSX
10017 if (!inhibit_window_system)
10018 MakeMeTheFrontProcess ();
10019 #endif
10020 #endif
10021 UNBLOCK_INPUT;
10025 void
10026 syms_of_macterm ()
10028 #if 0
10029 staticpro (&x_error_message_string);
10030 x_error_message_string = Qnil;
10031 #endif
10033 Qmodifier_value = intern ("modifier-value");
10034 Qalt = intern ("alt");
10035 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10036 Qhyper = intern ("hyper");
10037 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10038 Qsuper = intern ("super");
10039 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10041 Qapplication = intern ("application"); staticpro (&Qapplication);
10042 Qabout = intern ("about"); staticpro (&Qabout);
10044 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10045 Qpreferences = intern ("preferences"); staticpro (&Qpreferences);
10046 Qservices = intern ("services"); staticpro (&Qservices);
10047 Qpaste = intern ("paste"); staticpro (&Qpaste);
10048 Qperform = intern ("perform"); staticpro (&Qperform);
10049 #endif
10051 #ifdef MAC_OSX
10052 Fprovide (intern ("mac-carbon"), Qnil);
10053 #endif
10055 staticpro (&Qreverse);
10056 Qreverse = intern ("reverse");
10058 staticpro (&x_display_name_list);
10059 x_display_name_list = Qnil;
10061 staticpro (&last_mouse_scroll_bar);
10062 last_mouse_scroll_bar = Qnil;
10064 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
10065 staticpro (&Qmac_ready_for_drag_n_drop);
10067 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10068 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
10069 #ifdef USE_TOOLKIT_SCROLL_BARS
10070 Vx_toolkit_scroll_bars = Qt;
10071 #else
10072 Vx_toolkit_scroll_bars = Qnil;
10073 #endif
10075 staticpro (&last_mouse_motion_frame);
10076 last_mouse_motion_frame = Qnil;
10078 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
10079 doc: /* Non-nil means that the command key is used as the Emacs meta key.
10080 Otherwise the option key is used. */);
10081 Vmac_command_key_is_meta = Qt;
10083 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
10084 doc: /* Modifier to use for the Mac alt/option key. The value can
10085 be alt, hyper, or super for the respective modifier. If the value is
10086 nil then the key will act as the normal Mac option modifier. */);
10087 Vmac_option_modifier = Qnil;
10089 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
10090 doc: /* Non-nil means that the control and meta keys are reversed. This is
10091 useful for non-standard keyboard layouts. */);
10092 Vmac_reverse_ctrl_meta = Qnil;
10094 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10095 &Vmac_emulate_three_button_mouse,
10096 doc: /* t means that when the option-key is held down while pressing the
10097 mouse button, the click will register as mouse-2 and while the
10098 command-key is held down, the click will register as mouse-3.
10099 'reverse means that the option-key will register for mouse-3
10100 and the command-key will register for mouse-2. nil means that
10101 no emulation should be done and the modifiers should be placed
10102 on the mouse-1 event. */);
10103 Vmac_emulate_three_button_mouse = Qnil;
10105 #if USE_CARBON_EVENTS
10106 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
10107 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
10108 the right click will be mouse-3.
10109 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10110 Vmac_wheel_button_is_mouse_2 = Qt;
10112 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
10113 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10114 Toolbox for processing before Emacs sees it. */);
10115 Vmac_pass_command_to_system = Qt;
10117 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
10118 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10119 Toolbox for processing before Emacs sees it. */);
10120 Vmac_pass_control_to_system = Qt;
10122 #endif
10124 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
10125 doc: /* If non-nil, allow anti-aliasing.
10126 The text will be rendered using Core Graphics text rendering which
10127 may anti-alias the text. */);
10128 Vmac_use_core_graphics = Qnil;
10130 /* Register an entry for `mac-roman' so that it can be used when
10131 creating the terminal frame on Mac OS 9 before loading
10132 term/mac-win.elc. */
10133 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
10134 doc: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10135 Each entry should be of the form:
10137 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10139 where CHARSET-NAME is a string used in font names to identify the
10140 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10141 is a coding system corresponding to TEXT-ENCODING. */);
10142 Vmac_charset_info_alist =
10143 Fcons (list3 (build_string ("mac-roman"),
10144 make_number (smRoman), Qnil), Qnil);
10147 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10148 (do not change this comment) */