(latexenc-find-file-coding-system): Don't inherit the EOL part of the
[emacs.git] / src / macterm.c
blob6ebaa39437bf7b6a64cfc2bd6d79284ae4d61ddf
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., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.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"
65 #include "atimer.h"
66 #include "keymap.h"
68 #include <ctype.h>
69 #include <errno.h>
70 #include <setjmp.h>
71 #include <sys/stat.h>
72 #include <sys/param.h>
74 #include "keyboard.h"
75 #include "frame.h"
76 #include "dispextern.h"
77 #include "fontset.h"
78 #include "termhooks.h"
79 #include "termopts.h"
80 #include "termchar.h"
81 #include "gnu.h"
82 #include "disptab.h"
83 #include "buffer.h"
84 #include "window.h"
85 #include "intervals.h"
86 #include "composite.h"
87 #include "coding.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)
98 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
101 /* Non-nil means Emacs uses toolkit scroll bars. */
103 Lisp_Object Vx_toolkit_scroll_bars;
105 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
106 Lisp_Object Vmac_use_core_graphics;
109 /* Non-zero means that a HELP_EVENT has been generated since Emacs
110 start. */
112 static int any_help_event_p;
114 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
115 static Lisp_Object last_window;
117 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
119 int x_use_underline_position_properties;
121 /* Non-zero means draw block and hollow cursor as wide as the glyph
122 under it. For example, if a block cursor is over a tab, it will be
123 drawn as wide as that tab on the display. */
126 /* This is a chain of structures for all the X displays currently in
127 use. */
129 struct x_display_info *x_display_list;
131 /* This is a list of cons cells, each of the form (NAME
132 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
133 x_display_list and in the same order. NAME is the name of the
134 frame. FONT-LIST-CACHE records previous values returned by
135 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
136 equivalent, which is implemented with a Lisp object, for the
137 display. */
139 Lisp_Object x_display_name_list;
141 /* This is display since Mac does not support multiple ones. */
142 struct mac_display_info one_mac_display_info;
144 /* Frame being updated by update_frame. This is declared in term.c.
145 This is set by update_begin and looked at by all the XT functions.
146 It is zero while not inside an update. In that case, the XT
147 functions assume that `selected_frame' is the frame to apply to. */
149 extern struct frame *updating_frame;
151 extern int waiting_for_input;
153 /* This is a frame waiting to be auto-raised, within XTread_socket. */
155 struct frame *pending_autoraise_frame;
157 /* Mouse movement.
159 Formerly, we used PointerMotionHintMask (in standard_event_mask)
160 so that we would have to call XQueryPointer after each MotionNotify
161 event to ask for another such event. However, this made mouse tracking
162 slow, and there was a bug that made it eventually stop.
164 Simply asking for MotionNotify all the time seems to work better.
166 In order to avoid asking for motion events and then throwing most
167 of them away or busy-polling the server for mouse positions, we ask
168 the server for pointer motion hints. This means that we get only
169 one event per group of mouse movements. "Groups" are delimited by
170 other kinds of events (focus changes and button clicks, for
171 example), or by XQueryPointer calls; when one of these happens, we
172 get another MotionNotify event the next time the mouse moves. This
173 is at least as efficient as getting motion events when mouse
174 tracking is on, and I suspect only negligibly worse when tracking
175 is off. */
177 /* Where the mouse was last time we reported a mouse event. */
179 static Rect last_mouse_glyph;
180 static Lisp_Object last_mouse_press_frame;
182 /* The scroll bar in which the last X motion event occurred.
184 If the last X motion event occurred in a scroll bar, we set this so
185 XTmouse_position can know whether to report a scroll bar motion or
186 an ordinary motion.
188 If the last X motion event didn't occur in a scroll bar, we set
189 this to Qnil, to tell XTmouse_position to return an ordinary motion
190 event. */
192 static Lisp_Object last_mouse_scroll_bar;
194 /* This is a hack. We would really prefer that XTmouse_position would
195 return the time associated with the position it returns, but there
196 doesn't seem to be any way to wrest the time-stamp from the server
197 along with the position query. So, we just keep track of the time
198 of the last movement we received, and return that in hopes that
199 it's somewhat accurate. */
201 static Time last_mouse_movement_time;
203 struct scroll_bar *tracked_scroll_bar = NULL;
205 /* Incremented by XTread_socket whenever it really tries to read
206 events. */
208 #ifdef __STDC__
209 static int volatile input_signal_count;
210 #else
211 static int input_signal_count;
212 #endif
214 /* Used locally within XTread_socket. */
216 static int x_noop_count;
218 /* Initial values of argv and argc. */
220 extern char **initial_argv;
221 extern int initial_argc;
223 extern Lisp_Object Vcommand_line_args, Vsystem_name;
225 /* Tells if a window manager is present or not. */
227 extern Lisp_Object Vx_no_window_manager;
229 extern int errno;
231 /* A mask of extra modifier bits to put into every keyboard char. */
233 extern int extra_keyboard_modifiers;
235 /* The keysyms to use for the various modifiers. */
237 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
239 static Lisp_Object Qvendor_specific_keysyms;
241 #if 0
242 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
243 #endif
245 extern int inhibit_window_system;
247 #if __MRC__ && !TARGET_API_MAC_CARBON
248 QDGlobals qd; /* QuickDraw global information structure. */
249 #endif
252 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
253 struct mac_display_info *mac_display_info_for_display (Display *);
254 static void x_update_window_end P_ ((struct window *, int, int));
255 static int x_io_error_quitter P_ ((Display *));
256 int x_catch_errors P_ ((Display *));
257 void x_uncatch_errors P_ ((Display *, int));
258 void x_lower_frame P_ ((struct frame *));
259 void x_scroll_bar_clear P_ ((struct frame *));
260 int x_had_errors_p P_ ((Display *));
261 void x_wm_set_size_hint P_ ((struct frame *, long, int));
262 void x_raise_frame P_ ((struct frame *));
263 void x_set_window_size P_ ((struct frame *, int, int, int));
264 void x_wm_set_window_state P_ ((struct frame *, int));
265 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
266 void mac_initialize P_ ((void));
267 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
268 static int x_compute_min_glyph_bounds P_ ((struct frame *));
269 static void x_update_end P_ ((struct frame *));
270 static void XTframe_up_to_date P_ ((struct frame *));
271 static void XTset_terminal_modes P_ ((void));
272 static void XTreset_terminal_modes P_ ((void));
273 static void x_clear_frame P_ ((void));
274 static void frame_highlight P_ ((struct frame *));
275 static void frame_unhighlight P_ ((struct frame *));
276 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
277 static void mac_focus_changed P_ ((int, struct mac_display_info *,
278 struct frame *, struct input_event *));
279 static void x_detect_focus_change P_ ((struct mac_display_info *,
280 EventRecord *, struct input_event *));
281 static void XTframe_rehighlight P_ ((struct frame *));
282 static void x_frame_rehighlight P_ ((struct x_display_info *));
283 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
284 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
285 enum text_cursor_kinds));
287 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
288 static void x_flush P_ ((struct frame *f));
289 static void x_update_begin P_ ((struct frame *));
290 static void x_update_window_begin P_ ((struct window *));
291 static void x_after_update_window_line P_ ((struct glyph_row *));
293 static int is_emacs_window (WindowPtr);
295 int x_bitmap_icon (struct frame *, Lisp_Object);
296 void x_make_frame_visible (struct frame *);
298 extern void window_scroll (Lisp_Object, int, int, int);
300 /* Defined in macmenu.h. */
301 extern void menubar_selection_callback (FRAME_PTR, int);
302 extern void set_frame_menubar (FRAME_PTR, int, int);
304 /* X display function emulation */
306 void
307 XFreePixmap (display, pixmap)
308 Display *display; /* not used */
309 Pixmap pixmap;
311 DisposeGWorld (pixmap);
315 /* Set foreground color for subsequent QuickDraw commands. Assume
316 graphic port has already been set. */
318 static void
319 mac_set_forecolor (unsigned long color)
321 RGBColor fg_color;
323 fg_color.red = RED16_FROM_ULONG (color);
324 fg_color.green = GREEN16_FROM_ULONG (color);
325 fg_color.blue = BLUE16_FROM_ULONG (color);
327 RGBForeColor (&fg_color);
331 /* Set background color for subsequent QuickDraw commands. Assume
332 graphic port has already been set. */
334 static void
335 mac_set_backcolor (unsigned long color)
337 RGBColor bg_color;
339 bg_color.red = RED16_FROM_ULONG (color);
340 bg_color.green = GREEN16_FROM_ULONG (color);
341 bg_color.blue = BLUE16_FROM_ULONG (color);
343 RGBBackColor (&bg_color);
346 /* Set foreground and background color for subsequent QuickDraw
347 commands. Assume that the graphic port has already been set. */
349 static void
350 mac_set_colors (gc, bg_save)
351 GC gc;
352 RGBColor *bg_save;
354 if (bg_save)
355 GetBackColor (bg_save);
356 mac_set_forecolor (gc->foreground);
357 mac_set_backcolor (gc->background);
360 /* Mac version of XDrawLine. */
362 static void
363 XDrawLine (display, w, gc, x1, y1, x2, y2)
364 Display *display;
365 WindowPtr w;
366 GC gc;
367 int x1, y1, x2, y2;
369 RGBColor old_bg;
371 SetPortWindowPort (w);
373 mac_set_colors (gc, &old_bg);
375 MoveTo (x1, y1);
376 LineTo (x2, y2);
378 RGBBackColor (&old_bg);
381 void
382 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
383 Display *display;
384 Pixmap p;
385 GC gc;
386 int x1, y1, x2, y2;
388 CGrafPtr old_port;
389 GDHandle old_gdh;
391 GetGWorld (&old_port, &old_gdh);
392 SetGWorld (p, NULL);
394 mac_set_colors (gc, NULL);
396 LockPixels (GetGWorldPixMap (p));
397 MoveTo (x1, y1);
398 LineTo (x2, y2);
399 UnlockPixels (GetGWorldPixMap (p));
401 SetGWorld (old_port, old_gdh);
404 /* Mac version of XClearArea. */
406 void
407 XClearArea (display, w, x, y, width, height, exposures)
408 Display *display;
409 WindowPtr w;
410 int x, y;
411 unsigned int width, height;
412 int exposures;
414 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
415 Rect r;
416 XGCValues xgc;
417 RGBColor old_bg;
419 xgc.foreground = mwp->x_compatible.foreground_pixel;
420 xgc.background = mwp->x_compatible.background_pixel;
422 SetPortWindowPort (w);
424 mac_set_colors (&xgc, &old_bg);
425 SetRect (&r, x, y, x + width, y + height);
427 EraseRect (&r);
429 RGBBackColor (&old_bg);
432 /* Mac version of XClearWindow. */
434 static void
435 XClearWindow (display, w)
436 Display *display;
437 WindowPtr w;
439 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
440 XGCValues xgc;
442 xgc.foreground = mwp->x_compatible.foreground_pixel;
443 xgc.background = mwp->x_compatible.background_pixel;
445 SetPortWindowPort (w);
447 mac_set_colors (&xgc, NULL);
449 #if TARGET_API_MAC_CARBON
451 Rect r;
453 GetWindowPortBounds (w, &r);
454 EraseRect (&r);
456 #else /* not TARGET_API_MAC_CARBON */
457 EraseRect (&(w->portRect));
458 #endif /* not TARGET_API_MAC_CARBON */
462 /* Mac replacement for XCopyArea. */
464 static void
465 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
466 Display *display;
467 WindowPtr w;
468 GC gc;
469 int x, y, width, height;
470 unsigned short *bits;
471 int overlay_p;
473 BitMap bitmap;
474 Rect r;
475 RGBColor old_bg;
477 bitmap.rowBytes = sizeof(unsigned short);
478 bitmap.baseAddr = (char *)bits;
479 SetRect (&(bitmap.bounds), 0, 0, width, height);
481 SetPortWindowPort (w);
483 mac_set_colors (gc, &old_bg);
484 SetRect (&r, x, y, x + width, y + height);
486 #if TARGET_API_MAC_CARBON
487 LockPortBits (GetWindowPort (w));
488 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
489 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
490 UnlockPortBits (GetWindowPort (w));
491 #else /* not TARGET_API_MAC_CARBON */
492 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
493 overlay_p ? srcOr : srcCopy, 0);
494 #endif /* not TARGET_API_MAC_CARBON */
496 RGBBackColor (&old_bg);
500 /* Mac replacement for XSetClipRectangles. */
502 static void
503 mac_set_clip_rectangle (display, w, r)
504 Display *display;
505 WindowPtr w;
506 Rect *r;
508 SetPortWindowPort (w);
510 ClipRect (r);
514 /* Mac replacement for XSetClipMask. */
516 static void
517 mac_reset_clipping (display, w)
518 Display *display;
519 WindowPtr w;
521 Rect r;
523 SetPortWindowPort (w);
525 SetRect (&r, -32767, -32767, 32767, 32767);
526 ClipRect (&r);
530 /* Mac replacement for XCreateBitmapFromBitmapData. */
532 static void
533 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
534 BitMap *bitmap;
535 char *bits;
536 int w, h;
538 static unsigned char swap_nibble[16]
539 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
540 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
541 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
542 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
543 int i, j, w1;
544 char *p;
546 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
547 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
548 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
549 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
550 for (i = 0; i < h; i++)
552 p = bitmap->baseAddr + i * bitmap->rowBytes;
553 for (j = 0; j < w1; j++)
555 /* Bitswap XBM bytes to match how Mac does things. */
556 unsigned char c = *bits++;
557 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
558 | (swap_nibble[(c>>4) & 0xf]));;
562 SetRect (&(bitmap->bounds), 0, 0, w, h);
566 static void
567 mac_free_bitmap (bitmap)
568 BitMap *bitmap;
570 xfree (bitmap->baseAddr);
574 Pixmap
575 XCreatePixmap (display, w, width, height, depth)
576 Display *display; /* not used */
577 WindowPtr w;
578 unsigned int width, height;
579 unsigned int depth;
581 Pixmap pixmap;
582 Rect r;
583 QDErr err;
585 SetPortWindowPort (w);
587 SetRect (&r, 0, 0, width, height);
588 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
589 if (err != noErr)
590 return NULL;
591 return pixmap;
595 Pixmap
596 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
597 Display *display; /* not used */
598 WindowPtr w;
599 char *data;
600 unsigned int width, height;
601 unsigned long fg, bg;
602 unsigned int depth; /* not used */
604 Pixmap pixmap;
605 BitMap bitmap;
606 CGrafPtr old_port;
607 GDHandle old_gdh;
609 pixmap = XCreatePixmap (display, w, width, height, depth);
610 if (pixmap == NULL)
611 return NULL;
613 GetGWorld (&old_port, &old_gdh);
614 SetGWorld (pixmap, NULL);
615 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
616 mac_set_forecolor (fg);
617 mac_set_backcolor (bg);
618 LockPixels (GetGWorldPixMap (pixmap));
619 #if TARGET_API_MAC_CARBON
620 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
621 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
622 #else /* not TARGET_API_MAC_CARBON */
623 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
624 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
625 #endif /* not TARGET_API_MAC_CARBON */
626 UnlockPixels (GetGWorldPixMap (pixmap));
627 SetGWorld (old_port, old_gdh);
628 mac_free_bitmap (&bitmap);
630 return pixmap;
634 /* Mac replacement for XFillRectangle. */
636 static void
637 XFillRectangle (display, w, gc, x, y, width, height)
638 Display *display;
639 WindowPtr w;
640 GC gc;
641 int x, y;
642 unsigned int width, height;
644 Rect r;
645 RGBColor old_bg;
647 SetPortWindowPort (w);
649 mac_set_colors (gc, &old_bg);
650 SetRect (&r, x, y, x + width, y + height);
652 PaintRect (&r); /* using foreground color of gc */
654 RGBBackColor (&old_bg);
658 #if 0 /* TODO: figure out if we need to do this on Mac. */
659 static void
660 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
661 Display *display;
662 Pixmap p;
663 GC gc;
664 int x, y;
665 unsigned int width, height;
667 CGrafPtr old_port;
668 GDHandle old_gdh;
669 Rect r;
671 GetGWorld (&old_port, &old_gdh);
672 SetGWorld (p, NULL);
673 mac_set_colors (gc, NULL);
674 SetRect (&r, x, y, x + width, y + height);
676 LockPixels (GetGWorldPixMap (p));
677 PaintRect (&r); /* using foreground color of gc */
678 UnlockPixels (GetGWorldPixMap (p));
680 SetGWorld (old_port, old_gdh);
682 #endif
685 /* Mac replacement for XDrawRectangle: dest is a window. */
687 static void
688 mac_draw_rectangle (display, w, gc, x, y, width, height)
689 Display *display;
690 WindowPtr w;
691 GC gc;
692 int x, y;
693 unsigned int width, height;
695 Rect r;
696 RGBColor old_bg;
698 SetPortWindowPort (w);
700 mac_set_colors (gc, &old_bg);
701 SetRect (&r, x, y, x + width + 1, y + height + 1);
703 FrameRect (&r); /* using foreground color of gc */
705 RGBBackColor (&old_bg);
709 #if 0 /* TODO: figure out if we need to do this on Mac. */
710 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
712 static void
713 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
714 Display *display;
715 Pixmap p;
716 GC gc;
717 int x, y;
718 unsigned int width, height;
720 CGrafPtr old_port;
721 GDHandle old_gdh;
722 Rect r;
724 GetGWorld (&old_port, &old_gdh);
725 SetGWorld (p, NULL);
726 mac_set_colors (gc, NULL);
727 SetRect (&r, x, y, x + width + 1, y + height + 1);
729 LockPixels (GetGWorldPixMap (p));
730 FrameRect (&r); /* using foreground color of gc */
731 UnlockPixels (GetGWorldPixMap (p));
733 SetGWorld (old_port, old_gdh);
735 #endif
738 static void
739 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
740 bytes_per_char)
741 Display *display;
742 WindowPtr w;
743 GC gc;
744 int x, y;
745 char *buf;
746 int nchars, mode, bytes_per_char;
748 RGBColor old_bg;
750 SetPortWindowPort (w);
751 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
752 UInt32 textFlags, savedFlags;
753 if (!NILP(Vmac_use_core_graphics)) {
754 textFlags = kQDUseCGTextRendering;
755 savedFlags = SwapQDTextFlags(textFlags);
757 #endif
759 mac_set_colors (gc, &old_bg);
761 TextFont (gc->font->mac_fontnum);
762 TextSize (gc->font->mac_fontsize);
763 TextFace (gc->font->mac_fontface);
764 TextMode (mode);
766 MoveTo (x, y);
767 DrawText (buf, 0, nchars * bytes_per_char);
769 RGBBackColor (&old_bg);
770 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
771 if (!NILP(Vmac_use_core_graphics))
772 SwapQDTextFlags(savedFlags);
773 #endif
777 /* Mac replacement for XDrawString. */
779 static void
780 XDrawString (display, w, gc, x, y, buf, nchars)
781 Display *display;
782 WindowPtr w;
783 GC gc;
784 int x, y;
785 char *buf;
786 int nchars;
788 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
792 /* Mac replacement for XDrawString16. */
794 static void
795 XDrawString16 (display, w, gc, x, y, buf, nchars)
796 Display *display;
797 WindowPtr w;
798 GC gc;
799 int x, y;
800 XChar2b *buf;
801 int nchars;
803 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
808 /* Mac replacement for XDrawImageString. */
810 static void
811 XDrawImageString (display, w, gc, x, y, buf, nchars)
812 Display *display;
813 WindowPtr w;
814 GC gc;
815 int x, y;
816 char *buf;
817 int nchars;
819 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
823 /* Mac replacement for XDrawString16. */
825 static void
826 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
827 Display *display;
828 WindowPtr w;
829 GC gc;
830 int x, y;
831 XChar2b *buf;
832 int nchars;
834 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
839 /* Mac replacement for XCopyArea: dest must be window. */
841 static void
842 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
843 dest_y)
844 Display *display;
845 Pixmap src;
846 WindowPtr dest;
847 GC gc;
848 int src_x, src_y;
849 unsigned int width, height;
850 int dest_x, dest_y;
852 Rect src_r, dest_r;
854 SetPortWindowPort (dest);
856 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
857 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
859 ForeColor (blackColor);
860 BackColor (whiteColor);
862 LockPixels (GetGWorldPixMap (src));
863 #if TARGET_API_MAC_CARBON
864 LockPortBits (GetWindowPort (dest));
865 CopyBits (GetPortBitMapForCopyBits (src),
866 GetPortBitMapForCopyBits (GetWindowPort (dest)),
867 &src_r, &dest_r, srcCopy, 0);
868 UnlockPortBits (GetWindowPort (dest));
869 #else /* not TARGET_API_MAC_CARBON */
870 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
871 &src_r, &dest_r, srcCopy, 0);
872 #endif /* not TARGET_API_MAC_CARBON */
873 UnlockPixels (GetGWorldPixMap (src));
877 static void
878 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
879 width, height, dest_x, dest_y)
880 Display *display;
881 Pixmap src, mask;
882 WindowPtr dest;
883 GC gc;
884 int src_x, src_y;
885 unsigned int width, height;
886 int dest_x, dest_y;
888 Rect src_r, dest_r;
890 SetPortWindowPort (dest);
892 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
893 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
895 ForeColor (blackColor);
896 BackColor (whiteColor);
898 LockPixels (GetGWorldPixMap (src));
899 LockPixels (GetGWorldPixMap (mask));
900 #if TARGET_API_MAC_CARBON
901 LockPortBits (GetWindowPort (dest));
902 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
903 GetPortBitMapForCopyBits (GetWindowPort (dest)),
904 &src_r, &src_r, &dest_r);
905 UnlockPortBits (GetWindowPort (dest));
906 #else /* not TARGET_API_MAC_CARBON */
907 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
908 &(dest->portBits), &src_r, &src_r, &dest_r);
909 #endif /* not TARGET_API_MAC_CARBON */
910 UnlockPixels (GetGWorldPixMap (mask));
911 UnlockPixels (GetGWorldPixMap (src));
915 #if 0
916 /* Convert a pair of local coordinates to global (screen) coordinates.
917 Assume graphic port has been properly set. */
918 static void
919 local_to_global_coord (short *h, short *v)
921 Point p;
923 p.h = *h;
924 p.v = *v;
926 LocalToGlobal (&p);
928 *h = p.h;
929 *v = p.v;
931 #endif
933 /* Mac replacement for XCopyArea: used only for scrolling. */
935 static void
936 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
937 Display *display;
938 WindowPtr w;
939 GC gc;
940 int src_x, src_y;
941 unsigned int width, height;
942 int dest_x, dest_y;
944 #if TARGET_API_MAC_CARBON
945 Rect src_r;
946 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
948 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
949 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
950 kScrollWindowNoOptions, dummy);
951 DisposeRgn (dummy);
952 #else /* not TARGET_API_MAC_CARBON */
953 Rect src_r, dest_r;
955 SetPort (w);
956 #if 0
957 mac_set_colors (gc, NULL);
958 #endif
960 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
961 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
963 #if 0
964 /* Need to use global coordinates and screenBits since src and dest
965 areas overlap in general. */
966 local_to_global_coord (&src_r.left, &src_r.top);
967 local_to_global_coord (&src_r.right, &src_r.bottom);
968 local_to_global_coord (&dest_r.left, &dest_r.top);
969 local_to_global_coord (&dest_r.right, &dest_r.bottom);
971 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
972 #else
973 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
974 color mapping in CopyBits. Otherwise, it will be slow. */
975 ForeColor (blackColor);
976 BackColor (whiteColor);
977 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
979 mac_set_colors (gc, NULL);
980 #endif
981 #endif /* not TARGET_API_MAC_CARBON */
985 #if 0 /* TODO: figure out if we need to do this on Mac. */
986 /* Mac replacement for XCopyArea: dest must be Pixmap. */
988 static void
989 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
990 dest_x, dest_y)
991 Display *display;
992 Pixmap src, dest;
993 GC gc;
994 int src_x, src_y;
995 unsigned int width, height;
996 int dest_x, dest_y;
998 CGrafPtr old_port;
999 GDHandle old_gdh;
1000 Rect src_r, dest_r;
1002 GetGWorld (&old_port, &old_gdh);
1003 SetGWorld (dest, NULL);
1004 ForeColor (blackColor);
1005 BackColor (whiteColor);
1007 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1008 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1010 LockPixels (GetGWorldPixMap (src));
1011 LockPixels (GetGWorldPixMap (dest));
1012 #if TARGET_API_MAC_CARBON
1013 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
1014 &src_r, &dest_r, srcCopy, 0);
1015 #else /* not TARGET_API_MAC_CARBON */
1016 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
1017 &src_r, &dest_r, srcCopy, 0);
1018 #endif /* not TARGET_API_MAC_CARBON */
1019 UnlockPixels (GetGWorldPixMap (dest));
1020 UnlockPixels (GetGWorldPixMap (src));
1022 SetGWorld (old_port, old_gdh);
1026 static void
1027 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
1028 width, height, dest_x, dest_y)
1029 Display *display;
1030 Pixmap src, mask, dest;
1031 GC gc;
1032 int src_x, src_y;
1033 unsigned int width, height;
1034 int dest_x, dest_y;
1036 CGrafPtr old_port;
1037 GDHandle old_gdh;
1038 Rect src_r, dest_r;
1040 GetGWorld (&old_port, &old_gdh);
1041 SetGWorld (dest, NULL);
1042 ForeColor (blackColor);
1043 BackColor (whiteColor);
1045 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1046 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1048 LockPixels (GetGWorldPixMap (src));
1049 LockPixels (GetGWorldPixMap (mask));
1050 LockPixels (GetGWorldPixMap (dest));
1051 #if TARGET_API_MAC_CARBON
1052 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1053 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1054 #else /* not TARGET_API_MAC_CARBON */
1055 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1056 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1057 #endif /* not TARGET_API_MAC_CARBON */
1058 UnlockPixels (GetGWorldPixMap (dest));
1059 UnlockPixels (GetGWorldPixMap (mask));
1060 UnlockPixels (GetGWorldPixMap (src));
1062 SetGWorld (old_port, old_gdh);
1064 #endif
1067 /* Mac replacement for XChangeGC. */
1069 static void
1070 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1071 XGCValues *xgcv)
1073 if (mask & GCForeground)
1074 gc->foreground = xgcv->foreground;
1075 if (mask & GCBackground)
1076 gc->background = xgcv->background;
1077 if (mask & GCFont)
1078 gc->font = xgcv->font;
1082 /* Mac replacement for XCreateGC. */
1084 XGCValues *
1085 XCreateGC (void * ignore, Window window, unsigned long mask,
1086 XGCValues *xgcv)
1088 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1089 bzero (gc, sizeof (XGCValues));
1091 XChangeGC (ignore, gc, mask, xgcv);
1093 return gc;
1097 /* Used in xfaces.c. */
1099 void
1100 XFreeGC (display, gc)
1101 Display *display;
1102 GC gc;
1104 xfree (gc);
1108 /* Mac replacement for XGetGCValues. */
1110 static void
1111 XGetGCValues (void* ignore, XGCValues *gc,
1112 unsigned long mask, XGCValues *xgcv)
1114 XChangeGC (ignore, xgcv, mask, gc);
1118 /* Mac replacement for XSetForeground. */
1120 void
1121 XSetForeground (display, gc, color)
1122 Display *display;
1123 GC gc;
1124 unsigned long color;
1126 gc->foreground = color;
1130 /* Mac replacement for XSetBackground. */
1132 void
1133 XSetBackground (display, gc, color)
1134 Display *display;
1135 GC gc;
1136 unsigned long color;
1138 gc->background = color;
1142 /* Mac replacement for XSetWindowBackground. */
1144 void
1145 XSetWindowBackground (display, w, color)
1146 Display *display;
1147 WindowPtr w;
1148 unsigned long color;
1150 #if !TARGET_API_MAC_CARBON
1151 AuxWinHandle aw_handle;
1152 CTabHandle ctab_handle;
1153 ColorSpecPtr ct_table;
1154 short ct_size;
1155 #endif
1156 RGBColor bg_color;
1158 bg_color.red = RED16_FROM_ULONG (color);
1159 bg_color.green = GREEN16_FROM_ULONG (color);
1160 bg_color.blue = BLUE16_FROM_ULONG (color);
1162 #if TARGET_API_MAC_CARBON
1163 SetWindowContentColor (w, &bg_color);
1164 #else
1165 if (GetAuxWin (w, &aw_handle))
1167 ctab_handle = (*aw_handle)->awCTable;
1168 HandToHand ((Handle *) &ctab_handle);
1169 ct_table = (*ctab_handle)->ctTable;
1170 ct_size = (*ctab_handle)->ctSize;
1171 while (ct_size > -1)
1173 if (ct_table->value == 0)
1175 ct_table->rgb = bg_color;
1176 CTabChanged (ctab_handle);
1177 SetWinColor (w, (WCTabHandle) ctab_handle);
1179 ct_size--;
1182 #endif
1186 /* Mac replacement for XSetFont. */
1188 static void
1189 XSetFont (display, gc, font)
1190 Display *display;
1191 GC gc;
1192 XFontStruct *font;
1194 gc->font = font;
1198 /* x_sync is a no-op on Mac. */
1199 void
1200 x_sync (f)
1201 void *f;
1206 /* Flush display of frame F, or of all frames if F is null. */
1208 static void
1209 x_flush (f)
1210 struct frame *f;
1212 #if TARGET_API_MAC_CARBON
1213 BLOCK_INPUT;
1214 if (f)
1215 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1216 else
1217 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1218 UNBLOCK_INPUT;
1219 #endif
1223 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1224 Calls to XFlush should be unnecessary because the X output buffer
1225 is flushed automatically as needed by calls to XPending,
1226 XNextEvent, or XWindowEvent according to the XFlush man page.
1227 XTread_socket calls XPending. Removing XFlush improves
1228 performance. */
1230 #define XFlush(DISPLAY) (void) 0
1233 /* Return the struct mac_display_info corresponding to DPY. There's
1234 only one. */
1236 struct mac_display_info *
1237 mac_display_info_for_display (dpy)
1238 Display *dpy;
1240 return &one_mac_display_info;
1245 /***********************************************************************
1246 Starting and ending an update
1247 ***********************************************************************/
1249 /* Start an update of frame F. This function is installed as a hook
1250 for update_begin, i.e. it is called when update_begin is called.
1251 This function is called prior to calls to x_update_window_begin for
1252 each window being updated. */
1254 static void
1255 x_update_begin (f)
1256 struct frame *f;
1258 #if TARGET_API_MAC_CARBON
1259 /* During update of a frame, availability of input events is
1260 periodically checked with ReceiveNextEvent if
1261 redisplay-dont-pause is nil. That normally flushes window buffer
1262 changes for every check, and thus screen update looks waving even
1263 if no input is available. So we disable screen updates during
1264 update of a frame. */
1265 BLOCK_INPUT;
1266 DisableScreenUpdates ();
1267 UNBLOCK_INPUT;
1268 #endif
1272 /* Start update of window W. Set the global variable updated_window
1273 to the window being updated and set output_cursor to the cursor
1274 position of W. */
1276 static void
1277 x_update_window_begin (w)
1278 struct window *w;
1280 struct frame *f = XFRAME (WINDOW_FRAME (w));
1281 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1283 updated_window = w;
1284 set_output_cursor (&w->cursor);
1286 BLOCK_INPUT;
1288 if (f == display_info->mouse_face_mouse_frame)
1290 /* Don't do highlighting for mouse motion during the update. */
1291 display_info->mouse_face_defer = 1;
1293 /* If F needs to be redrawn, simply forget about any prior mouse
1294 highlighting. */
1295 if (FRAME_GARBAGED_P (f))
1296 display_info->mouse_face_window = Qnil;
1298 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1299 their mouse_face_p flag set, which means that they are always
1300 unequal to rows in a desired matrix which never have that
1301 flag set. So, rows containing mouse-face glyphs are never
1302 scrolled, and we don't have to switch the mouse highlight off
1303 here to prevent it from being scrolled. */
1305 /* Can we tell that this update does not affect the window
1306 where the mouse highlight is? If so, no need to turn off.
1307 Likewise, don't do anything if the frame is garbaged;
1308 in that case, the frame's current matrix that we would use
1309 is all wrong, and we will redisplay that line anyway. */
1310 if (!NILP (display_info->mouse_face_window)
1311 && w == XWINDOW (display_info->mouse_face_window))
1313 int i;
1315 for (i = 0; i < w->desired_matrix->nrows; ++i)
1316 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1317 break;
1319 if (i < w->desired_matrix->nrows)
1320 clear_mouse_face (display_info);
1322 #endif /* 0 */
1325 UNBLOCK_INPUT;
1329 /* Draw a vertical window border from (x,y0) to (x,y1) */
1331 static void
1332 mac_draw_vertical_window_border (w, x, y0, y1)
1333 struct window *w;
1334 int x, y0, y1;
1336 struct frame *f = XFRAME (WINDOW_FRAME (w));
1338 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1339 f->output_data.mac->normal_gc, x, y0, x, y1);
1343 /* End update of window W (which is equal to updated_window).
1345 Draw vertical borders between horizontally adjacent windows, and
1346 display W's cursor if CURSOR_ON_P is non-zero.
1348 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1349 glyphs in mouse-face were overwritten. In that case we have to
1350 make sure that the mouse-highlight is properly redrawn.
1352 W may be a menu bar pseudo-window in case we don't have X toolkit
1353 support. Such windows don't have a cursor, so don't display it
1354 here. */
1356 static void
1357 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1358 struct window *w;
1359 int cursor_on_p, mouse_face_overwritten_p;
1361 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1363 if (!w->pseudo_window_p)
1365 BLOCK_INPUT;
1367 if (cursor_on_p)
1368 display_and_set_cursor (w, 1, output_cursor.hpos,
1369 output_cursor.vpos,
1370 output_cursor.x, output_cursor.y);
1372 if (draw_window_fringes (w, 1))
1373 x_draw_vertical_border (w);
1375 UNBLOCK_INPUT;
1378 /* If a row with mouse-face was overwritten, arrange for
1379 XTframe_up_to_date to redisplay the mouse highlight. */
1380 if (mouse_face_overwritten_p)
1382 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1383 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1384 dpyinfo->mouse_face_window = Qnil;
1387 #if 0
1388 /* Unhide the caret. This won't actually show the cursor, unless it
1389 was visible before the corresponding call to HideCaret in
1390 x_update_window_begin. */
1391 if (w32_use_visible_system_caret)
1392 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1393 #endif
1395 updated_window = NULL;
1399 /* End update of frame F. This function is installed as a hook in
1400 update_end. */
1402 static void
1403 x_update_end (f)
1404 struct frame *f;
1406 /* Mouse highlight may be displayed again. */
1407 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1409 BLOCK_INPUT;
1410 #if TARGET_API_MAC_CARBON
1411 EnableScreenUpdates ();
1412 #endif
1413 XFlush (FRAME_MAC_DISPLAY (f));
1414 UNBLOCK_INPUT;
1418 /* This function is called from various places in xdisp.c whenever a
1419 complete update has been performed. The global variable
1420 updated_window is not available here. */
1422 static void
1423 XTframe_up_to_date (f)
1424 struct frame *f;
1426 if (FRAME_MAC_P (f))
1428 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1430 if (dpyinfo->mouse_face_deferred_gc
1431 || f == dpyinfo->mouse_face_mouse_frame)
1433 BLOCK_INPUT;
1434 if (dpyinfo->mouse_face_mouse_frame)
1435 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1436 dpyinfo->mouse_face_mouse_x,
1437 dpyinfo->mouse_face_mouse_y);
1438 dpyinfo->mouse_face_deferred_gc = 0;
1439 UNBLOCK_INPUT;
1445 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1446 arrow bitmaps, or clear the fringes if no bitmaps are required
1447 before DESIRED_ROW is made current. The window being updated is
1448 found in updated_window. This function is called from
1449 update_window_line only if it is known that there are differences
1450 between bitmaps to be drawn between current row and DESIRED_ROW. */
1452 static void
1453 x_after_update_window_line (desired_row)
1454 struct glyph_row *desired_row;
1456 struct window *w = updated_window;
1457 struct frame *f;
1458 int width, height;
1460 xassert (w);
1462 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1463 desired_row->redraw_fringe_bitmaps_p = 1;
1465 /* When a window has disappeared, make sure that no rest of
1466 full-width rows stays visible in the internal border. Could
1467 check here if updated_window is the leftmost/rightmost window,
1468 but I guess it's not worth doing since vertically split windows
1469 are almost never used, internal border is rarely set, and the
1470 overhead is very small. */
1471 if (windows_or_buffers_changed
1472 && desired_row->full_width_p
1473 && (f = XFRAME (w->frame),
1474 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1475 width != 0)
1476 && (height = desired_row->visible_height,
1477 height > 0))
1479 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1480 /* Internal border is drawn below the tool bar. */
1481 if (WINDOWP (f->tool_bar_window)
1482 && w == XWINDOW (f->tool_bar_window))
1483 y -= width;
1485 BLOCK_INPUT;
1487 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1488 0, y, width, height, 0);
1489 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1490 FRAME_PIXEL_WIDTH (f) - width, y,
1491 width, height, 0);
1493 UNBLOCK_INPUT;
1498 /* Draw the bitmap WHICH in one of the left or right fringes of
1499 window W. ROW is the glyph row for which to display the bitmap; it
1500 determines the vertical position at which the bitmap has to be
1501 drawn. */
1503 static void
1504 x_draw_fringe_bitmap (w, row, p)
1505 struct window *w;
1506 struct glyph_row *row;
1507 struct draw_fringe_bitmap_params *p;
1509 struct frame *f = XFRAME (WINDOW_FRAME (w));
1510 Display *display = FRAME_MAC_DISPLAY (f);
1511 WindowPtr window = FRAME_MAC_WINDOW (f);
1512 XGCValues gcv;
1513 GC gc = f->output_data.mac->normal_gc;
1514 struct face *face = p->face;
1515 int rowY;
1517 /* Must clip because of partially visible lines. */
1518 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1519 if (p->y < rowY)
1521 /* Adjust position of "bottom aligned" bitmap on partially
1522 visible last row. */
1523 int oldY = row->y;
1524 int oldVH = row->visible_height;
1525 row->visible_height = p->h;
1526 row->y -= rowY - p->y;
1527 x_clip_to_row (w, row, -1, gc);
1528 row->y = oldY;
1529 row->visible_height = oldVH;
1531 else
1532 x_clip_to_row (w, row, -1, gc);
1534 if (p->bx >= 0 && !p->overlay_p)
1536 XGCValues gcv;
1537 gcv.foreground = face->background;
1539 #if 0 /* MAC_TODO: stipple */
1540 /* In case the same realized face is used for fringes and
1541 for something displayed in the text (e.g. face `region' on
1542 mono-displays, the fill style may have been changed to
1543 FillSolid in x_draw_glyph_string_background. */
1544 if (face->stipple)
1545 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1546 else
1547 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1548 #endif
1550 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1551 &gcv,
1552 p->bx, p->by, p->nx, p->ny);
1554 #if 0 /* MAC_TODO: stipple */
1555 if (!face->stipple)
1556 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1557 #endif
1560 if (p->which)
1562 unsigned short *bits = p->bits + p->dh;
1564 gcv.foreground = (p->cursor_p
1565 ? (p->overlay_p ? face->background
1566 : f->output_data.mac->cursor_pixel)
1567 : face->foreground);
1568 gcv.background = face->background;
1570 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1571 p->wd, p->h, bits, p->overlay_p);
1574 mac_reset_clipping (display, window);
1578 /* This is called when starting Emacs and when restarting after
1579 suspend. When starting Emacs, no window is mapped. And nothing
1580 must be done to Emacs's own window if it is suspended (though that
1581 rarely happens). */
1583 static void
1584 XTset_terminal_modes ()
1588 /* This is called when exiting or suspending Emacs. Exiting will make
1589 the windows go away, and suspending requires no action. */
1591 static void
1592 XTreset_terminal_modes ()
1597 /***********************************************************************
1598 Display Iterator
1599 ***********************************************************************/
1601 /* Function prototypes of this page. */
1603 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1604 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1607 /* Return a pointer to per-char metric information in FONT of a
1608 character pointed by B which is a pointer to an XChar2b. */
1610 #define PER_CHAR_METRIC(font, b) \
1611 ((font)->per_char \
1612 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1613 + (((font)->min_byte1 || (font)->max_byte1) \
1614 ? (((b)->byte1 - (font)->min_byte1) \
1615 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1616 : 0)) \
1617 : &((font)->max_bounds))
1620 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1621 is not contained in the font. */
1623 static INLINE XCharStruct *
1624 x_per_char_metric (font, char2b)
1625 XFontStruct *font;
1626 XChar2b *char2b;
1628 /* The result metric information. */
1629 XCharStruct *pcm = NULL;
1631 xassert (font && char2b);
1633 if (font->per_char != NULL)
1635 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1637 /* min_char_or_byte2 specifies the linear character index
1638 corresponding to the first element of the per_char array,
1639 max_char_or_byte2 is the index of the last character. A
1640 character with non-zero CHAR2B->byte1 is not in the font.
1641 A character with byte2 less than min_char_or_byte2 or
1642 greater max_char_or_byte2 is not in the font. */
1643 if (char2b->byte1 == 0
1644 && char2b->byte2 >= font->min_char_or_byte2
1645 && char2b->byte2 <= font->max_char_or_byte2)
1646 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1648 else
1650 /* If either min_byte1 or max_byte1 are nonzero, both
1651 min_char_or_byte2 and max_char_or_byte2 are less than
1652 256, and the 2-byte character index values corresponding
1653 to the per_char array element N (counting from 0) are:
1655 byte1 = N/D + min_byte1
1656 byte2 = N\D + min_char_or_byte2
1658 where:
1660 D = max_char_or_byte2 - min_char_or_byte2 + 1
1661 / = integer division
1662 \ = integer modulus */
1663 if (char2b->byte1 >= font->min_byte1
1664 && char2b->byte1 <= font->max_byte1
1665 && char2b->byte2 >= font->min_char_or_byte2
1666 && char2b->byte2 <= font->max_char_or_byte2)
1668 pcm = (font->per_char
1669 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1670 * (char2b->byte1 - font->min_byte1))
1671 + (char2b->byte2 - font->min_char_or_byte2));
1675 else
1677 /* If the per_char pointer is null, all glyphs between the first
1678 and last character indexes inclusive have the same
1679 information, as given by both min_bounds and max_bounds. */
1680 if (char2b->byte2 >= font->min_char_or_byte2
1681 && char2b->byte2 <= font->max_char_or_byte2)
1682 pcm = &font->max_bounds;
1685 return ((pcm == NULL
1686 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1687 ? NULL : pcm);
1690 /* RIF:
1693 static XCharStruct *
1694 mac_per_char_metric (font, char2b, font_type)
1695 XFontStruct *font;
1696 XChar2b *char2b;
1697 int font_type;
1699 return x_per_char_metric (font, char2b);
1702 /* RIF:
1703 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1704 the two-byte form of C. Encoding is returned in *CHAR2B. */
1706 static int
1707 mac_encode_char (c, char2b, font_info, two_byte_p)
1708 int c;
1709 XChar2b *char2b;
1710 struct font_info *font_info;
1711 int *two_byte_p;
1713 int charset = CHAR_CHARSET (c);
1714 XFontStruct *font = font_info->font;
1716 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1717 This may be either a program in a special encoder language or a
1718 fixed encoding. */
1719 if (font_info->font_encoder)
1721 /* It's a program. */
1722 struct ccl_program *ccl = font_info->font_encoder;
1724 if (CHARSET_DIMENSION (charset) == 1)
1726 ccl->reg[0] = charset;
1727 ccl->reg[1] = char2b->byte2;
1729 else
1731 ccl->reg[0] = charset;
1732 ccl->reg[1] = char2b->byte1;
1733 ccl->reg[2] = char2b->byte2;
1736 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1738 /* We assume that MSBs are appropriately set/reset by CCL
1739 program. */
1740 if (font->max_byte1 == 0) /* 1-byte font */
1741 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1742 else
1743 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1745 else if (font_info->encoding[charset])
1747 /* Fixed encoding scheme. See fontset.h for the meaning of the
1748 encoding numbers. */
1749 int enc = font_info->encoding[charset];
1751 if ((enc == 1 || enc == 2)
1752 && CHARSET_DIMENSION (charset) == 2)
1753 char2b->byte1 |= 0x80;
1755 if (enc == 1 || enc == 3)
1756 char2b->byte2 |= 0x80;
1758 if (enc == 4)
1760 int sjis1, sjis2;
1762 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1763 char2b->byte1 = sjis1;
1764 char2b->byte2 = sjis2;
1768 if (two_byte_p)
1769 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1771 return FONT_TYPE_UNKNOWN;
1776 /***********************************************************************
1777 Glyph display
1778 ***********************************************************************/
1781 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1782 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1783 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1784 int));
1785 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1786 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1787 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1788 static void x_draw_glyph_string P_ ((struct glyph_string *));
1789 static void x_set_cursor_gc P_ ((struct glyph_string *));
1790 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1791 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1792 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1793 unsigned long *, double, int));*/
1794 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1795 double, int, unsigned long));
1796 static void x_setup_relief_colors P_ ((struct glyph_string *));
1797 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1798 static void x_draw_image_relief P_ ((struct glyph_string *));
1799 static void x_draw_image_foreground P_ ((struct glyph_string *));
1800 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1801 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1802 int, int, int));
1803 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1804 int, int, int, int, int, int,
1805 Rect *));
1806 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1807 int, int, int, Rect *));
1809 #if GLYPH_DEBUG
1810 static void x_check_font P_ ((struct frame *, XFontStruct *));
1811 #endif
1814 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1815 face. */
1817 static void
1818 x_set_cursor_gc (s)
1819 struct glyph_string *s;
1821 if (s->font == FRAME_FONT (s->f)
1822 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1823 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1824 && !s->cmp)
1825 s->gc = s->f->output_data.mac->cursor_gc;
1826 else
1828 /* Cursor on non-default face: must merge. */
1829 XGCValues xgcv;
1830 unsigned long mask;
1832 xgcv.background = s->f->output_data.mac->cursor_pixel;
1833 xgcv.foreground = s->face->background;
1835 /* If the glyph would be invisible, try a different foreground. */
1836 if (xgcv.foreground == xgcv.background)
1837 xgcv.foreground = s->face->foreground;
1838 if (xgcv.foreground == xgcv.background)
1839 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1840 if (xgcv.foreground == xgcv.background)
1841 xgcv.foreground = s->face->foreground;
1843 /* Make sure the cursor is distinct from text in this face. */
1844 if (xgcv.background == s->face->background
1845 && xgcv.foreground == s->face->foreground)
1847 xgcv.background = s->face->foreground;
1848 xgcv.foreground = s->face->background;
1851 IF_DEBUG (x_check_font (s->f, s->font));
1852 xgcv.font = s->font;
1853 mask = GCForeground | GCBackground | GCFont;
1855 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1856 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1857 mask, &xgcv);
1858 else
1859 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1860 = XCreateGC (s->display, s->window, mask, &xgcv);
1862 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1867 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1869 static void
1870 x_set_mouse_face_gc (s)
1871 struct glyph_string *s;
1873 int face_id;
1874 struct face *face;
1876 /* What face has to be used last for the mouse face? */
1877 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1878 face = FACE_FROM_ID (s->f, face_id);
1879 if (face == NULL)
1880 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1882 if (s->first_glyph->type == CHAR_GLYPH)
1883 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1884 else
1885 face_id = FACE_FOR_CHAR (s->f, face, 0);
1886 s->face = FACE_FROM_ID (s->f, face_id);
1887 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1889 /* If font in this face is same as S->font, use it. */
1890 if (s->font == s->face->font)
1891 s->gc = s->face->gc;
1892 else
1894 /* Otherwise construct scratch_cursor_gc with values from FACE
1895 but font FONT. */
1896 XGCValues xgcv;
1897 unsigned long mask;
1899 xgcv.background = s->face->background;
1900 xgcv.foreground = s->face->foreground;
1901 IF_DEBUG (x_check_font (s->f, s->font));
1902 xgcv.font = s->font;
1903 mask = GCForeground | GCBackground | GCFont;
1905 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1906 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1907 mask, &xgcv);
1908 else
1909 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1910 = XCreateGC (s->display, s->window, mask, &xgcv);
1912 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1915 xassert (s->gc != 0);
1919 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1920 Faces to use in the mode line have already been computed when the
1921 matrix was built, so there isn't much to do, here. */
1923 static INLINE void
1924 x_set_mode_line_face_gc (s)
1925 struct glyph_string *s;
1927 s->gc = s->face->gc;
1931 /* Set S->gc of glyph string S for drawing that glyph string. Set
1932 S->stippled_p to a non-zero value if the face of S has a stipple
1933 pattern. */
1935 static INLINE void
1936 x_set_glyph_string_gc (s)
1937 struct glyph_string *s;
1939 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1941 if (s->hl == DRAW_NORMAL_TEXT)
1943 s->gc = s->face->gc;
1944 s->stippled_p = s->face->stipple != 0;
1946 else if (s->hl == DRAW_INVERSE_VIDEO)
1948 x_set_mode_line_face_gc (s);
1949 s->stippled_p = s->face->stipple != 0;
1951 else if (s->hl == DRAW_CURSOR)
1953 x_set_cursor_gc (s);
1954 s->stippled_p = 0;
1956 else if (s->hl == DRAW_MOUSE_FACE)
1958 x_set_mouse_face_gc (s);
1959 s->stippled_p = s->face->stipple != 0;
1961 else if (s->hl == DRAW_IMAGE_RAISED
1962 || s->hl == DRAW_IMAGE_SUNKEN)
1964 s->gc = s->face->gc;
1965 s->stippled_p = s->face->stipple != 0;
1967 else
1969 s->gc = s->face->gc;
1970 s->stippled_p = s->face->stipple != 0;
1973 /* GC must have been set. */
1974 xassert (s->gc != 0);
1978 /* Set clipping for output of glyph string S. S may be part of a mode
1979 line or menu if we don't have X toolkit support. */
1981 static INLINE void
1982 x_set_glyph_string_clipping (s)
1983 struct glyph_string *s;
1985 Rect r;
1986 get_glyph_string_clip_rect (s, &r);
1987 mac_set_clip_rectangle (s->display, s->window, &r);
1991 /* RIF:
1992 Compute left and right overhang of glyph string S. If S is a glyph
1993 string for a composition, assume overhangs don't exist. */
1995 static void
1996 mac_compute_glyph_string_overhangs (s)
1997 struct glyph_string *s;
1999 Rect r;
2000 MacFontStruct *font = s->font;
2002 TextFont (font->mac_fontnum);
2003 TextSize (font->mac_fontsize);
2004 TextFace (font->mac_fontface);
2006 if (s->two_byte_p)
2007 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2008 else
2010 int i;
2011 char *buf = xmalloc (s->nchars);
2013 if (buf == NULL)
2014 SetRect (&r, 0, 0, 0, 0);
2015 else
2017 for (i = 0; i < s->nchars; ++i)
2018 buf[i] = s->char2b[i].byte2;
2019 QDTextBounds (s->nchars, buf, &r);
2020 xfree (buf);
2024 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2025 s->left_overhang = r.left < 0 ? -r.left : 0;
2029 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2031 static INLINE void
2032 x_clear_glyph_string_rect (s, x, y, w, h)
2033 struct glyph_string *s;
2034 int x, y, w, h;
2036 XGCValues xgcv;
2038 xgcv.foreground = s->gc->background;
2039 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
2043 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2044 on Mac OS X because:
2045 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2046 into an offscreen graphics world first. So performance gain
2047 cannot be expected.)
2048 - It lowers rendering quality.
2049 - Some fonts leave garbage on cursor movement. */
2051 /* Draw the background of glyph_string S. If S->background_filled_p
2052 is non-zero don't draw it. FORCE_P non-zero means draw the
2053 background even if it wouldn't be drawn normally. This is used
2054 when a string preceding S draws into the background of S, or S
2055 contains the first component of a composition. */
2057 static void
2058 x_draw_glyph_string_background (s, force_p)
2059 struct glyph_string *s;
2060 int force_p;
2062 /* Nothing to do if background has already been drawn or if it
2063 shouldn't be drawn in the first place. */
2064 if (!s->background_filled_p)
2066 int box_line_width = max (s->face->box_line_width, 0);
2068 #if 0 /* MAC_TODO: stipple */
2069 if (s->stippled_p)
2071 /* Fill background with a stipple pattern. */
2072 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2073 XFillRectangle (s->display, s->window, s->gc, s->x,
2074 s->y + box_line_width,
2075 s->background_width,
2076 s->height - 2 * box_line_width);
2077 XSetFillStyle (s->display, s->gc, FillSolid);
2078 s->background_filled_p = 1;
2080 else
2081 #endif
2082 #ifdef MAC_OS8
2083 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2084 || s->font_not_found_p
2085 || s->extends_to_end_of_line_p
2086 || force_p)
2087 #endif
2089 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2090 s->background_width,
2091 s->height - 2 * box_line_width);
2092 s->background_filled_p = 1;
2098 /* Draw the foreground of glyph string S. */
2100 static void
2101 x_draw_glyph_string_foreground (s)
2102 struct glyph_string *s;
2104 int i, x;
2106 /* If first glyph of S has a left box line, start drawing the text
2107 of S to the right of that box line. */
2108 if (s->face->box != FACE_NO_BOX
2109 && s->first_glyph->left_box_line_p)
2110 x = s->x + abs (s->face->box_line_width);
2111 else
2112 x = s->x;
2114 /* Draw characters of S as rectangles if S's font could not be
2115 loaded. */
2116 if (s->font_not_found_p)
2118 for (i = 0; i < s->nchars; ++i)
2120 struct glyph *g = s->first_glyph + i;
2121 mac_draw_rectangle (s->display, s->window,
2122 s->gc, x, s->y, g->pixel_width - 1,
2123 s->height - 1);
2124 x += g->pixel_width;
2127 else
2129 char *char1b = (char *) s->char2b;
2130 int boff = s->font_info->baseline_offset;
2132 if (s->font_info->vertical_centering)
2133 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2135 /* If we can use 8-bit functions, condense S->char2b. */
2136 if (!s->two_byte_p)
2137 for (i = 0; i < s->nchars; ++i)
2138 char1b[i] = s->char2b[i].byte2;
2140 #ifdef MAC_OS8
2141 /* Draw text with XDrawString if background has already been
2142 filled. Otherwise, use XDrawImageString. (Note that
2143 XDrawImageString is usually faster than XDrawString.) Always
2144 use XDrawImageString when drawing the cursor so that there is
2145 no chance that characters under a box cursor are invisible. */
2146 if (s->for_overlaps_p
2147 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2148 #endif
2150 /* Draw characters with 16-bit or 8-bit functions. */
2151 if (s->two_byte_p)
2152 XDrawString16 (s->display, s->window, s->gc, x,
2153 s->ybase - boff, s->char2b, s->nchars);
2154 else
2155 XDrawString (s->display, s->window, s->gc, x,
2156 s->ybase - boff, char1b, s->nchars);
2158 #ifdef MAC_OS8
2159 else
2161 if (s->two_byte_p)
2162 XDrawImageString16 (s->display, s->window, s->gc, x,
2163 s->ybase - boff, s->char2b, s->nchars);
2164 else
2165 XDrawImageString (s->display, s->window, s->gc, x,
2166 s->ybase - boff, char1b, s->nchars);
2168 #endif
2172 /* Draw the foreground of composite glyph string S. */
2174 static void
2175 x_draw_composite_glyph_string_foreground (s)
2176 struct glyph_string *s;
2178 int i, x;
2180 /* If first glyph of S has a left box line, start drawing the text
2181 of S to the right of that box line. */
2182 if (s->face->box != FACE_NO_BOX
2183 && s->first_glyph->left_box_line_p)
2184 x = s->x + abs (s->face->box_line_width);
2185 else
2186 x = s->x;
2188 /* S is a glyph string for a composition. S->gidx is the index of
2189 the first character drawn for glyphs of this composition.
2190 S->gidx == 0 means we are drawing the very first character of
2191 this composition. */
2193 /* Draw a rectangle for the composition if the font for the very
2194 first character of the composition could not be loaded. */
2195 if (s->font_not_found_p)
2197 if (s->gidx == 0)
2198 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2199 s->width - 1, s->height - 1);
2201 else
2203 for (i = 0; i < s->nchars; i++, ++s->gidx)
2204 XDrawString16 (s->display, s->window, s->gc,
2205 x + s->cmp->offsets[s->gidx * 2],
2206 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2207 s->char2b + i, 1);
2212 #ifdef USE_X_TOOLKIT
2214 static struct frame *x_frame_of_widget P_ ((Widget));
2217 /* Return the frame on which widget WIDGET is used.. Abort if frame
2218 cannot be determined. */
2220 static struct frame *
2221 x_frame_of_widget (widget)
2222 Widget widget;
2224 struct x_display_info *dpyinfo;
2225 Lisp_Object tail;
2226 struct frame *f;
2228 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2230 /* Find the top-level shell of the widget. Note that this function
2231 can be called when the widget is not yet realized, so XtWindow
2232 (widget) == 0. That's the reason we can't simply use
2233 x_any_window_to_frame. */
2234 while (!XtIsTopLevelShell (widget))
2235 widget = XtParent (widget);
2237 /* Look for a frame with that top-level widget. Allocate the color
2238 on that frame to get the right gamma correction value. */
2239 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2240 if (GC_FRAMEP (XCAR (tail))
2241 && (f = XFRAME (XCAR (tail)),
2242 (f->output_data.nothing != 1
2243 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2244 && f->output_data.x->widget == widget)
2245 return f;
2247 abort ();
2251 /* Allocate the color COLOR->pixel on the screen and display of
2252 widget WIDGET in colormap CMAP. If an exact match cannot be
2253 allocated, try the nearest color available. Value is non-zero
2254 if successful. This is called from lwlib. */
2257 x_alloc_nearest_color_for_widget (widget, cmap, color)
2258 Widget widget;
2259 Colormap cmap;
2260 XColor *color;
2262 struct frame *f = x_frame_of_widget (widget);
2263 return x_alloc_nearest_color (f, cmap, color);
2267 #endif /* USE_X_TOOLKIT */
2269 #if 0 /* MAC_TODO */
2271 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2272 CMAP. If an exact match can't be allocated, try the nearest color
2273 available. Value is non-zero if successful. Set *COLOR to the
2274 color allocated. */
2277 x_alloc_nearest_color (f, cmap, color)
2278 struct frame *f;
2279 Colormap cmap;
2280 XColor *color;
2282 Display *display = FRAME_X_DISPLAY (f);
2283 Screen *screen = FRAME_X_SCREEN (f);
2284 int rc;
2286 gamma_correct (f, color);
2287 rc = XAllocColor (display, cmap, color);
2288 if (rc == 0)
2290 /* If we got to this point, the colormap is full, so we're going
2291 to try to get the next closest color. The algorithm used is
2292 a least-squares matching, which is what X uses for closest
2293 color matching with StaticColor visuals. */
2294 int nearest, i;
2295 unsigned long nearest_delta = ~0;
2296 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2297 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2299 for (i = 0; i < ncells; ++i)
2300 cells[i].pixel = i;
2301 XQueryColors (display, cmap, cells, ncells);
2303 for (nearest = i = 0; i < ncells; ++i)
2305 long dred = (color->red >> 8) - (cells[i].red >> 8);
2306 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2307 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2308 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2310 if (delta < nearest_delta)
2312 nearest = i;
2313 nearest_delta = delta;
2317 color->red = cells[nearest].red;
2318 color->green = cells[nearest].green;
2319 color->blue = cells[nearest].blue;
2320 rc = XAllocColor (display, cmap, color);
2323 #ifdef DEBUG_X_COLORS
2324 if (rc)
2325 register_color (color->pixel);
2326 #endif /* DEBUG_X_COLORS */
2328 return rc;
2332 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2333 It's necessary to do this instead of just using PIXEL directly to
2334 get color reference counts right. */
2336 unsigned long
2337 x_copy_color (f, pixel)
2338 struct frame *f;
2339 unsigned long pixel;
2341 XColor color;
2343 color.pixel = pixel;
2344 BLOCK_INPUT;
2345 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2346 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2347 UNBLOCK_INPUT;
2348 #ifdef DEBUG_X_COLORS
2349 register_color (pixel);
2350 #endif
2351 return color.pixel;
2355 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2356 It's necessary to do this instead of just using PIXEL directly to
2357 get color reference counts right. */
2359 unsigned long
2360 x_copy_dpy_color (dpy, cmap, pixel)
2361 Display *dpy;
2362 Colormap cmap;
2363 unsigned long pixel;
2365 XColor color;
2367 color.pixel = pixel;
2368 BLOCK_INPUT;
2369 XQueryColor (dpy, cmap, &color);
2370 XAllocColor (dpy, cmap, &color);
2371 UNBLOCK_INPUT;
2372 #ifdef DEBUG_X_COLORS
2373 register_color (pixel);
2374 #endif
2375 return color.pixel;
2378 #endif /* MAC_TODO */
2381 /* Brightness beyond which a color won't have its highlight brightness
2382 boosted.
2384 Nominally, highlight colors for `3d' faces are calculated by
2385 brightening an object's color by a constant scale factor, but this
2386 doesn't yield good results for dark colors, so for colors who's
2387 brightness is less than this value (on a scale of 0-255) have to
2388 use an additional additive factor.
2390 The value here is set so that the default menu-bar/mode-line color
2391 (grey75) will not have its highlights changed at all. */
2392 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2395 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2396 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2397 If this produces the same color as COLOR, try a color where all RGB
2398 values have DELTA added. Return the allocated color in *COLOR.
2399 DISPLAY is the X display, CMAP is the colormap to operate on.
2400 Value is non-zero if successful. */
2402 static int
2403 mac_alloc_lighter_color (f, color, factor, delta)
2404 struct frame *f;
2405 unsigned long *color;
2406 double factor;
2407 int delta;
2409 unsigned long new;
2410 long bright;
2412 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2413 delta /= 256;
2415 /* Change RGB values by specified FACTOR. Avoid overflow! */
2416 xassert (factor >= 0);
2417 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2418 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2419 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2421 /* Calculate brightness of COLOR. */
2422 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2423 + BLUE_FROM_ULONG (*color)) / 6;
2425 /* We only boost colors that are darker than
2426 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2427 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2428 /* Make an additive adjustment to NEW, because it's dark enough so
2429 that scaling by FACTOR alone isn't enough. */
2431 /* How far below the limit this color is (0 - 1, 1 being darker). */
2432 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2433 /* The additive adjustment. */
2434 int min_delta = delta * dimness * factor / 2;
2436 if (factor < 1)
2437 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2438 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2439 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2440 else
2441 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2442 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2443 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2446 if (new == *color)
2447 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2448 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2449 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2451 /* MAC_TODO: Map to palette and retry with delta if same? */
2452 /* MAC_TODO: Free colors (if using palette)? */
2454 if (new == *color)
2455 return 0;
2457 *color = new;
2459 return 1;
2463 /* Set up the foreground color for drawing relief lines of glyph
2464 string S. RELIEF is a pointer to a struct relief containing the GC
2465 with which lines will be drawn. Use a color that is FACTOR or
2466 DELTA lighter or darker than the relief's background which is found
2467 in S->f->output_data.x->relief_background. If such a color cannot
2468 be allocated, use DEFAULT_PIXEL, instead. */
2470 static void
2471 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2472 struct frame *f;
2473 struct relief *relief;
2474 double factor;
2475 int delta;
2476 unsigned long default_pixel;
2478 XGCValues xgcv;
2479 struct mac_output *di = f->output_data.mac;
2480 unsigned long mask = GCForeground;
2481 unsigned long pixel;
2482 unsigned long background = di->relief_background;
2483 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2485 /* MAC_TODO: Free colors (if using palette)? */
2487 /* Allocate new color. */
2488 xgcv.foreground = default_pixel;
2489 pixel = background;
2490 if (dpyinfo->n_planes != 1
2491 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2493 relief->allocated_p = 1;
2494 xgcv.foreground = relief->pixel = pixel;
2497 if (relief->gc == 0)
2499 #if 0 /* MAC_TODO: stipple */
2500 xgcv.stipple = dpyinfo->gray;
2501 mask |= GCStipple;
2502 #endif
2503 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2505 else
2506 XChangeGC (NULL, relief->gc, mask, &xgcv);
2510 /* Set up colors for the relief lines around glyph string S. */
2512 static void
2513 x_setup_relief_colors (s)
2514 struct glyph_string *s;
2516 struct mac_output *di = s->f->output_data.mac;
2517 unsigned long color;
2519 if (s->face->use_box_color_for_shadows_p)
2520 color = s->face->box_color;
2521 else if (s->first_glyph->type == IMAGE_GLYPH
2522 && s->img->pixmap
2523 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2524 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2525 else
2527 XGCValues xgcv;
2529 /* Get the background color of the face. */
2530 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2531 color = xgcv.background;
2534 if (di->white_relief.gc == 0
2535 || color != di->relief_background)
2537 di->relief_background = color;
2538 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2539 WHITE_PIX_DEFAULT (s->f));
2540 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2541 BLACK_PIX_DEFAULT (s->f));
2546 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2547 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2548 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2549 relief. LEFT_P non-zero means draw a relief on the left side of
2550 the rectangle. RIGHT_P non-zero means draw a relief on the right
2551 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2552 when drawing. */
2554 static void
2555 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2556 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2557 struct frame *f;
2558 int left_x, top_y, right_x, bottom_y, width;
2559 int top_p, bot_p, left_p, right_p, raised_p;
2560 Rect *clip_rect;
2562 Display *dpy = FRAME_MAC_DISPLAY (f);
2563 Window window = FRAME_MAC_WINDOW (f);
2564 int i;
2565 GC gc;
2567 if (raised_p)
2568 gc = f->output_data.mac->white_relief.gc;
2569 else
2570 gc = f->output_data.mac->black_relief.gc;
2571 mac_set_clip_rectangle (dpy, window, clip_rect);
2573 /* Top. */
2574 if (top_p)
2575 for (i = 0; i < width; ++i)
2576 XDrawLine (dpy, window, gc,
2577 left_x + i * left_p, top_y + i,
2578 right_x - i * right_p, top_y + i);
2580 /* Left. */
2581 if (left_p)
2582 for (i = 0; i < width; ++i)
2583 XDrawLine (dpy, window, gc,
2584 left_x + i, top_y + i, left_x + i, bottom_y - i);
2586 mac_reset_clipping (dpy, window);
2587 if (raised_p)
2588 gc = f->output_data.mac->black_relief.gc;
2589 else
2590 gc = f->output_data.mac->white_relief.gc;
2591 mac_set_clip_rectangle (dpy, window,
2592 clip_rect);
2594 /* Bottom. */
2595 if (bot_p)
2596 for (i = 0; i < width; ++i)
2597 XDrawLine (dpy, window, gc,
2598 left_x + i * left_p, bottom_y - i,
2599 right_x - i * right_p, bottom_y - i);
2601 /* Right. */
2602 if (right_p)
2603 for (i = 0; i < width; ++i)
2604 XDrawLine (dpy, window, gc,
2605 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2607 mac_reset_clipping (dpy, window);
2611 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2612 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2613 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2614 left side of the rectangle. RIGHT_P non-zero means draw a line
2615 on the right side of the rectangle. CLIP_RECT is the clipping
2616 rectangle to use when drawing. */
2618 static void
2619 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2620 left_p, right_p, clip_rect)
2621 struct glyph_string *s;
2622 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2623 Rect *clip_rect;
2625 XGCValues xgcv;
2627 xgcv.foreground = s->face->box_color;
2628 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2630 /* Top. */
2631 XFillRectangle (s->display, s->window, &xgcv,
2632 left_x, top_y, right_x - left_x + 1, width);
2634 /* Left. */
2635 if (left_p)
2636 XFillRectangle (s->display, s->window, &xgcv,
2637 left_x, top_y, width, bottom_y - top_y + 1);
2639 /* Bottom. */
2640 XFillRectangle (s->display, s->window, &xgcv,
2641 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2643 /* Right. */
2644 if (right_p)
2645 XFillRectangle (s->display, s->window, &xgcv,
2646 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2648 mac_reset_clipping (s->display, s->window);
2652 /* Draw a box around glyph string S. */
2654 static void
2655 x_draw_glyph_string_box (s)
2656 struct glyph_string *s;
2658 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2659 int left_p, right_p;
2660 struct glyph *last_glyph;
2661 Rect clip_rect;
2663 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2664 ? WINDOW_RIGHT_EDGE_X (s->w)
2665 : window_box_right (s->w, s->area));
2667 /* The glyph that may have a right box line. */
2668 last_glyph = (s->cmp || s->img
2669 ? s->first_glyph
2670 : s->first_glyph + s->nchars - 1);
2672 width = abs (s->face->box_line_width);
2673 raised_p = s->face->box == FACE_RAISED_BOX;
2674 left_x = s->x;
2675 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2676 ? last_x - 1
2677 : min (last_x, s->x + s->background_width) - 1);
2678 top_y = s->y;
2679 bottom_y = top_y + s->height - 1;
2681 left_p = (s->first_glyph->left_box_line_p
2682 || (s->hl == DRAW_MOUSE_FACE
2683 && (s->prev == NULL
2684 || s->prev->hl != s->hl)));
2685 right_p = (last_glyph->right_box_line_p
2686 || (s->hl == DRAW_MOUSE_FACE
2687 && (s->next == NULL
2688 || s->next->hl != s->hl)));
2690 get_glyph_string_clip_rect (s, &clip_rect);
2692 if (s->face->box == FACE_SIMPLE_BOX)
2693 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2694 left_p, right_p, &clip_rect);
2695 else
2697 x_setup_relief_colors (s);
2698 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2699 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2704 /* Draw foreground of image glyph string S. */
2706 static void
2707 x_draw_image_foreground (s)
2708 struct glyph_string *s;
2710 int x = s->x;
2711 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2713 /* If first glyph of S has a left box line, start drawing it to the
2714 right of that line. */
2715 if (s->face->box != FACE_NO_BOX
2716 && s->first_glyph->left_box_line_p
2717 && s->slice.x == 0)
2718 x += abs (s->face->box_line_width);
2720 /* If there is a margin around the image, adjust x- and y-position
2721 by that margin. */
2722 if (s->slice.x == 0)
2723 x += s->img->hmargin;
2724 if (s->slice.y == 0)
2725 y += s->img->vmargin;
2727 if (s->img->pixmap)
2729 x_set_glyph_string_clipping (s);
2731 if (s->img->mask)
2732 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2733 s->window, s->gc, s->slice.x, s->slice.y,
2734 s->slice.width, s->slice.height, x, y);
2735 else
2737 mac_copy_area (s->display, s->img->pixmap,
2738 s->window, s->gc, s->slice.x, s->slice.y,
2739 s->slice.width, s->slice.height, x, y);
2741 /* When the image has a mask, we can expect that at
2742 least part of a mouse highlight or a block cursor will
2743 be visible. If the image doesn't have a mask, make
2744 a block cursor visible by drawing a rectangle around
2745 the image. I believe it's looking better if we do
2746 nothing here for mouse-face. */
2747 if (s->hl == DRAW_CURSOR)
2749 int r = s->img->relief;
2750 if (r < 0) r = -r;
2751 mac_draw_rectangle (s->display, s->window, s->gc,
2752 x - r, y - r,
2753 s->slice.width + r*2 - 1,
2754 s->slice.height + r*2 - 1);
2758 else
2759 /* Draw a rectangle if image could not be loaded. */
2760 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2761 s->slice.width - 1, s->slice.height - 1);
2765 /* Draw a relief around the image glyph string S. */
2767 static void
2768 x_draw_image_relief (s)
2769 struct glyph_string *s;
2771 int x0, y0, x1, y1, thick, raised_p;
2772 Rect r;
2773 int x = s->x;
2774 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2776 /* If first glyph of S has a left box line, start drawing it to the
2777 right of that line. */
2778 if (s->face->box != FACE_NO_BOX
2779 && s->first_glyph->left_box_line_p
2780 && s->slice.x == 0)
2781 x += abs (s->face->box_line_width);
2783 /* If there is a margin around the image, adjust x- and y-position
2784 by that margin. */
2785 if (s->slice.x == 0)
2786 x += s->img->hmargin;
2787 if (s->slice.y == 0)
2788 y += s->img->vmargin;
2790 if (s->hl == DRAW_IMAGE_SUNKEN
2791 || s->hl == DRAW_IMAGE_RAISED)
2793 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2794 raised_p = s->hl == DRAW_IMAGE_RAISED;
2796 else
2798 thick = abs (s->img->relief);
2799 raised_p = s->img->relief > 0;
2802 x0 = x - thick;
2803 y0 = y - thick;
2804 x1 = x + s->slice.width + thick - 1;
2805 y1 = y + s->slice.height + thick - 1;
2807 x_setup_relief_colors (s);
2808 get_glyph_string_clip_rect (s, &r);
2809 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2810 s->slice.y == 0,
2811 s->slice.y + s->slice.height == s->img->height,
2812 s->slice.x == 0,
2813 s->slice.x + s->slice.width == s->img->width,
2814 &r);
2818 #if 0 /* TODO: figure out if we need to do this on Mac. */
2819 /* Draw the foreground of image glyph string S to PIXMAP. */
2821 static void
2822 x_draw_image_foreground_1 (s, pixmap)
2823 struct glyph_string *s;
2824 Pixmap pixmap;
2826 int x = 0;
2827 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2829 /* If first glyph of S has a left box line, start drawing it to the
2830 right of that line. */
2831 if (s->face->box != FACE_NO_BOX
2832 && s->first_glyph->left_box_line_p
2833 && s->slice.x == 0)
2834 x += abs (s->face->box_line_width);
2836 /* If there is a margin around the image, adjust x- and y-position
2837 by that margin. */
2838 if (s->slice.x == 0)
2839 x += s->img->hmargin;
2840 if (s->slice.y == 0)
2841 y += s->img->vmargin;
2843 if (s->img->pixmap)
2845 if (s->img->mask)
2846 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2847 s->img->mask, pixmap, s->gc,
2848 s->slice.x, s->slice.y,
2849 s->slice.width, s->slice.height,
2850 x, y);
2851 else
2853 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2854 s->slice.x, s->slice.y,
2855 s->slice.width, s->slice.height,
2856 x, y);
2858 /* When the image has a mask, we can expect that at
2859 least part of a mouse highlight or a block cursor will
2860 be visible. If the image doesn't have a mask, make
2861 a block cursor visible by drawing a rectangle around
2862 the image. I believe it's looking better if we do
2863 nothing here for mouse-face. */
2864 if (s->hl == DRAW_CURSOR)
2866 int r = s->img->relief;
2867 if (r < 0) r = -r;
2868 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2869 s->slice.width + r*2 - 1,
2870 s->slice.height + r*2 - 1);
2874 else
2875 /* Draw a rectangle if image could not be loaded. */
2876 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2877 s->slice.width - 1, s->slice.height - 1);
2879 #endif
2882 /* Draw part of the background of glyph string S. X, Y, W, and H
2883 give the rectangle to draw. */
2885 static void
2886 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2887 struct glyph_string *s;
2888 int x, y, w, h;
2890 #if 0 /* MAC_TODO: stipple */
2891 if (s->stippled_p)
2893 /* Fill background with a stipple pattern. */
2894 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2895 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2896 XSetFillStyle (s->display, s->gc, FillSolid);
2898 else
2899 #endif /* MAC_TODO */
2900 x_clear_glyph_string_rect (s, x, y, w, h);
2904 /* Draw image glyph string S.
2906 s->y
2907 s->x +-------------------------
2908 | s->face->box
2910 | +-------------------------
2911 | | s->img->margin
2913 | | +-------------------
2914 | | | the image
2918 static void
2919 x_draw_image_glyph_string (s)
2920 struct glyph_string *s;
2922 int x, y;
2923 int box_line_hwidth = abs (s->face->box_line_width);
2924 int box_line_vwidth = max (s->face->box_line_width, 0);
2925 int height;
2926 Pixmap pixmap = 0;
2928 height = s->height - 2 * box_line_vwidth;
2931 /* Fill background with face under the image. Do it only if row is
2932 taller than image or if image has a clip mask to reduce
2933 flickering. */
2934 s->stippled_p = s->face->stipple != 0;
2935 if (height > s->slice.height
2936 || s->img->hmargin
2937 || s->img->vmargin
2938 || s->img->mask
2939 || s->img->pixmap == 0
2940 || s->width != s->background_width)
2942 x = s->x;
2943 if (s->first_glyph->left_box_line_p
2944 && s->slice.x == 0)
2945 x += box_line_hwidth;
2947 y = s->y;
2948 if (s->slice.y == 0)
2949 y += box_line_vwidth;
2951 #if 0 /* TODO: figure out if we need to do this on Mac. */
2952 if (s->img->mask)
2954 /* Create a pixmap as large as the glyph string. Fill it
2955 with the background color. Copy the image to it, using
2956 its mask. Copy the temporary pixmap to the display. */
2957 int depth = one_mac_display_info.n_planes;
2959 /* Create a pixmap as large as the glyph string. */
2960 pixmap = XCreatePixmap (s->display, s->window,
2961 s->background_width,
2962 s->height, depth);
2964 /* Fill the pixmap with the background color/stipple. */
2965 #if 0 /* TODO: stipple */
2966 if (s->stippled_p)
2968 /* Fill background with a stipple pattern. */
2969 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2970 XFillRectangle (s->display, pixmap, s->gc,
2971 0, 0, s->background_width, s->height);
2972 XSetFillStyle (s->display, s->gc, FillSolid);
2974 else
2975 #endif
2977 XGCValues xgcv;
2978 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2979 &xgcv);
2980 XSetForeground (s->display, s->gc, xgcv.background);
2981 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2982 0, 0, s->background_width,
2983 s->height);
2984 XSetForeground (s->display, s->gc, xgcv.foreground);
2987 else
2988 #endif
2989 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2991 s->background_filled_p = 1;
2994 /* Draw the foreground. */
2995 #if 0 /* TODO: figure out if we need to do this on Mac. */
2996 if (pixmap != 0)
2998 x_draw_image_foreground_1 (s, pixmap);
2999 x_set_glyph_string_clipping (s);
3000 mac_copy_area (s->display, pixmap, s->window, s->gc,
3001 0, 0, s->background_width, s->height, s->x, s->y);
3002 mac_reset_clipping (s->display, s->window);
3003 XFreePixmap (s->display, pixmap);
3005 else
3006 #endif
3007 x_draw_image_foreground (s);
3009 /* If we must draw a relief around the image, do it. */
3010 if (s->img->relief
3011 || s->hl == DRAW_IMAGE_RAISED
3012 || s->hl == DRAW_IMAGE_SUNKEN)
3013 x_draw_image_relief (s);
3017 /* Draw stretch glyph string S. */
3019 static void
3020 x_draw_stretch_glyph_string (s)
3021 struct glyph_string *s;
3023 xassert (s->first_glyph->type == STRETCH_GLYPH);
3024 s->stippled_p = s->face->stipple != 0;
3026 if (s->hl == DRAW_CURSOR
3027 && !x_stretch_cursor_p)
3029 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3030 as wide as the stretch glyph. */
3031 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
3033 /* Draw cursor. */
3034 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3036 /* Clear rest using the GC of the original non-cursor face. */
3037 if (width < s->background_width)
3039 int x = s->x + width, y = s->y;
3040 int w = s->background_width - width, h = s->height;
3041 Rect r;
3042 GC gc;
3044 if (s->row->mouse_face_p
3045 && cursor_in_mouse_face_p (s->w))
3047 x_set_mouse_face_gc (s);
3048 gc = s->gc;
3050 else
3051 gc = s->face->gc;
3053 get_glyph_string_clip_rect (s, &r);
3054 mac_set_clip_rectangle (s->display, s->window, &r);
3056 #if 0 /* MAC_TODO: stipple */
3057 if (s->face->stipple)
3059 /* Fill background with a stipple pattern. */
3060 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3061 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3062 XSetFillStyle (s->display, gc, FillSolid);
3064 else
3065 #endif /* MAC_TODO */
3067 XGCValues xgcv;
3068 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3069 XSetForeground (s->display, gc, xgcv.background);
3070 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3071 XSetForeground (s->display, gc, xgcv.foreground);
3074 mac_reset_clipping (s->display, s->window);
3077 else if (!s->background_filled_p)
3078 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3079 s->height);
3081 s->background_filled_p = 1;
3085 /* Draw glyph string S. */
3087 static void
3088 x_draw_glyph_string (s)
3089 struct glyph_string *s;
3091 int relief_drawn_p = 0;
3093 /* If S draws into the background of its successor that does not
3094 draw a cursor, draw the background of the successor first so that
3095 S can draw into it. This makes S->next use XDrawString instead
3096 of XDrawImageString. */
3097 if (s->next && s->right_overhang && !s->for_overlaps_p
3098 && s->next->hl != DRAW_CURSOR)
3100 xassert (s->next->img == NULL);
3101 x_set_glyph_string_gc (s->next);
3102 x_set_glyph_string_clipping (s->next);
3103 x_draw_glyph_string_background (s->next, 1);
3106 /* Set up S->gc, set clipping and draw S. */
3107 x_set_glyph_string_gc (s);
3109 /* Draw relief (if any) in advance for char/composition so that the
3110 glyph string can be drawn over it. */
3111 if (!s->for_overlaps_p
3112 && s->face->box != FACE_NO_BOX
3113 && (s->first_glyph->type == CHAR_GLYPH
3114 || s->first_glyph->type == COMPOSITE_GLYPH))
3117 x_set_glyph_string_clipping (s);
3118 x_draw_glyph_string_background (s, 1);
3119 x_draw_glyph_string_box (s);
3120 x_set_glyph_string_clipping (s);
3121 relief_drawn_p = 1;
3123 else
3124 x_set_glyph_string_clipping (s);
3126 switch (s->first_glyph->type)
3128 case IMAGE_GLYPH:
3129 x_draw_image_glyph_string (s);
3130 break;
3132 case STRETCH_GLYPH:
3133 x_draw_stretch_glyph_string (s);
3134 break;
3136 case CHAR_GLYPH:
3137 if (s->for_overlaps_p)
3138 s->background_filled_p = 1;
3139 else
3140 x_draw_glyph_string_background (s, 0);
3141 x_draw_glyph_string_foreground (s);
3142 break;
3144 case COMPOSITE_GLYPH:
3145 if (s->for_overlaps_p || s->gidx > 0)
3146 s->background_filled_p = 1;
3147 else
3148 x_draw_glyph_string_background (s, 1);
3149 x_draw_composite_glyph_string_foreground (s);
3150 break;
3152 default:
3153 abort ();
3156 if (!s->for_overlaps_p)
3158 /* Draw underline. */
3159 if (s->face->underline_p)
3161 unsigned long h = 1;
3162 unsigned long dy = s->height - h;
3164 if (s->face->underline_defaulted_p)
3165 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3166 s->width, h);
3167 else
3169 XGCValues xgcv;
3170 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3171 XSetForeground (s->display, s->gc, s->face->underline_color);
3172 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3173 s->width, h);
3174 XSetForeground (s->display, s->gc, xgcv.foreground);
3178 /* Draw overline. */
3179 if (s->face->overline_p)
3181 unsigned long dy = 0, h = 1;
3183 if (s->face->overline_color_defaulted_p)
3184 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3185 s->width, h);
3186 else
3188 XGCValues xgcv;
3189 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3190 XSetForeground (s->display, s->gc, s->face->overline_color);
3191 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3192 s->width, h);
3193 XSetForeground (s->display, s->gc, xgcv.foreground);
3197 /* Draw strike-through. */
3198 if (s->face->strike_through_p)
3200 unsigned long h = 1;
3201 unsigned long dy = (s->height - h) / 2;
3203 if (s->face->strike_through_color_defaulted_p)
3204 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3205 s->width, h);
3206 else
3208 XGCValues xgcv;
3209 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3210 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3211 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3212 s->width, h);
3213 XSetForeground (s->display, s->gc, xgcv.foreground);
3217 /* Draw relief if not yet drawn. */
3218 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3219 x_draw_glyph_string_box (s);
3222 /* Reset clipping. */
3223 mac_reset_clipping (s->display, s->window);
3226 /* Shift display to make room for inserted glyphs. */
3228 void
3229 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3230 struct frame *f;
3231 int x, y, width, height, shift_by;
3233 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3234 f->output_data.mac->normal_gc,
3235 x, y, width, height,
3236 x + shift_by, y);
3239 /* Delete N glyphs at the nominal cursor position. Not implemented
3240 for X frames. */
3242 static void
3243 x_delete_glyphs (n)
3244 register int n;
3246 abort ();
3250 /* Clear entire frame. If updating_frame is non-null, clear that
3251 frame. Otherwise clear the selected frame. */
3253 static void
3254 x_clear_frame ()
3256 struct frame *f;
3258 if (updating_frame)
3259 f = updating_frame;
3260 else
3261 f = SELECTED_FRAME ();
3263 /* Clearing the frame will erase any cursor, so mark them all as no
3264 longer visible. */
3265 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3266 output_cursor.hpos = output_cursor.vpos = 0;
3267 output_cursor.x = -1;
3269 /* We don't set the output cursor here because there will always
3270 follow an explicit cursor_to. */
3271 BLOCK_INPUT;
3272 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3274 /* We have to clear the scroll bars, too. If we have changed
3275 colors or something like that, then they should be notified. */
3276 x_scroll_bar_clear (f);
3278 XFlush (FRAME_MAC_DISPLAY (f));
3279 UNBLOCK_INPUT;
3284 /* Invert the middle quarter of the frame for .15 sec. */
3286 /* We use the select system call to do the waiting, so we have to make
3287 sure it's available. If it isn't, we just won't do visual bells. */
3289 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3292 /* Subtract the `struct timeval' values X and Y, storing the result in
3293 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3295 static int
3296 timeval_subtract (result, x, y)
3297 struct timeval *result, x, y;
3299 /* Perform the carry for the later subtraction by updating y. This
3300 is safer because on some systems the tv_sec member is unsigned. */
3301 if (x.tv_usec < y.tv_usec)
3303 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3304 y.tv_usec -= 1000000 * nsec;
3305 y.tv_sec += nsec;
3308 if (x.tv_usec - y.tv_usec > 1000000)
3310 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3311 y.tv_usec += 1000000 * nsec;
3312 y.tv_sec -= nsec;
3315 /* Compute the time remaining to wait. tv_usec is certainly
3316 positive. */
3317 result->tv_sec = x.tv_sec - y.tv_sec;
3318 result->tv_usec = x.tv_usec - y.tv_usec;
3320 /* Return indication of whether the result should be considered
3321 negative. */
3322 return x.tv_sec < y.tv_sec;
3325 void
3326 XTflash (f)
3327 struct frame *f;
3329 BLOCK_INPUT;
3331 FlashMenuBar (0);
3334 struct timeval wakeup;
3336 EMACS_GET_TIME (wakeup);
3338 /* Compute time to wait until, propagating carry from usecs. */
3339 wakeup.tv_usec += 150000;
3340 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3341 wakeup.tv_usec %= 1000000;
3343 /* Keep waiting until past the time wakeup. */
3344 while (1)
3346 struct timeval timeout;
3348 EMACS_GET_TIME (timeout);
3350 /* In effect, timeout = wakeup - timeout.
3351 Break if result would be negative. */
3352 if (timeval_subtract (&timeout, wakeup, timeout))
3353 break;
3355 /* Try to wait that long--but we might wake up sooner. */
3356 select (0, NULL, NULL, NULL, &timeout);
3360 FlashMenuBar (0);
3362 UNBLOCK_INPUT;
3365 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3368 /* Make audible bell. */
3370 void
3371 XTring_bell ()
3373 struct frame *f = SELECTED_FRAME ();
3375 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3376 if (visible_bell)
3377 XTflash (f);
3378 else
3379 #endif
3381 BLOCK_INPUT;
3382 SysBeep (1);
3383 XFlush (FRAME_MAC_DISPLAY (f));
3384 UNBLOCK_INPUT;
3390 /* Specify how many text lines, from the top of the window,
3391 should be affected by insert-lines and delete-lines operations.
3392 This, and those operations, are used only within an update
3393 that is bounded by calls to x_update_begin and x_update_end. */
3395 static void
3396 XTset_terminal_window (n)
3397 register int n;
3399 /* This function intentionally left blank. */
3404 /***********************************************************************
3405 Line Dance
3406 ***********************************************************************/
3408 /* Perform an insert-lines or delete-lines operation, inserting N
3409 lines or deleting -N lines at vertical position VPOS. */
3411 static void
3412 x_ins_del_lines (vpos, n)
3413 int vpos, n;
3415 abort ();
3419 /* Scroll part of the display as described by RUN. */
3421 static void
3422 x_scroll_run (w, run)
3423 struct window *w;
3424 struct run *run;
3426 struct frame *f = XFRAME (w->frame);
3427 int x, y, width, height, from_y, to_y, bottom_y;
3429 /* Get frame-relative bounding box of the text display area of W,
3430 without mode lines. Include in this box the left and right
3431 fringe of W. */
3432 window_box (w, -1, &x, &y, &width, &height);
3434 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3435 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3436 bottom_y = y + height;
3438 if (to_y < from_y)
3440 /* Scrolling up. Make sure we don't copy part of the mode
3441 line at the bottom. */
3442 if (from_y + run->height > bottom_y)
3443 height = bottom_y - from_y;
3444 else
3445 height = run->height;
3447 else
3449 /* Scolling down. Make sure we don't copy over the mode line.
3450 at the bottom. */
3451 if (to_y + run->height > bottom_y)
3452 height = bottom_y - to_y;
3453 else
3454 height = run->height;
3457 BLOCK_INPUT;
3459 /* Cursor off. Will be switched on again in x_update_window_end. */
3460 updated_window = w;
3461 x_clear_cursor (w);
3463 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3464 f->output_data.mac->normal_gc,
3465 x, from_y,
3466 width, height,
3467 x, to_y);
3469 UNBLOCK_INPUT;
3474 /***********************************************************************
3475 Exposure Events
3476 ***********************************************************************/
3479 static void
3480 frame_highlight (f)
3481 struct frame *f;
3483 OSErr err;
3484 ControlRef root_control;
3486 BLOCK_INPUT;
3487 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
3488 if (err == noErr)
3489 ActivateControl (root_control);
3490 UNBLOCK_INPUT;
3491 x_update_cursor (f, 1);
3494 static void
3495 frame_unhighlight (f)
3496 struct frame *f;
3498 OSErr err;
3499 ControlRef root_control;
3501 BLOCK_INPUT;
3502 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
3503 if (err == noErr)
3504 DeactivateControl (root_control);
3505 UNBLOCK_INPUT;
3506 x_update_cursor (f, 1);
3509 /* The focus has changed. Update the frames as necessary to reflect
3510 the new situation. Note that we can't change the selected frame
3511 here, because the Lisp code we are interrupting might become confused.
3512 Each event gets marked with the frame in which it occurred, so the
3513 Lisp code can tell when the switch took place by examining the events. */
3515 static void
3516 x_new_focus_frame (dpyinfo, frame)
3517 struct x_display_info *dpyinfo;
3518 struct frame *frame;
3520 struct frame *old_focus = dpyinfo->x_focus_frame;
3522 if (frame != dpyinfo->x_focus_frame)
3524 /* Set this before calling other routines, so that they see
3525 the correct value of x_focus_frame. */
3526 dpyinfo->x_focus_frame = frame;
3528 if (old_focus && old_focus->auto_lower)
3529 x_lower_frame (old_focus);
3531 #if 0
3532 selected_frame = frame;
3533 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3534 selected_frame);
3535 Fselect_window (selected_frame->selected_window, Qnil);
3536 choose_minibuf_frame ();
3537 #endif /* ! 0 */
3539 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3540 pending_autoraise_frame = dpyinfo->x_focus_frame;
3541 else
3542 pending_autoraise_frame = 0;
3545 x_frame_rehighlight (dpyinfo);
3548 /* Handle FocusIn and FocusOut state changes for FRAME.
3549 If FRAME has focus and there exists more than one frame, puts
3550 a FOCUS_IN_EVENT into *BUFP. */
3552 static void
3553 mac_focus_changed (type, dpyinfo, frame, bufp)
3554 int type;
3555 struct mac_display_info *dpyinfo;
3556 struct frame *frame;
3557 struct input_event *bufp;
3559 if (type == activeFlag)
3561 if (dpyinfo->x_focus_event_frame != frame)
3563 x_new_focus_frame (dpyinfo, frame);
3564 dpyinfo->x_focus_event_frame = frame;
3566 /* Don't stop displaying the initial startup message
3567 for a switch-frame event we don't need. */
3568 if (GC_NILP (Vterminal_frame)
3569 && GC_CONSP (Vframe_list)
3570 && !GC_NILP (XCDR (Vframe_list)))
3572 bufp->kind = FOCUS_IN_EVENT;
3573 XSETFRAME (bufp->frame_or_window, frame);
3577 else
3579 if (dpyinfo->x_focus_event_frame == frame)
3581 dpyinfo->x_focus_event_frame = 0;
3582 x_new_focus_frame (dpyinfo, 0);
3587 /* The focus may have changed. Figure out if it is a real focus change,
3588 by checking both FocusIn/Out and Enter/LeaveNotify events.
3590 Returns FOCUS_IN_EVENT event in *BUFP. */
3592 static void
3593 x_detect_focus_change (dpyinfo, event, bufp)
3594 struct mac_display_info *dpyinfo;
3595 EventRecord *event;
3596 struct input_event *bufp;
3598 struct frame *frame;
3600 frame = mac_window_to_frame ((WindowPtr) event->message);
3601 if (! frame)
3602 return;
3604 /* On Mac, this is only called from focus events, so no switch needed. */
3605 mac_focus_changed ((event->modifiers & activeFlag),
3606 dpyinfo, frame, bufp);
3610 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3612 void
3613 x_mouse_leave (dpyinfo)
3614 struct x_display_info *dpyinfo;
3616 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3619 /* The focus has changed, or we have redirected a frame's focus to
3620 another frame (this happens when a frame uses a surrogate
3621 mini-buffer frame). Shift the highlight as appropriate.
3623 The FRAME argument doesn't necessarily have anything to do with which
3624 frame is being highlighted or un-highlighted; we only use it to find
3625 the appropriate X display info. */
3627 static void
3628 XTframe_rehighlight (frame)
3629 struct frame *frame;
3631 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3634 static void
3635 x_frame_rehighlight (dpyinfo)
3636 struct x_display_info *dpyinfo;
3638 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3640 if (dpyinfo->x_focus_frame)
3642 dpyinfo->x_highlight_frame
3643 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3644 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3645 : dpyinfo->x_focus_frame);
3646 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3648 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3649 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3652 else
3653 dpyinfo->x_highlight_frame = 0;
3655 if (dpyinfo->x_highlight_frame != old_highlight)
3657 if (old_highlight)
3658 frame_unhighlight (old_highlight);
3659 if (dpyinfo->x_highlight_frame)
3660 frame_highlight (dpyinfo->x_highlight_frame);
3666 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3668 #if 0 /* MAC_TODO */
3669 /* Initialize mode_switch_bit and modifier_meaning. */
3670 static void
3671 x_find_modifier_meanings (dpyinfo)
3672 struct x_display_info *dpyinfo;
3674 int min_code, max_code;
3675 KeySym *syms;
3676 int syms_per_code;
3677 XModifierKeymap *mods;
3679 dpyinfo->meta_mod_mask = 0;
3680 dpyinfo->shift_lock_mask = 0;
3681 dpyinfo->alt_mod_mask = 0;
3682 dpyinfo->super_mod_mask = 0;
3683 dpyinfo->hyper_mod_mask = 0;
3685 #ifdef HAVE_X11R4
3686 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3687 #else
3688 min_code = dpyinfo->display->min_keycode;
3689 max_code = dpyinfo->display->max_keycode;
3690 #endif
3692 syms = XGetKeyboardMapping (dpyinfo->display,
3693 min_code, max_code - min_code + 1,
3694 &syms_per_code);
3695 mods = XGetModifierMapping (dpyinfo->display);
3697 /* Scan the modifier table to see which modifier bits the Meta and
3698 Alt keysyms are on. */
3700 int row, col; /* The row and column in the modifier table. */
3702 for (row = 3; row < 8; row++)
3703 for (col = 0; col < mods->max_keypermod; col++)
3705 KeyCode code
3706 = mods->modifiermap[(row * mods->max_keypermod) + col];
3708 /* Zeroes are used for filler. Skip them. */
3709 if (code == 0)
3710 continue;
3712 /* Are any of this keycode's keysyms a meta key? */
3714 int code_col;
3716 for (code_col = 0; code_col < syms_per_code; code_col++)
3718 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3720 switch (sym)
3722 case XK_Meta_L:
3723 case XK_Meta_R:
3724 dpyinfo->meta_mod_mask |= (1 << row);
3725 break;
3727 case XK_Alt_L:
3728 case XK_Alt_R:
3729 dpyinfo->alt_mod_mask |= (1 << row);
3730 break;
3732 case XK_Hyper_L:
3733 case XK_Hyper_R:
3734 dpyinfo->hyper_mod_mask |= (1 << row);
3735 break;
3737 case XK_Super_L:
3738 case XK_Super_R:
3739 dpyinfo->super_mod_mask |= (1 << row);
3740 break;
3742 case XK_Shift_Lock:
3743 /* Ignore this if it's not on the lock modifier. */
3744 if ((1 << row) == LockMask)
3745 dpyinfo->shift_lock_mask = LockMask;
3746 break;
3753 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3754 if (! dpyinfo->meta_mod_mask)
3756 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3757 dpyinfo->alt_mod_mask = 0;
3760 /* If some keys are both alt and meta,
3761 make them just meta, not alt. */
3762 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3764 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3767 XFree ((char *) syms);
3768 XFreeModifiermap (mods);
3771 #endif /* MAC_TODO */
3773 /* Convert between the modifier bits X uses and the modifier bits
3774 Emacs uses. */
3776 static unsigned int
3777 x_mac_to_emacs_modifiers (dpyinfo, state)
3778 struct x_display_info *dpyinfo;
3779 unsigned short state;
3781 return (((state & shiftKey) ? shift_modifier : 0)
3782 | ((state & controlKey) ? ctrl_modifier : 0)
3783 | ((state & cmdKey) ? meta_modifier : 0)
3784 | ((state & optionKey) ? alt_modifier : 0));
3787 #if 0 /* MAC_TODO */
3788 static unsigned short
3789 x_emacs_to_x_modifiers (dpyinfo, state)
3790 struct x_display_info *dpyinfo;
3791 unsigned int state;
3793 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3794 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3795 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3796 | ((state & shift_modifier) ? ShiftMask : 0)
3797 | ((state & ctrl_modifier) ? ControlMask : 0)
3798 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3800 #endif /* MAC_TODO */
3802 /* Convert a keysym to its name. */
3804 char *
3805 x_get_keysym_name (keysym)
3806 int keysym;
3808 char *value;
3810 BLOCK_INPUT;
3811 #if 0
3812 value = XKeysymToString (keysym);
3813 #else
3814 value = 0;
3815 #endif
3816 UNBLOCK_INPUT;
3818 return value;
3823 #if 0
3824 /* Mouse clicks and mouse movement. Rah. */
3826 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3828 If the event is a button press, then note that we have grabbed
3829 the mouse. */
3831 static Lisp_Object
3832 construct_mouse_click (result, event, f)
3833 struct input_event *result;
3834 EventRecord *event;
3835 struct frame *f;
3837 Point mouseLoc;
3839 result->kind = MOUSE_CLICK_EVENT;
3840 result->code = 0; /* only one mouse button */
3841 result->timestamp = event->when;
3842 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3844 mouseLoc = event->where;
3846 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3848 GlobalToLocal (&mouseLoc);
3849 XSETINT (result->x, mouseLoc.h);
3850 XSETINT (result->y, mouseLoc.v);
3852 XSETFRAME (result->frame_or_window, f);
3854 result->arg = Qnil;
3855 return Qnil;
3857 #endif
3860 /* Function to report a mouse movement to the mainstream Emacs code.
3861 The input handler calls this.
3863 We have received a mouse movement event, which is given in *event.
3864 If the mouse is over a different glyph than it was last time, tell
3865 the mainstream emacs code by setting mouse_moved. If not, ask for
3866 another motion event, so we can check again the next time it moves. */
3868 static Point last_mouse_motion_position;
3869 static Lisp_Object last_mouse_motion_frame;
3871 static void
3872 note_mouse_movement (frame, pos)
3873 FRAME_PTR frame;
3874 Point *pos;
3876 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3877 #if TARGET_API_MAC_CARBON
3878 Rect r;
3879 #endif
3881 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3882 last_mouse_motion_position = *pos;
3883 XSETFRAME (last_mouse_motion_frame, frame);
3885 #if TARGET_API_MAC_CARBON
3886 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3887 #else
3888 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3889 #endif
3891 if (frame == dpyinfo->mouse_face_mouse_frame)
3892 /* This case corresponds to LeaveNotify in X11. */
3894 /* If we move outside the frame, then we're certainly no
3895 longer on any text in the frame. */
3896 clear_mouse_face (dpyinfo);
3897 dpyinfo->mouse_face_mouse_frame = 0;
3898 if (!dpyinfo->grabbed)
3899 rif->define_frame_cursor (frame,
3900 frame->output_data.mac->nontext_cursor);
3903 /* Has the mouse moved off the glyph it was on at the last sighting? */
3904 else if (pos->h < last_mouse_glyph.left
3905 || pos->h >= last_mouse_glyph.right
3906 || pos->v < last_mouse_glyph.top
3907 || pos->v >= last_mouse_glyph.bottom)
3909 frame->mouse_moved = 1;
3910 last_mouse_scroll_bar = Qnil;
3911 note_mouse_highlight (frame, pos->h, pos->v);
3915 /* This is used for debugging, to turn off note_mouse_highlight. */
3917 int disable_mouse_highlight;
3921 /************************************************************************
3922 Mouse Face
3923 ************************************************************************/
3925 static struct scroll_bar *x_window_to_scroll_bar ();
3926 static void x_scroll_bar_report_motion ();
3927 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3930 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3932 static void
3933 redo_mouse_highlight ()
3935 if (!NILP (last_mouse_motion_frame)
3936 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3937 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3938 last_mouse_motion_position.h,
3939 last_mouse_motion_position.v);
3943 /* Try to determine frame pixel position and size of the glyph under
3944 frame pixel coordinates X/Y on frame F . Return the position and
3945 size in *RECT. Value is non-zero if we could compute these
3946 values. */
3948 static int
3949 glyph_rect (f, x, y, rect)
3950 struct frame *f;
3951 int x, y;
3952 Rect *rect;
3954 Lisp_Object window;
3956 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3958 if (!NILP (window))
3960 struct window *w = XWINDOW (window);
3961 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3962 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3964 for (; r < end && r->enabled_p; ++r)
3965 if (r->y <= y && r->y + r->height > y)
3967 /* Found the row at y. */
3968 struct glyph *g = r->glyphs[TEXT_AREA];
3969 struct glyph *end = g + r->used[TEXT_AREA];
3970 int gx;
3972 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3973 rect->bottom = rect->top + r->height;
3975 if (x < r->x)
3977 /* x is to the left of the first glyph in the row. */
3978 /* Shouldn't this be a pixel value?
3979 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3980 ++KFS */
3981 rect->left = WINDOW_LEFT_EDGE_COL (w);
3982 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3983 return 1;
3986 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3987 if (gx <= x && gx + g->pixel_width > x)
3989 /* x is on a glyph. */
3990 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3991 rect->right = rect->left + g->pixel_width;
3992 return 1;
3995 /* x is to the right of the last glyph in the row. */
3996 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3997 /* Shouldn't this be a pixel value?
3998 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3999 ++KFS */
4000 rect->right = WINDOW_RIGHT_EDGE_COL (w);
4001 return 1;
4005 /* The y is not on any row. */
4006 return 0;
4009 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4011 /* Record the position of the mouse in last_mouse_glyph. */
4012 static void
4013 remember_mouse_glyph (f1, gx, gy)
4014 struct frame * f1;
4015 int gx, gy;
4017 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
4019 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
4020 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
4022 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
4023 round down even for negative values. */
4024 if (gx < 0)
4025 gx -= width - 1;
4026 if (gy < 0)
4027 gy -= height - 1;
4028 #if 0
4029 /* This was the original code from XTmouse_position, but it seems
4030 to give the position of the glyph diagonally next to the one
4031 the mouse is over. */
4032 gx = (gx + width - 1) / width * width;
4033 gy = (gy + height - 1) / height * height;
4034 #else
4035 gx = gx / width * width;
4036 gy = gy / height * height;
4037 #endif
4039 last_mouse_glyph.left = gx;
4040 last_mouse_glyph.top = gy;
4041 last_mouse_glyph.right = gx + width;
4042 last_mouse_glyph.bottom = gy + height;
4047 static struct frame *
4048 mac_focus_frame (dpyinfo)
4049 struct mac_display_info *dpyinfo;
4051 if (dpyinfo->x_focus_frame)
4052 return dpyinfo->x_focus_frame;
4053 else
4054 /* Mac version may get events, such as a menu bar click, even when
4055 all the frames are invisible. In this case, we regard the
4056 event came to the selected frame. */
4057 return SELECTED_FRAME ();
4061 /* Return the current position of the mouse.
4062 *fp should be a frame which indicates which display to ask about.
4064 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4065 and *part to the frame, window, and scroll bar part that the mouse
4066 is over. Set *x and *y to the portion and whole of the mouse's
4067 position on the scroll bar.
4069 If the mouse movement started elsewhere, set *fp to the frame the
4070 mouse is on, *bar_window to nil, and *x and *y to the character cell
4071 the mouse is over.
4073 Set *time to the server time-stamp for the time at which the mouse
4074 was at this position.
4076 Don't store anything if we don't have a valid set of values to report.
4078 This clears the mouse_moved flag, so we can wait for the next mouse
4079 movement. */
4081 static void
4082 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4083 FRAME_PTR *fp;
4084 int insist;
4085 Lisp_Object *bar_window;
4086 enum scroll_bar_part *part;
4087 Lisp_Object *x, *y;
4088 unsigned long *time;
4090 Point mouse_pos;
4091 int ignore1, ignore2;
4092 struct frame *f = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
4093 WindowPtr wp = FRAME_MAC_WINDOW (f);
4094 Lisp_Object frame, tail;
4096 BLOCK_INPUT;
4098 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4099 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4100 else
4102 /* Clear the mouse-moved flag for every frame on this display. */
4103 FOR_EACH_FRAME (tail, frame)
4104 XFRAME (frame)->mouse_moved = 0;
4106 last_mouse_scroll_bar = Qnil;
4108 SetPortWindowPort (wp);
4110 GetMouse (&mouse_pos);
4112 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
4113 &last_mouse_glyph, insist);
4115 *bar_window = Qnil;
4116 *part = scroll_bar_handle;
4117 *fp = f;
4118 XSETINT (*x, mouse_pos.h);
4119 XSETINT (*y, mouse_pos.v);
4120 *time = last_mouse_movement_time;
4123 UNBLOCK_INPUT;
4127 /************************************************************************
4128 Toolkit scroll bars
4129 ************************************************************************/
4131 #ifdef USE_TOOLKIT_SCROLL_BARS
4133 static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
4134 static OSStatus install_scroll_bar_timer P_ ((void));
4135 static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
4136 static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
4137 static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
4138 unsigned long,
4139 struct input_event *));
4140 static OSErr get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
4141 Rect *));
4142 static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
4143 ControlPartCode,
4144 unsigned long,
4145 struct input_event *));
4146 static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
4147 unsigned long,
4148 struct input_event *));
4149 static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
4150 Point, unsigned long,
4151 struct input_event *));
4152 static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
4153 int, int, int));
4155 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4157 static int last_scroll_bar_part;
4159 static EventLoopTimerRef scroll_bar_timer;
4161 static int scroll_bar_timer_event_posted_p;
4163 #define SCROLL_BAR_FIRST_DELAY 0.5
4164 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4166 static pascal void
4167 scroll_bar_timer_callback (timer, data)
4168 EventLoopTimerRef timer;
4169 void *data;
4171 EventRef event = NULL;
4172 OSErr err;
4174 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
4175 kEventAttributeNone, &event);
4176 if (err == noErr)
4178 Point mouse_pos;
4180 GetMouse (&mouse_pos);
4181 LocalToGlobal (&mouse_pos);
4182 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
4183 sizeof (Point), &mouse_pos);
4185 if (err == noErr)
4187 UInt32 modifiers = GetCurrentKeyModifiers ();
4189 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
4190 sizeof (UInt32), &modifiers);
4192 if (err == noErr)
4193 err = PostEventToQueue (GetCurrentEventQueue (), event,
4194 kEventPriorityStandard);
4195 if (err == noErr)
4196 scroll_bar_timer_event_posted_p = 1;
4198 if (event)
4199 ReleaseEvent (event);
4202 static OSStatus
4203 install_scroll_bar_timer ()
4205 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
4207 if (scroll_bar_timer_callbackUPP == NULL)
4208 scroll_bar_timer_callbackUPP =
4209 NewEventLoopTimerUPP (scroll_bar_timer_callback);
4211 if (scroll_bar_timer == NULL)
4212 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4213 kEventDurationForever as delays. */
4214 return
4215 InstallEventLoopTimer (GetCurrentEventLoop (),
4216 kEventDurationForever, kEventDurationForever,
4217 scroll_bar_timer_callbackUPP, NULL,
4218 &scroll_bar_timer);
4221 static OSStatus
4222 set_scroll_bar_timer (delay)
4223 EventTimerInterval delay;
4225 if (scroll_bar_timer == NULL)
4226 install_scroll_bar_timer ();
4228 scroll_bar_timer_event_posted_p = 0;
4230 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
4233 static int
4234 control_part_code_to_scroll_bar_part (part_code)
4235 ControlPartCode part_code;
4237 switch (part_code)
4239 case kControlUpButtonPart: return scroll_bar_up_arrow;
4240 case kControlDownButtonPart: return scroll_bar_down_arrow;
4241 case kControlPageUpPart: return scroll_bar_above_handle;
4242 case kControlPageDownPart: return scroll_bar_below_handle;
4243 case kControlIndicatorPart: return scroll_bar_handle;
4246 return -1;
4249 static void
4250 construct_scroll_bar_click (bar, part, timestamp, bufp)
4251 struct scroll_bar *bar;
4252 int part;
4253 unsigned long timestamp;
4254 struct input_event *bufp;
4256 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4257 bufp->frame_or_window = bar->window;
4258 bufp->arg = Qnil;
4259 bufp->part = part;
4260 bufp->code = 0;
4261 bufp->timestamp = timestamp;
4262 XSETINT (bufp->x, 0);
4263 XSETINT (bufp->y, 0);
4264 bufp->modifiers = 0;
4267 static OSErr
4268 get_control_part_bounds (ch, part_code, rect)
4269 ControlHandle ch;
4270 ControlPartCode part_code;
4271 Rect *rect;
4273 RgnHandle region = NewRgn ();
4274 OSStatus err;
4276 err = GetControlRegion (ch, part_code, region);
4277 if (err == noErr)
4278 GetRegionBounds (region, rect);
4279 DisposeRgn (region);
4281 return err;
4284 static void
4285 x_scroll_bar_handle_press (bar, part_code, timestamp, bufp)
4286 struct scroll_bar *bar;
4287 ControlPartCode part_code;
4288 unsigned long timestamp;
4289 struct input_event *bufp;
4291 int part = control_part_code_to_scroll_bar_part (part_code);
4293 if (part < 0)
4294 return;
4296 if (part != scroll_bar_handle)
4298 construct_scroll_bar_click (bar, part, timestamp, bufp);
4299 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4300 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY);
4303 last_scroll_bar_part = part;
4304 bar->dragging = Qnil;
4305 tracked_scroll_bar = bar;
4308 static void
4309 x_scroll_bar_handle_release (bar, timestamp, bufp)
4310 struct scroll_bar *bar;
4311 unsigned long timestamp;
4312 struct input_event *bufp;
4314 if (last_scroll_bar_part != scroll_bar_handle
4315 || !GC_NILP (bar->dragging))
4316 construct_scroll_bar_click (bar, scroll_bar_end_scroll, timestamp, bufp);
4318 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4319 set_scroll_bar_timer (kEventDurationForever);
4321 last_scroll_bar_part = -1;
4322 bar->dragging = Qnil;
4323 tracked_scroll_bar = NULL;
4326 static void
4327 x_scroll_bar_handle_drag (win, bar, mouse_pos, timestamp, bufp)
4328 WindowPtr win;
4329 struct scroll_bar *bar;
4330 Point mouse_pos;
4331 unsigned long timestamp;
4332 struct input_event *bufp;
4334 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4336 if (last_scroll_bar_part == scroll_bar_handle)
4338 int top, top_range;
4339 Rect r;
4341 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar),
4342 kControlIndicatorPart, &r);
4344 if (GC_NILP (bar->dragging))
4345 XSETINT (bar->dragging, mouse_pos.v - r.top);
4347 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top);
4348 top_range = (XINT (bar->track_height) - (r.bottom - r.top)) *
4349 (1.0 + (float) GetControlViewSize (ch) / GetControl32BitMaximum (ch))
4350 + .5;
4352 if (top < 0)
4353 top = 0;
4354 if (top > top_range)
4355 top = top_range;
4357 construct_scroll_bar_click (bar, scroll_bar_handle, timestamp, bufp);
4358 XSETINT (bufp->x, top);
4359 XSETINT (bufp->y, top_range);
4361 else
4363 ControlPartCode part_code;
4364 int unhilite_p = 0, part;
4366 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code))
4367 unhilite_p = 1;
4368 else
4370 part = control_part_code_to_scroll_bar_part (part_code);
4372 switch (last_scroll_bar_part)
4374 case scroll_bar_above_handle:
4375 case scroll_bar_below_handle:
4376 if (part != scroll_bar_above_handle
4377 && part != scroll_bar_below_handle)
4378 unhilite_p = 1;
4379 break;
4381 case scroll_bar_up_arrow:
4382 case scroll_bar_down_arrow:
4383 if (part != scroll_bar_up_arrow
4384 && part != scroll_bar_down_arrow)
4385 unhilite_p = 1;
4386 break;
4390 if (unhilite_p)
4391 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0);
4392 else if (part != last_scroll_bar_part
4393 || scroll_bar_timer_event_posted_p)
4395 construct_scroll_bar_click (bar, part, timestamp, bufp);
4396 last_scroll_bar_part = part;
4397 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code);
4398 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY);
4403 /* Set the thumb size and position of scroll bar BAR. We are currently
4404 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4406 static void
4407 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
4408 struct scroll_bar *bar;
4409 int portion, position, whole;
4411 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4413 int value, viewsize, maximum;
4415 if (whole == 0 || XINT (bar->track_height) == 0)
4416 value = 0, viewsize = 1, maximum = 0;
4417 else
4419 value = position;
4420 viewsize = portion;
4421 maximum = max (0, whole - portion);
4424 BLOCK_INPUT;
4426 SetControl32BitMinimum (ch, 0);
4427 SetControl32BitMaximum (ch, maximum);
4428 SetControl32BitValue (ch, value);
4429 SetControlViewSize (ch, viewsize);
4431 UNBLOCK_INPUT;
4434 #endif /* USE_TOOLKIT_SCROLL_BARS */
4438 /************************************************************************
4439 Scroll bars, general
4440 ************************************************************************/
4442 /* Create a scroll bar and return the scroll bar vector for it. W is
4443 the Emacs window on which to create the scroll bar. TOP, LEFT,
4444 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4445 scroll bar. */
4447 static struct scroll_bar *
4448 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4449 struct window *w;
4450 int top, left, width, height, disp_top, disp_height;
4452 struct frame *f = XFRAME (w->frame);
4453 struct scroll_bar *bar
4454 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4455 Rect r;
4456 ControlHandle ch;
4458 BLOCK_INPUT;
4460 r.left = left;
4461 r.top = disp_top;
4462 r.right = left + width;
4463 r.bottom = disp_top + disp_height;
4465 #if TARGET_API_MAC_CARBON
4466 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4467 kControlScrollBarProc, (long) bar);
4468 #else
4469 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4470 scrollBarProc, (long) bar);
4471 #endif
4472 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4474 XSETWINDOW (bar->window, w);
4475 XSETINT (bar->top, top);
4476 XSETINT (bar->left, left);
4477 XSETINT (bar->width, width);
4478 XSETINT (bar->height, height);
4479 XSETINT (bar->start, 0);
4480 XSETINT (bar->end, 0);
4481 bar->dragging = Qnil;
4482 #ifdef USE_TOOLKIT_SCROLL_BARS
4483 bar->track_top = Qnil;
4484 bar->track_height = Qnil;
4485 #endif
4487 /* Add bar to its frame's list of scroll bars. */
4488 bar->next = FRAME_SCROLL_BARS (f);
4489 bar->prev = Qnil;
4490 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4491 if (!NILP (bar->next))
4492 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4494 UNBLOCK_INPUT;
4495 return bar;
4499 /* Draw BAR's handle in the proper position.
4501 If the handle is already drawn from START to END, don't bother
4502 redrawing it, unless REBUILD is non-zero; in that case, always
4503 redraw it. (REBUILD is handy for drawing the handle after expose
4504 events.)
4506 Normally, we want to constrain the start and end of the handle to
4507 fit inside its rectangle, but if the user is dragging the scroll
4508 bar handle, we want to let them drag it down all the way, so that
4509 the bar's top is as far down as it goes; otherwise, there's no way
4510 to move to the very end of the buffer. */
4512 #ifndef USE_TOOLKIT_SCROLL_BARS
4514 static void
4515 x_scroll_bar_set_handle (bar, start, end, rebuild)
4516 struct scroll_bar *bar;
4517 int start, end;
4518 int rebuild;
4520 int dragging = ! NILP (bar->dragging);
4521 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4522 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4523 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4524 int length = end - start;
4526 /* If the display is already accurate, do nothing. */
4527 if (! rebuild
4528 && start == XINT (bar->start)
4529 && end == XINT (bar->end))
4530 return;
4532 BLOCK_INPUT;
4534 /* Make sure the values are reasonable, and try to preserve the
4535 distance between start and end. */
4536 if (start < 0)
4537 start = 0;
4538 else if (start > top_range)
4539 start = top_range;
4540 end = start + length;
4542 if (end < start)
4543 end = start;
4544 else if (end > top_range && ! dragging)
4545 end = top_range;
4547 /* Store the adjusted setting in the scroll bar. */
4548 XSETINT (bar->start, start);
4549 XSETINT (bar->end, end);
4551 /* Clip the end position, just for display. */
4552 if (end > top_range)
4553 end = top_range;
4555 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4556 top positions, to make sure the handle is always at least that
4557 many pixels tall. */
4558 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4560 SetControlMinimum (ch, 0);
4561 /* Don't inadvertently activate deactivated scroll bars */
4562 if (GetControlMaximum (ch) != -1)
4563 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4564 - (end - start));
4565 SetControlValue (ch, start);
4566 #if TARGET_API_MAC_CARBON
4567 SetControlViewSize (ch, end - start);
4568 #endif
4570 UNBLOCK_INPUT;
4573 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4575 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4576 nil. */
4578 static void
4579 x_scroll_bar_remove (bar)
4580 struct scroll_bar *bar;
4582 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4584 BLOCK_INPUT;
4586 /* Destroy the Mac scroll bar control */
4587 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4589 /* Disassociate this scroll bar from its window. */
4590 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4592 UNBLOCK_INPUT;
4595 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4596 that we are displaying PORTION characters out of a total of WHOLE
4597 characters, starting at POSITION. If WINDOW has no scroll bar,
4598 create one. */
4599 static void
4600 XTset_vertical_scroll_bar (w, portion, whole, position)
4601 struct window *w;
4602 int portion, whole, position;
4604 struct frame *f = XFRAME (w->frame);
4605 struct scroll_bar *bar;
4606 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4607 int window_y, window_height;
4609 /* Get window dimensions. */
4610 window_box (w, -1, 0, &window_y, 0, &window_height);
4611 top = window_y;
4612 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4613 height = window_height;
4615 /* Compute the left edge of the scroll bar area. */
4616 left = WINDOW_SCROLL_BAR_AREA_X (w);
4618 /* Compute the width of the scroll bar which might be less than
4619 the width of the area reserved for the scroll bar. */
4620 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4621 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4622 else
4623 sb_width = width;
4625 /* Compute the left edge of the scroll bar. */
4626 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4627 sb_left = left;
4628 else
4629 sb_left = left + width - sb_width;
4631 /* Adjustments according to Inside Macintosh to make it look nice */
4632 disp_top = top;
4633 disp_height = height;
4634 if (disp_top == 0)
4636 disp_top = -1;
4637 disp_height++;
4639 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4641 disp_top++;
4642 disp_height--;
4645 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4646 sb_left++;
4648 /* Does the scroll bar exist yet? */
4649 if (NILP (w->vertical_scroll_bar))
4651 BLOCK_INPUT;
4652 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4653 left, top, width, height, 0);
4654 UNBLOCK_INPUT;
4655 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4656 disp_height);
4657 XSETVECTOR (w->vertical_scroll_bar, bar);
4659 else
4661 /* It may just need to be moved and resized. */
4662 ControlHandle ch;
4664 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4665 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4667 BLOCK_INPUT;
4669 /* If already correctly positioned, do nothing. */
4670 if (!(XINT (bar->left) == sb_left
4671 && XINT (bar->top) == top
4672 && XINT (bar->width) == sb_width
4673 && XINT (bar->height) == height))
4675 /* Clear areas not covered by the scroll bar because it's not as
4676 wide as the area reserved for it . This makes sure a
4677 previous mode line display is cleared after C-x 2 C-x 1, for
4678 example. */
4679 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4680 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4681 left, top, area_width, height, 0);
4683 #if 0
4684 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4685 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4686 sb_left - 1, top, 1, height, 0);
4687 #endif
4689 HideControl (ch);
4690 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4691 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4692 disp_height);
4693 ShowControl (ch);
4695 /* Remember new settings. */
4696 XSETINT (bar->left, sb_left);
4697 XSETINT (bar->top, top);
4698 XSETINT (bar->width, sb_width);
4699 XSETINT (bar->height, height);
4700 #ifdef USE_TOOLKIT_SCROLL_BARS
4701 bar->track_top = Qnil;
4702 bar->track_height = Qnil;
4703 #endif
4706 UNBLOCK_INPUT;
4709 #ifdef USE_TOOLKIT_SCROLL_BARS
4710 if (NILP (bar->track_top))
4712 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4713 Rect r0, r1;
4715 BLOCK_INPUT;
4717 SetControl32BitMinimum (ch, 0);
4718 SetControl32BitMaximum (ch, 1);
4719 SetControlViewSize (ch, 1);
4721 /* Move the scroll bar thumb to the top. */
4722 SetControl32BitValue (ch, 0);
4723 get_control_part_bounds (ch, kControlIndicatorPart, &r0);
4725 /* Move the scroll bar thumb to the bottom. */
4726 SetControl32BitValue (ch, 1);
4727 get_control_part_bounds (ch, kControlIndicatorPart, &r1);
4729 UnionRect (&r0, &r1, &r0);
4730 XSETINT (bar->track_top, r0.top);
4731 XSETINT (bar->track_height, r0.bottom - r0.top);
4733 UNBLOCK_INPUT;
4736 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
4737 #else /* not USE_TOOLKIT_SCROLL_BARS */
4738 /* Set the scroll bar's current state, unless we're currently being
4739 dragged. */
4740 if (NILP (bar->dragging))
4742 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4744 if (whole == 0)
4745 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4746 else
4748 int start = ((double) position * top_range) / whole;
4749 int end = ((double) (position + portion) * top_range) / whole;
4750 x_scroll_bar_set_handle (bar, start, end, 0);
4753 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4757 /* The following three hooks are used when we're doing a thorough
4758 redisplay of the frame. We don't explicitly know which scroll bars
4759 are going to be deleted, because keeping track of when windows go
4760 away is a real pain - "Can you say set-window-configuration, boys
4761 and girls?" Instead, we just assert at the beginning of redisplay
4762 that *all* scroll bars are to be removed, and then save a scroll bar
4763 from the fiery pit when we actually redisplay its window. */
4765 /* Arrange for all scroll bars on FRAME to be removed at the next call
4766 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4767 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4769 static void
4770 XTcondemn_scroll_bars (frame)
4771 FRAME_PTR frame;
4773 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4774 while (! NILP (FRAME_SCROLL_BARS (frame)))
4776 Lisp_Object bar;
4777 bar = FRAME_SCROLL_BARS (frame);
4778 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4779 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4780 XSCROLL_BAR (bar)->prev = Qnil;
4781 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4782 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4783 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4788 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4789 Note that WINDOW isn't necessarily condemned at all. */
4791 static void
4792 XTredeem_scroll_bar (window)
4793 struct window *window;
4795 struct scroll_bar *bar;
4797 /* We can't redeem this window's scroll bar if it doesn't have one. */
4798 if (NILP (window->vertical_scroll_bar))
4799 abort ();
4801 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4803 /* Unlink it from the condemned list. */
4805 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4807 if (NILP (bar->prev))
4809 /* If the prev pointer is nil, it must be the first in one of
4810 the lists. */
4811 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4812 /* It's not condemned. Everything's fine. */
4813 return;
4814 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4815 window->vertical_scroll_bar))
4816 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4817 else
4818 /* If its prev pointer is nil, it must be at the front of
4819 one or the other! */
4820 abort ();
4822 else
4823 XSCROLL_BAR (bar->prev)->next = bar->next;
4825 if (! NILP (bar->next))
4826 XSCROLL_BAR (bar->next)->prev = bar->prev;
4828 bar->next = FRAME_SCROLL_BARS (f);
4829 bar->prev = Qnil;
4830 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4831 if (! NILP (bar->next))
4832 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4836 /* Remove all scroll bars on FRAME that haven't been saved since the
4837 last call to `*condemn_scroll_bars_hook'. */
4839 static void
4840 XTjudge_scroll_bars (f)
4841 FRAME_PTR f;
4843 Lisp_Object bar, next;
4845 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4847 /* Clear out the condemned list now so we won't try to process any
4848 more events on the hapless scroll bars. */
4849 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4851 for (; ! NILP (bar); bar = next)
4853 struct scroll_bar *b = XSCROLL_BAR (bar);
4855 x_scroll_bar_remove (b);
4857 next = b->next;
4858 b->next = b->prev = Qnil;
4861 /* Now there should be no references to the condemned scroll bars,
4862 and they should get garbage-collected. */
4866 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4867 is set to something other than NO_EVENT, it is enqueued.
4869 This may be called from a signal handler, so we have to ignore GC
4870 mark bits. */
4872 static void
4873 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4874 struct scroll_bar *bar;
4875 ControlPartCode part_code;
4876 EventRecord *er;
4877 struct input_event *bufp;
4879 int win_y, top_range;
4881 if (! GC_WINDOWP (bar->window))
4882 abort ();
4884 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4885 bufp->frame_or_window = bar->window;
4886 bufp->arg = Qnil;
4888 bar->dragging = Qnil;
4890 switch (part_code)
4892 case kControlUpButtonPart:
4893 bufp->part = scroll_bar_up_arrow;
4894 break;
4895 case kControlDownButtonPart:
4896 bufp->part = scroll_bar_down_arrow;
4897 break;
4898 case kControlPageUpPart:
4899 bufp->part = scroll_bar_above_handle;
4900 break;
4901 case kControlPageDownPart:
4902 bufp->part = scroll_bar_below_handle;
4903 break;
4904 #if TARGET_API_MAC_CARBON
4905 default:
4906 #else
4907 case kControlIndicatorPart:
4908 #endif
4909 if (er->what == mouseDown)
4910 bar->dragging = make_number (0);
4911 XSETVECTOR (last_mouse_scroll_bar, bar);
4912 bufp->part = scroll_bar_handle;
4913 break;
4916 win_y = XINT (bufp->y) - XINT (bar->top);
4917 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4919 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4921 win_y -= 24;
4923 if (! NILP (bar->dragging))
4924 win_y -= XINT (bar->dragging);
4926 if (win_y < 0)
4927 win_y = 0;
4928 if (win_y > top_range)
4929 win_y = top_range;
4931 XSETINT (bufp->x, win_y);
4932 XSETINT (bufp->y, top_range);
4935 #ifndef USE_TOOLKIT_SCROLL_BARS
4937 /* Handle some mouse motion while someone is dragging the scroll bar.
4939 This may be called from a signal handler, so we have to ignore GC
4940 mark bits. */
4942 static void
4943 x_scroll_bar_note_movement (bar, y_pos, t)
4944 struct scroll_bar *bar;
4945 int y_pos;
4946 Time t;
4948 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4950 last_mouse_movement_time = t;
4952 f->mouse_moved = 1;
4953 XSETVECTOR (last_mouse_scroll_bar, bar);
4955 /* If we're dragging the bar, display it. */
4956 if (! GC_NILP (bar->dragging))
4958 /* Where should the handle be now? */
4959 int new_start = y_pos - 24;
4961 if (new_start != XINT (bar->start))
4963 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4965 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4970 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4972 /* Return information to the user about the current position of the
4973 mouse on the scroll bar. */
4975 static void
4976 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4977 FRAME_PTR *fp;
4978 Lisp_Object *bar_window;
4979 enum scroll_bar_part *part;
4980 Lisp_Object *x, *y;
4981 unsigned long *time;
4983 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4984 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4985 #if TARGET_API_MAC_CARBON
4986 WindowPtr wp = GetControlOwner (ch);
4987 #else
4988 WindowPtr wp = (*ch)->contrlOwner;
4989 #endif
4990 Point mouse_pos;
4991 struct frame *f = mac_window_to_frame (wp);
4992 int win_y, top_range;
4994 SetPortWindowPort (wp);
4996 GetMouse (&mouse_pos);
4998 win_y = mouse_pos.v - XINT (bar->top);
4999 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
5001 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
5003 win_y -= 24;
5005 if (! NILP (bar->dragging))
5006 win_y -= XINT (bar->dragging);
5008 if (win_y < 0)
5009 win_y = 0;
5010 if (win_y > top_range)
5011 win_y = top_range;
5013 *fp = f;
5014 *bar_window = bar->window;
5016 if (! NILP (bar->dragging))
5017 *part = scroll_bar_handle;
5018 else if (win_y < XINT (bar->start))
5019 *part = scroll_bar_above_handle;
5020 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
5021 *part = scroll_bar_handle;
5022 else
5023 *part = scroll_bar_below_handle;
5025 XSETINT (*x, win_y);
5026 XSETINT (*y, top_range);
5028 f->mouse_moved = 0;
5029 last_mouse_scroll_bar = Qnil;
5031 *time = last_mouse_movement_time;
5035 /* The screen has been cleared so we may have changed foreground or
5036 background colors, and the scroll bars may need to be redrawn.
5037 Clear out the scroll bars, and ask for expose events, so we can
5038 redraw them. */
5040 void
5041 x_scroll_bar_clear (f)
5042 FRAME_PTR f;
5044 XTcondemn_scroll_bars (f);
5045 XTjudge_scroll_bars (f);
5049 /***********************************************************************
5050 Text Cursor
5051 ***********************************************************************/
5053 /* Set clipping for output in glyph row ROW. W is the window in which
5054 we operate. GC is the graphics context to set clipping in.
5056 ROW may be a text row or, e.g., a mode line. Text rows must be
5057 clipped to the interior of the window dedicated to text display,
5058 mode lines must be clipped to the whole window. */
5060 static void
5061 x_clip_to_row (w, row, area, gc)
5062 struct window *w;
5063 struct glyph_row *row;
5064 int area;
5065 GC gc;
5067 struct frame *f = XFRAME (WINDOW_FRAME (w));
5068 Rect clip_rect;
5069 int window_x, window_y, window_width;
5071 window_box (w, area, &window_x, &window_y, &window_width, 0);
5073 clip_rect.left = window_x;
5074 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
5075 clip_rect.top = max (clip_rect.top, window_y);
5076 clip_rect.right = clip_rect.left + window_width;
5077 clip_rect.bottom = clip_rect.top + row->visible_height;
5079 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
5083 /* Draw a hollow box cursor on window W in glyph row ROW. */
5085 static void
5086 x_draw_hollow_cursor (w, row)
5087 struct window *w;
5088 struct glyph_row *row;
5090 struct frame *f = XFRAME (WINDOW_FRAME (w));
5091 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5092 Display *dpy = FRAME_MAC_DISPLAY (f);
5093 int x, y, wd, h;
5094 XGCValues xgcv;
5095 struct glyph *cursor_glyph;
5096 GC gc;
5098 /* Get the glyph the cursor is on. If we can't tell because
5099 the current matrix is invalid or such, give up. */
5100 cursor_glyph = get_phys_cursor_glyph (w);
5101 if (cursor_glyph == NULL)
5102 return;
5104 /* Compute frame-relative coordinates for phys cursor. */
5105 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
5106 y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
5107 wd = w->phys_cursor_width;
5109 /* The foreground of cursor_gc is typically the same as the normal
5110 background color, which can cause the cursor box to be invisible. */
5111 xgcv.foreground = f->output_data.mac->cursor_pixel;
5112 if (dpyinfo->scratch_cursor_gc)
5113 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
5114 else
5115 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
5116 GCForeground, &xgcv);
5117 gc = dpyinfo->scratch_cursor_gc;
5119 /* Set clipping, draw the rectangle, and reset clipping again. */
5120 x_clip_to_row (w, row, TEXT_AREA, gc);
5121 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
5122 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
5126 /* Draw a bar cursor on window W in glyph row ROW.
5128 Implementation note: One would like to draw a bar cursor with an
5129 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5130 Unfortunately, I didn't find a font yet that has this property set.
5131 --gerd. */
5133 static void
5134 x_draw_bar_cursor (w, row, width, kind)
5135 struct window *w;
5136 struct glyph_row *row;
5137 int width;
5138 enum text_cursor_kinds kind;
5140 struct frame *f = XFRAME (w->frame);
5141 struct glyph *cursor_glyph;
5143 /* If cursor is out of bounds, don't draw garbage. This can happen
5144 in mini-buffer windows when switching between echo area glyphs
5145 and mini-buffer. */
5146 cursor_glyph = get_phys_cursor_glyph (w);
5147 if (cursor_glyph == NULL)
5148 return;
5150 /* If on an image, draw like a normal cursor. That's usually better
5151 visible than drawing a bar, esp. if the image is large so that
5152 the bar might not be in the window. */
5153 if (cursor_glyph->type == IMAGE_GLYPH)
5155 struct glyph_row *row;
5156 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
5157 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
5159 else
5161 Display *dpy = FRAME_MAC_DISPLAY (f);
5162 Window window = FRAME_MAC_WINDOW (f);
5163 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
5164 unsigned long mask = GCForeground | GCBackground;
5165 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
5166 XGCValues xgcv;
5168 /* If the glyph's background equals the color we normally draw
5169 the bar cursor in, the bar cursor in its normal color is
5170 invisible. Use the glyph's foreground color instead in this
5171 case, on the assumption that the glyph's colors are chosen so
5172 that the glyph is legible. */
5173 if (face->background == f->output_data.mac->cursor_pixel)
5174 xgcv.background = xgcv.foreground = face->foreground;
5175 else
5176 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
5178 if (gc)
5179 XChangeGC (dpy, gc, mask, &xgcv);
5180 else
5182 gc = XCreateGC (dpy, window, mask, &xgcv);
5183 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
5186 if (width < 0)
5187 width = FRAME_CURSOR_WIDTH (f);
5188 width = min (cursor_glyph->pixel_width, width);
5190 w->phys_cursor_width = width;
5191 x_clip_to_row (w, row, TEXT_AREA, gc);
5193 if (kind == BAR_CURSOR)
5194 XFillRectangle (dpy, window, gc,
5195 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5196 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
5197 width, row->height);
5198 else
5199 XFillRectangle (dpy, window, gc,
5200 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
5201 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
5202 row->height - width),
5203 cursor_glyph->pixel_width,
5204 width);
5206 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
5211 /* RIF: Define cursor CURSOR on frame F. */
5213 static void
5214 mac_define_frame_cursor (f, cursor)
5215 struct frame *f;
5216 Cursor cursor;
5218 SetThemeCursor (cursor);
5222 /* RIF: Clear area on frame F. */
5224 static void
5225 mac_clear_frame_area (f, x, y, width, height)
5226 struct frame *f;
5227 int x, y, width, height;
5229 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
5230 x, y, width, height, 0);
5234 /* RIF: Draw cursor on window W. */
5236 static void
5237 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
5238 struct window *w;
5239 struct glyph_row *glyph_row;
5240 int x, y;
5241 int cursor_type, cursor_width;
5242 int on_p, active_p;
5244 if (on_p)
5246 w->phys_cursor_type = cursor_type;
5247 w->phys_cursor_on_p = 1;
5249 if (glyph_row->exact_window_width_line_p
5250 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
5252 glyph_row->cursor_in_fringe_p = 1;
5253 draw_fringe_bitmap (w, glyph_row, 0);
5255 else
5256 switch (cursor_type)
5258 case HOLLOW_BOX_CURSOR:
5259 x_draw_hollow_cursor (w, glyph_row);
5260 break;
5262 case FILLED_BOX_CURSOR:
5263 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
5264 break;
5266 case BAR_CURSOR:
5267 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
5268 break;
5270 case HBAR_CURSOR:
5271 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
5272 break;
5274 case NO_CURSOR:
5275 w->phys_cursor_width = 0;
5276 break;
5278 default:
5279 abort ();
5285 /* Icons. */
5287 #if 0 /* MAC_TODO: no icon support yet. */
5289 x_bitmap_icon (f, icon)
5290 struct frame *f;
5291 Lisp_Object icon;
5293 HANDLE hicon;
5295 if (FRAME_W32_WINDOW (f) == 0)
5296 return 1;
5298 if (NILP (icon))
5299 hicon = LoadIcon (hinst, EMACS_CLASS);
5300 else if (STRINGP (icon))
5301 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
5302 LR_DEFAULTSIZE | LR_LOADFROMFILE);
5303 else if (SYMBOLP (icon))
5305 LPCTSTR name;
5307 if (EQ (icon, intern ("application")))
5308 name = (LPCTSTR) IDI_APPLICATION;
5309 else if (EQ (icon, intern ("hand")))
5310 name = (LPCTSTR) IDI_HAND;
5311 else if (EQ (icon, intern ("question")))
5312 name = (LPCTSTR) IDI_QUESTION;
5313 else if (EQ (icon, intern ("exclamation")))
5314 name = (LPCTSTR) IDI_EXCLAMATION;
5315 else if (EQ (icon, intern ("asterisk")))
5316 name = (LPCTSTR) IDI_ASTERISK;
5317 else if (EQ (icon, intern ("winlogo")))
5318 name = (LPCTSTR) IDI_WINLOGO;
5319 else
5320 return 1;
5322 hicon = LoadIcon (NULL, name);
5324 else
5325 return 1;
5327 if (hicon == NULL)
5328 return 1;
5330 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
5331 (LPARAM) hicon);
5333 return 0;
5335 #endif /* MAC_TODO */
5337 /************************************************************************
5338 Handling X errors
5339 ************************************************************************/
5341 /* Display Error Handling functions not used on W32. Listing them here
5342 helps diff stay in step when comparing w32term.c with xterm.c.
5344 x_error_catcher (display, error)
5345 x_catch_errors (dpy)
5346 x_catch_errors_unwind (old_val)
5347 x_check_errors (dpy, format)
5348 x_had_errors_p (dpy)
5349 x_clear_errors (dpy)
5350 x_uncatch_errors (dpy, count)
5351 x_trace_wire ()
5352 x_connection_signal (signalnum)
5353 x_connection_closed (dpy, error_message)
5354 x_error_quitter (display, error)
5355 x_error_handler (display, error)
5356 x_io_error_quitter (display)
5361 /* Changing the font of the frame. */
5363 /* Give frame F the font named FONTNAME as its default font, and
5364 return the full name of that font. FONTNAME may be a wildcard
5365 pattern; in that case, we choose some font that fits the pattern.
5366 The return value shows which font we chose. */
5368 Lisp_Object
5369 x_new_font (f, fontname)
5370 struct frame *f;
5371 register char *fontname;
5373 struct font_info *fontp
5374 = FS_LOAD_FONT (f, 0, fontname, -1);
5376 if (!fontp)
5377 return Qnil;
5379 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5380 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5381 FRAME_FONTSET (f) = -1;
5383 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5384 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5385 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5387 compute_fringe_widths (f, 1);
5389 /* Compute the scroll bar width in character columns. */
5390 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5392 int wid = FRAME_COLUMN_WIDTH (f);
5393 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5394 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5396 else
5398 int wid = FRAME_COLUMN_WIDTH (f);
5399 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5402 /* Now make the frame display the given font. */
5403 if (FRAME_MAC_WINDOW (f) != 0)
5405 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5406 FRAME_FONT (f));
5407 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5408 FRAME_FONT (f));
5409 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5410 FRAME_FONT (f));
5412 /* Don't change the size of a tip frame; there's no point in
5413 doing it because it's done in Fx_show_tip, and it leads to
5414 problems because the tip frame has no widget. */
5415 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5416 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5419 return build_string (fontp->full_name);
5422 /* Give frame F the fontset named FONTSETNAME as its default font, and
5423 return the full name of that fontset. FONTSETNAME may be a wildcard
5424 pattern; in that case, we choose some fontset that fits the pattern.
5425 The return value shows which fontset we chose. */
5427 Lisp_Object
5428 x_new_fontset (f, fontsetname)
5429 struct frame *f;
5430 char *fontsetname;
5432 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5433 Lisp_Object result;
5435 if (fontset < 0)
5436 return Qnil;
5438 if (FRAME_FONTSET (f) == fontset)
5439 /* This fontset is already set in frame F. There's nothing more
5440 to do. */
5441 return fontset_name (fontset);
5443 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5445 if (!STRINGP (result))
5446 /* Can't load ASCII font. */
5447 return Qnil;
5449 /* Since x_new_font doesn't update any fontset information, do it now. */
5450 FRAME_FONTSET (f) = fontset;
5452 return build_string (fontsetname);
5456 /***********************************************************************
5457 TODO: W32 Input Methods
5458 ***********************************************************************/
5459 /* Listing missing functions from xterm.c helps diff stay in step.
5461 xim_destroy_callback (xim, client_data, call_data)
5462 xim_open_dpy (dpyinfo, resource_name)
5463 struct xim_inst_t
5464 xim_instantiate_callback (display, client_data, call_data)
5465 xim_initialize (dpyinfo, resource_name)
5466 xim_close_dpy (dpyinfo)
5471 void
5472 mac_get_window_bounds (f, inner, outer)
5473 struct frame *f;
5474 Rect *inner, *outer;
5476 #if TARGET_API_MAC_CARBON
5477 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5478 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5479 #else /* not TARGET_API_MAC_CARBON */
5480 RgnHandle region = NewRgn ();
5482 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5483 *inner = (*region)->rgnBBox;
5484 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5485 *outer = (*region)->rgnBBox;
5486 DisposeRgn (region);
5487 #endif /* not TARGET_API_MAC_CARBON */
5491 /* Calculate the absolute position in frame F
5492 from its current recorded position values and gravity. */
5494 void
5495 x_calc_absolute_position (f)
5496 struct frame *f;
5498 int width_diff = 0, height_diff = 0;
5499 int flags = f->size_hint_flags;
5500 Rect inner, outer;
5502 /* We have nothing to do if the current position
5503 is already for the top-left corner. */
5504 if (! ((flags & XNegative) || (flags & YNegative)))
5505 return;
5507 /* Find the offsets of the outside upper-left corner of
5508 the inner window, with respect to the outer window. */
5509 mac_get_window_bounds (f, &inner, &outer);
5511 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5512 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5514 /* Treat negative positions as relative to the leftmost bottommost
5515 position that fits on the screen. */
5516 if (flags & XNegative)
5517 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5518 - width_diff
5519 - FRAME_PIXEL_WIDTH (f)
5520 + f->left_pos);
5522 if (flags & YNegative)
5523 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5524 - height_diff
5525 - FRAME_PIXEL_HEIGHT (f)
5526 + f->top_pos);
5528 /* The left_pos and top_pos
5529 are now relative to the top and left screen edges,
5530 so the flags should correspond. */
5531 f->size_hint_flags &= ~ (XNegative | YNegative);
5534 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5535 to really change the position, and 0 when calling from
5536 x_make_frame_visible (in that case, XOFF and YOFF are the current
5537 position values). It is -1 when calling from x_set_frame_parameters,
5538 which means, do adjust for borders but don't change the gravity. */
5540 void
5541 x_set_offset (f, xoff, yoff, change_gravity)
5542 struct frame *f;
5543 register int xoff, yoff;
5544 int change_gravity;
5546 if (change_gravity > 0)
5548 f->top_pos = yoff;
5549 f->left_pos = xoff;
5550 f->size_hint_flags &= ~ (XNegative | YNegative);
5551 if (xoff < 0)
5552 f->size_hint_flags |= XNegative;
5553 if (yoff < 0)
5554 f->size_hint_flags |= YNegative;
5555 f->win_gravity = NorthWestGravity;
5557 x_calc_absolute_position (f);
5559 BLOCK_INPUT;
5560 x_wm_set_size_hint (f, (long) 0, 0);
5562 #if TARGET_API_MAC_CARBON
5563 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5564 /* If the title bar is completely outside the screen, adjust the
5565 position. */
5566 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5567 kWindowConstrainMoveRegardlessOfFit
5568 | kWindowConstrainAllowPartial, NULL, NULL);
5569 x_real_positions (f, &f->left_pos, &f->top_pos);
5570 #else
5572 Rect inner, outer, screen_rect, dummy;
5573 RgnHandle region = NewRgn ();
5575 mac_get_window_bounds (f, &inner, &outer);
5576 f->x_pixels_diff = inner.left - outer.left;
5577 f->y_pixels_diff = inner.top - outer.top;
5578 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5579 f->top_pos + f->y_pixels_diff, false);
5581 /* If the title bar is completely outside the screen, adjust the
5582 position. The variable `outer' holds the title bar rectangle.
5583 The variable `inner' holds slightly smaller one than `outer',
5584 so that the calculation of overlapping may not become too
5585 strict. */
5586 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5587 outer = (*region)->rgnBBox;
5588 DisposeRgn (region);
5589 inner = outer;
5590 InsetRect (&inner, 8, 8);
5591 screen_rect = qd.screenBits.bounds;
5592 screen_rect.top += GetMBarHeight ();
5594 if (!SectRect (&inner, &screen_rect, &dummy))
5596 if (inner.right <= screen_rect.left)
5597 f->left_pos = screen_rect.left;
5598 else if (inner.left >= screen_rect.right)
5599 f->left_pos = screen_rect.right - (outer.right - outer.left);
5601 if (inner.bottom <= screen_rect.top)
5602 f->top_pos = screen_rect.top;
5603 else if (inner.top >= screen_rect.bottom)
5604 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5606 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5607 f->top_pos + f->y_pixels_diff, false);
5610 #endif
5612 UNBLOCK_INPUT;
5615 /* Call this to change the size of frame F's x-window.
5616 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5617 for this size change and subsequent size changes.
5618 Otherwise we leave the window gravity unchanged. */
5620 void
5621 x_set_window_size (f, change_gravity, cols, rows)
5622 struct frame *f;
5623 int change_gravity;
5624 int cols, rows;
5626 int pixelwidth, pixelheight;
5628 BLOCK_INPUT;
5630 check_frame_size (f, &rows, &cols);
5631 f->scroll_bar_actual_width
5632 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5634 compute_fringe_widths (f, 0);
5636 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5637 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5639 f->win_gravity = NorthWestGravity;
5640 x_wm_set_size_hint (f, (long) 0, 0);
5642 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5643 #if TARGET_API_MAC_CARBON
5644 if (f->output_data.mac->hourglass_control)
5645 MoveControl (f->output_data.mac->hourglass_control,
5646 pixelwidth - HOURGLASS_WIDTH, 0);
5647 #endif
5649 /* Now, strictly speaking, we can't be sure that this is accurate,
5650 but the window manager will get around to dealing with the size
5651 change request eventually, and we'll hear how it went when the
5652 ConfigureNotify event gets here.
5654 We could just not bother storing any of this information here,
5655 and let the ConfigureNotify event set everything up, but that
5656 might be kind of confusing to the Lisp code, since size changes
5657 wouldn't be reported in the frame parameters until some random
5658 point in the future when the ConfigureNotify event arrives.
5660 We pass 1 for DELAY since we can't run Lisp code inside of
5661 a BLOCK_INPUT. */
5662 change_frame_size (f, rows, cols, 0, 1, 0);
5663 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5664 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5666 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5667 receive in the ConfigureNotify event; if we get what we asked
5668 for, then the event won't cause the screen to become garbaged, so
5669 we have to make sure to do it here. */
5670 SET_FRAME_GARBAGED (f);
5672 XFlush (FRAME_X_DISPLAY (f));
5674 /* If cursor was outside the new size, mark it as off. */
5675 mark_window_cursors_off (XWINDOW (f->root_window));
5677 /* Clear out any recollection of where the mouse highlighting was,
5678 since it might be in a place that's outside the new frame size.
5679 Actually checking whether it is outside is a pain in the neck,
5680 so don't try--just let the highlighting be done afresh with new size. */
5681 cancel_mouse_face (f);
5683 UNBLOCK_INPUT;
5686 /* Mouse warping. */
5688 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5690 void
5691 x_set_mouse_position (f, x, y)
5692 struct frame *f;
5693 int x, y;
5695 int pix_x, pix_y;
5697 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5698 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5700 if (pix_x < 0) pix_x = 0;
5701 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5703 if (pix_y < 0) pix_y = 0;
5704 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5706 x_set_mouse_pixel_position (f, pix_x, pix_y);
5709 void
5710 x_set_mouse_pixel_position (f, pix_x, pix_y)
5711 struct frame *f;
5712 int pix_x, pix_y;
5714 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5715 BLOCK_INPUT;
5717 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5718 0, 0, 0, 0, pix_x, pix_y);
5719 UNBLOCK_INPUT;
5720 #endif
5724 /* focus shifting, raising and lowering. */
5726 void
5727 x_focus_on_frame (f)
5728 struct frame *f;
5730 #if 0 /* This proves to be unpleasant. */
5731 x_raise_frame (f);
5732 #endif
5733 #if 0
5734 /* I don't think that the ICCCM allows programs to do things like this
5735 without the interaction of the window manager. Whatever you end up
5736 doing with this code, do it to x_unfocus_frame too. */
5737 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5738 RevertToPointerRoot, CurrentTime);
5739 #endif /* ! 0 */
5742 void
5743 x_unfocus_frame (f)
5744 struct frame *f;
5748 /* Raise frame F. */
5749 void
5750 x_raise_frame (f)
5751 struct frame *f;
5753 if (f->async_visible)
5755 BLOCK_INPUT;
5756 SelectWindow (FRAME_MAC_WINDOW (f));
5757 UNBLOCK_INPUT;
5761 /* Lower frame F. */
5762 void
5763 x_lower_frame (f)
5764 struct frame *f;
5766 if (f->async_visible)
5768 BLOCK_INPUT;
5769 SendBehind (FRAME_MAC_WINDOW (f), nil);
5770 UNBLOCK_INPUT;
5774 static void
5775 XTframe_raise_lower (f, raise_flag)
5776 FRAME_PTR f;
5777 int raise_flag;
5779 if (raise_flag)
5780 x_raise_frame (f);
5781 else
5782 x_lower_frame (f);
5785 /* Change of visibility. */
5787 /* This tries to wait until the frame is really visible.
5788 However, if the window manager asks the user where to position
5789 the frame, this will return before the user finishes doing that.
5790 The frame will not actually be visible at that time,
5791 but it will become visible later when the window manager
5792 finishes with it. */
5794 void
5795 x_make_frame_visible (f)
5796 struct frame *f;
5798 Lisp_Object type;
5799 int original_top, original_left;
5801 BLOCK_INPUT;
5803 if (! FRAME_VISIBLE_P (f))
5805 /* We test FRAME_GARBAGED_P here to make sure we don't
5806 call x_set_offset a second time
5807 if we get to x_make_frame_visible a second time
5808 before the window gets really visible. */
5809 if (! FRAME_ICONIFIED_P (f)
5810 && ! f->output_data.mac->asked_for_visible)
5811 x_set_offset (f, f->left_pos, f->top_pos, 0);
5813 f->output_data.mac->asked_for_visible = 1;
5815 #if TARGET_API_MAC_CARBON
5816 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5818 struct frame *sf = SELECTED_FRAME ();
5819 if (!FRAME_MAC_P (sf))
5820 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5821 kWindowCenterOnMainScreen);
5822 else
5823 RepositionWindow (FRAME_MAC_WINDOW (f),
5824 FRAME_MAC_WINDOW (sf),
5825 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5826 kWindowCascadeStartAtParentWindowScreen
5827 #else
5828 kWindowCascadeOnParentWindowScreen
5829 #endif
5831 x_real_positions (f, &f->left_pos, &f->top_pos);
5833 #endif
5834 ShowWindow (FRAME_MAC_WINDOW (f));
5837 XFlush (FRAME_MAC_DISPLAY (f));
5839 /* Synchronize to ensure Emacs knows the frame is visible
5840 before we do anything else. We do this loop with input not blocked
5841 so that incoming events are handled. */
5843 Lisp_Object frame;
5844 int count;
5846 /* This must come after we set COUNT. */
5847 UNBLOCK_INPUT;
5849 XSETFRAME (frame, f);
5851 /* Wait until the frame is visible. Process X events until a
5852 MapNotify event has been seen, or until we think we won't get a
5853 MapNotify at all.. */
5854 for (count = input_signal_count + 10;
5855 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5857 /* Force processing of queued events. */
5858 x_sync (f);
5860 /* Machines that do polling rather than SIGIO have been
5861 observed to go into a busy-wait here. So we'll fake an
5862 alarm signal to let the handler know that there's something
5863 to be read. We used to raise a real alarm, but it seems
5864 that the handler isn't always enabled here. This is
5865 probably a bug. */
5866 if (input_polling_used ())
5868 /* It could be confusing if a real alarm arrives while
5869 processing the fake one. Turn it off and let the
5870 handler reset it. */
5871 extern void poll_for_input_1 P_ ((void));
5872 int old_poll_suppress_count = poll_suppress_count;
5873 poll_suppress_count = 1;
5874 poll_for_input_1 ();
5875 poll_suppress_count = old_poll_suppress_count;
5878 /* See if a MapNotify event has been processed. */
5879 FRAME_SAMPLE_VISIBILITY (f);
5884 /* Change from mapped state to withdrawn state. */
5886 /* Make the frame visible (mapped and not iconified). */
5888 void
5889 x_make_frame_invisible (f)
5890 struct frame *f;
5892 /* Don't keep the highlight on an invisible frame. */
5893 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5894 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5896 BLOCK_INPUT;
5898 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5899 that the current position of the window is user-specified, rather than
5900 program-specified, so that when the window is mapped again, it will be
5901 placed at the same location, without forcing the user to position it
5902 by hand again (they have already done that once for this window.) */
5903 x_wm_set_size_hint (f, (long) 0, 1);
5905 HideWindow (FRAME_MAC_WINDOW (f));
5907 /* We can't distinguish this from iconification
5908 just by the event that we get from the server.
5909 So we can't win using the usual strategy of letting
5910 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5911 and synchronize with the server to make sure we agree. */
5912 f->visible = 0;
5913 FRAME_ICONIFIED_P (f) = 0;
5914 f->async_visible = 0;
5915 f->async_iconified = 0;
5917 UNBLOCK_INPUT;
5920 /* Change window state from mapped to iconified. */
5922 void
5923 x_iconify_frame (f)
5924 struct frame *f;
5926 /* Don't keep the highlight on an invisible frame. */
5927 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5928 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5930 #if 0
5931 /* Review: Since window is still visible in dock, still allow updates? */
5932 if (f->async_iconified)
5933 return;
5934 #endif
5936 BLOCK_INPUT;
5938 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5940 UNBLOCK_INPUT;
5944 /* Free X resources of frame F. */
5946 void
5947 x_free_frame_resources (f)
5948 struct frame *f;
5950 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5951 WindowPtr wp = FRAME_MAC_WINDOW (f);
5953 BLOCK_INPUT;
5955 if (wp != tip_window)
5956 remove_window_handler (wp);
5958 DisposeWindow (wp);
5959 if (wp == tip_window)
5960 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5961 closed' event. So we reset tip_window here. */
5962 tip_window = NULL;
5964 free_frame_menubar (f);
5966 if (FRAME_FACE_CACHE (f))
5967 free_frame_faces (f);
5969 x_free_gcs (f);
5971 if (FRAME_SIZE_HINTS (f))
5972 xfree (FRAME_SIZE_HINTS (f));
5974 xfree (f->output_data.mac);
5975 f->output_data.mac = NULL;
5977 if (f == dpyinfo->x_focus_frame)
5978 dpyinfo->x_focus_frame = 0;
5979 if (f == dpyinfo->x_focus_event_frame)
5980 dpyinfo->x_focus_event_frame = 0;
5981 if (f == dpyinfo->x_highlight_frame)
5982 dpyinfo->x_highlight_frame = 0;
5984 if (f == dpyinfo->mouse_face_mouse_frame)
5986 dpyinfo->mouse_face_beg_row
5987 = dpyinfo->mouse_face_beg_col = -1;
5988 dpyinfo->mouse_face_end_row
5989 = dpyinfo->mouse_face_end_col = -1;
5990 dpyinfo->mouse_face_window = Qnil;
5991 dpyinfo->mouse_face_deferred_gc = 0;
5992 dpyinfo->mouse_face_mouse_frame = 0;
5995 UNBLOCK_INPUT;
5999 /* Destroy the X window of frame F. */
6001 void
6002 x_destroy_window (f)
6003 struct frame *f;
6005 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6007 x_free_frame_resources (f);
6009 dpyinfo->reference_count--;
6013 /* Setting window manager hints. */
6015 /* Set the normal size hints for the window manager, for frame F.
6016 FLAGS is the flags word to use--or 0 meaning preserve the flags
6017 that the window now has.
6018 If USER_POSITION is nonzero, we set the USPosition
6019 flag (this is useful when FLAGS is 0). */
6020 void
6021 x_wm_set_size_hint (f, flags, user_position)
6022 struct frame *f;
6023 long flags;
6024 int user_position;
6026 int base_width, base_height, width_inc, height_inc;
6027 int min_rows = 0, min_cols = 0;
6028 XSizeHints *size_hints;
6030 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
6031 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
6032 width_inc = FRAME_COLUMN_WIDTH (f);
6033 height_inc = FRAME_LINE_HEIGHT (f);
6035 check_frame_size (f, &min_rows, &min_cols);
6037 size_hints = FRAME_SIZE_HINTS (f);
6038 if (size_hints == NULL)
6040 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
6041 bzero (size_hints, sizeof (XSizeHints));
6044 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
6045 size_hints->width_inc = width_inc;
6046 size_hints->height_inc = height_inc;
6047 size_hints->min_width = base_width + min_cols * width_inc;
6048 size_hints->min_height = base_height + min_rows * height_inc;
6049 size_hints->base_width = base_width;
6050 size_hints->base_height = base_height;
6052 if (flags)
6053 size_hints->flags = flags;
6054 else if (user_position)
6056 size_hints->flags &= ~ PPosition;
6057 size_hints->flags |= USPosition;
6061 #if 0 /* MAC_TODO: hide application instead of iconify? */
6062 /* Used for IconicState or NormalState */
6064 void
6065 x_wm_set_window_state (f, state)
6066 struct frame *f;
6067 int state;
6069 #ifdef USE_X_TOOLKIT
6070 Arg al[1];
6072 XtSetArg (al[0], XtNinitialState, state);
6073 XtSetValues (f->output_data.x->widget, al, 1);
6074 #else /* not USE_X_TOOLKIT */
6075 Window window = FRAME_X_WINDOW (f);
6077 f->output_data.x->wm_hints.flags |= StateHint;
6078 f->output_data.x->wm_hints.initial_state = state;
6080 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6081 #endif /* not USE_X_TOOLKIT */
6084 void
6085 x_wm_set_icon_pixmap (f, pixmap_id)
6086 struct frame *f;
6087 int pixmap_id;
6089 Pixmap icon_pixmap;
6091 #ifndef USE_X_TOOLKIT
6092 Window window = FRAME_X_WINDOW (f);
6093 #endif
6095 if (pixmap_id > 0)
6097 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
6098 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
6100 else
6102 /* It seems there is no way to turn off use of an icon pixmap.
6103 The following line does it, only if no icon has yet been created,
6104 for some window managers. But with mwm it crashes.
6105 Some people say it should clear the IconPixmapHint bit in this case,
6106 but that doesn't work, and the X consortium said it isn't the
6107 right thing at all. Since there is no way to win,
6108 best to explicitly give up. */
6109 #if 0
6110 f->output_data.x->wm_hints.icon_pixmap = None;
6111 #else
6112 return;
6113 #endif
6116 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6119 Arg al[1];
6120 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
6121 XtSetValues (f->output_data.x->widget, al, 1);
6124 #else /* not USE_X_TOOLKIT */
6126 f->output_data.x->wm_hints.flags |= IconPixmapHint;
6127 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6129 #endif /* not USE_X_TOOLKIT */
6132 #endif /* MAC_TODO */
6134 void
6135 x_wm_set_icon_position (f, icon_x, icon_y)
6136 struct frame *f;
6137 int icon_x, icon_y;
6139 #if 0 /* MAC_TODO: no icons on Mac */
6140 #ifdef USE_X_TOOLKIT
6141 Window window = XtWindow (f->output_data.x->widget);
6142 #else
6143 Window window = FRAME_X_WINDOW (f);
6144 #endif
6146 f->output_data.x->wm_hints.flags |= IconPositionHint;
6147 f->output_data.x->wm_hints.icon_x = icon_x;
6148 f->output_data.x->wm_hints.icon_y = icon_y;
6150 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
6151 #endif /* MAC_TODO */
6155 /***********************************************************************
6156 Fonts
6157 ***********************************************************************/
6159 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6161 struct font_info *
6162 x_get_font_info (f, font_idx)
6163 FRAME_PTR f;
6164 int font_idx;
6166 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
6169 /* the global font name table */
6170 char **font_name_table = NULL;
6171 int font_name_table_size = 0;
6172 int font_name_count = 0;
6174 /* Alist linking character set strings to Mac text encoding and Emacs
6175 coding system. */
6176 static Lisp_Object Vmac_charset_info_alist;
6178 static Lisp_Object
6179 create_text_encoding_info_alist ()
6181 Lisp_Object result = Qnil, rest;
6183 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest))
6185 Lisp_Object charset_info = XCAR (rest);
6186 Lisp_Object charset, coding_system, text_encoding;
6187 Lisp_Object existing_info;
6189 if (!(CONSP (charset_info)
6190 && STRINGP (charset = XCAR (charset_info))
6191 && CONSP (XCDR (charset_info))
6192 && INTEGERP (text_encoding = XCAR (XCDR (charset_info)))
6193 && CONSP (XCDR (XCDR (charset_info)))
6194 && SYMBOLP (coding_system = XCAR (XCDR (XCDR (charset_info))))))
6195 continue;
6197 existing_info = assq_no_quit (text_encoding, result);
6198 if (NILP (existing_info))
6199 result = Fcons (list3 (text_encoding, coding_system, charset),
6200 result);
6201 else
6202 if (NILP (Fmember (charset, XCDR (XCDR (existing_info)))))
6203 XSETCDR (XCDR (existing_info),
6204 Fcons (charset, XCDR (XCDR (existing_info))));
6207 return result;
6211 static void
6212 decode_mac_font_name (name, size, coding_system)
6213 char *name;
6214 int size;
6215 Lisp_Object coding_system;
6217 struct coding_system coding;
6218 char *buf, *p;
6220 for (p = name; *p; p++)
6221 if (!isascii (*p) || iscntrl (*p))
6222 break;
6224 if (*p == '\0'
6225 || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
6226 return;
6228 setup_coding_system (coding_system, &coding);
6229 coding.src_multibyte = 0;
6230 coding.dst_multibyte = 1;
6231 coding.mode |= CODING_MODE_LAST_BLOCK;
6232 coding.composing = COMPOSITION_DISABLED;
6233 buf = (char *) alloca (size);
6235 decode_coding (&coding, name, buf, strlen (name), size - 1);
6236 bcopy (buf, name, coding.produced);
6237 name[coding.produced] = '\0';
6241 static char *
6242 mac_to_x_fontname (name, size, style, charset)
6243 char *name;
6244 int size;
6245 Style style;
6246 char *charset;
6248 char foundry[32], family[32], cs[32];
6249 char xf[256], *result, *p;
6251 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) == 3)
6252 charset = cs;
6253 else
6255 strcpy(foundry, "Apple");
6256 strcpy(family, name);
6259 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6260 foundry, family, style & bold ? "bold" : "medium",
6261 style & italic ? 'i' : 'r', size, size * 10,
6262 size ? 75 : 0, size ? 75 : 0, size * 10, charset);
6264 result = (char *) xmalloc (strlen (xf) + 1);
6265 strcpy (result, xf);
6266 for (p = result; *p; p++)
6267 *p = tolower(*p);
6268 return result;
6272 /* Convert an X font spec to the corresponding mac font name, which
6273 can then be passed to GetFNum after conversion to a Pascal string.
6274 For ordinary Mac fonts, this should just be their names, like
6275 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6276 collection contain their charset designation in their names, like
6277 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6278 names are handled accordingly. */
6279 static void
6280 x_font_name_to_mac_font_name (xf, mf, mf_decoded, style, cs)
6281 char *xf, *mf, *mf_decoded;
6282 Style *style;
6283 char *cs;
6285 char foundry[32], family[32], weight[20], slant[2], *p;
6286 Lisp_Object charset_info, coding_system = Qnil;
6287 struct coding_system coding;
6289 strcpy (mf, "");
6291 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6292 foundry, family, weight, slant, cs) != 5 &&
6293 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6294 foundry, family, weight, slant, cs) != 5)
6295 return;
6297 *style = normal;
6298 if (strcmp (weight, "bold") == 0)
6299 *style |= bold;
6300 if (*slant == 'i')
6301 *style |= italic;
6303 charset_info = Fassoc (build_string (cs), Vmac_charset_info_alist);
6304 if (!NILP (charset_info))
6306 strcpy (mf_decoded, family);
6307 coding_system = Fcar (Fcdr (Fcdr (charset_info)));
6309 else
6310 sprintf (mf_decoded, "%s-%s-%s", foundry, family, cs);
6312 for (p = mf_decoded; *p; p++)
6313 if (!isascii (*p) || iscntrl (*p))
6314 break;
6316 if (*p == '\0'
6317 || NILP (coding_system) || NILP (Fcoding_system_p (coding_system)))
6318 strcpy (mf, mf_decoded);
6319 else
6321 setup_coding_system (coding_system, &coding);
6322 coding.src_multibyte = 1;
6323 coding.dst_multibyte = 1;
6324 coding.mode |= CODING_MODE_LAST_BLOCK;
6325 encode_coding (&coding, mf_decoded, mf,
6326 strlen (mf_decoded), sizeof (Str32) - 1);
6327 mf[coding.produced] = '\0';
6332 static void
6333 add_font_name_table_entry (char *font_name)
6335 if (font_name_table_size == 0)
6337 font_name_table_size = 16;
6338 font_name_table = (char **)
6339 xmalloc (font_name_table_size * sizeof (char *));
6341 else if (font_name_count + 1 >= font_name_table_size)
6343 font_name_table_size += 16;
6344 font_name_table = (char **)
6345 xrealloc (font_name_table,
6346 font_name_table_size * sizeof (char *));
6349 font_name_table[font_name_count++] = font_name;
6352 /* Sets up the table font_name_table to contain the list of all fonts
6353 in the system the first time the table is used so that the Resource
6354 Manager need not be accessed every time this information is
6355 needed. */
6357 static void
6358 init_font_name_table ()
6360 #if TARGET_API_MAC_CARBON
6361 FMFontFamilyIterator ffi;
6362 FMFontFamilyInstanceIterator ffii;
6363 FMFontFamily ff;
6364 Lisp_Object text_encoding_info_alist;
6365 struct gcpro gcpro1;
6367 /* Create a dummy instance iterator here to avoid creating and
6368 destroying it in the loop. */
6369 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6370 return;
6371 /* Create an iterator to enumerate the font families. */
6372 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6373 != noErr)
6375 FMDisposeFontFamilyInstanceIterator (&ffii);
6376 return;
6379 text_encoding_info_alist = create_text_encoding_info_alist ();
6381 GCPRO1 (text_encoding_info_alist);
6383 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6385 Str255 name;
6386 FMFont font;
6387 FMFontStyle style;
6388 FMFontSize size;
6389 TextEncoding encoding;
6390 TextEncodingBase sc;
6391 Lisp_Object text_encoding_info;
6393 if (FMGetFontFamilyName (ff, name) != noErr)
6394 break;
6395 p2cstr (name);
6396 if (*name == '.')
6397 continue;
6399 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6400 break;
6401 sc = GetTextEncodingBase (encoding);
6402 text_encoding_info = assq_no_quit (make_number (sc),
6403 text_encoding_info_alist);
6404 if (!NILP (text_encoding_info))
6405 decode_mac_font_name (name, sizeof (name),
6406 XCAR (XCDR (text_encoding_info)));
6407 else
6408 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman),
6409 text_encoding_info_alist);
6411 /* Point the instance iterator at the current font family. */
6412 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6413 break;
6415 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6416 == noErr)
6418 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
6420 for (; !NILP (rest); rest = XCDR (rest))
6422 char *cs = SDATA (XCAR (rest));
6424 if (size == 0)
6426 add_font_name_table_entry (mac_to_x_fontname (name, size,
6427 style, cs));
6428 add_font_name_table_entry (mac_to_x_fontname (name, size,
6429 italic, cs));
6430 add_font_name_table_entry (mac_to_x_fontname (name, size,
6431 bold, cs));
6432 add_font_name_table_entry (mac_to_x_fontname (name, size,
6433 italic | bold,
6434 cs));
6436 else
6438 add_font_name_table_entry (mac_to_x_fontname (name, size,
6439 style, cs));
6445 UNGCPRO;
6447 /* Dispose of the iterators. */
6448 FMDisposeFontFamilyIterator (&ffi);
6449 FMDisposeFontFamilyInstanceIterator (&ffii);
6450 #else /* !TARGET_API_MAC_CARBON */
6451 GrafPtr port;
6452 SInt16 fontnum, old_fontnum;
6453 int num_mac_fonts = CountResources('FOND');
6454 int i, j;
6455 Handle font_handle, font_handle_2;
6456 short id, scriptcode;
6457 ResType type;
6458 Str32 name;
6459 struct FontAssoc *fat;
6460 struct AsscEntry *assc_entry;
6461 Lisp_Object text_encoding_info_alist, text_encoding_info;
6462 struct gcpro gcpro1;
6464 GetPort (&port); /* save the current font number used */
6465 old_fontnum = port->txFont;
6467 text_encoding_info_alist = create_text_encoding_info_alist ();
6469 GCPRO1 (text_encoding_info_alist);
6471 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6473 font_handle = GetIndResource ('FOND', i);
6474 if (!font_handle)
6475 continue;
6477 GetResInfo (font_handle, &id, &type, name);
6478 GetFNum (name, &fontnum);
6479 p2cstr (name);
6480 if (fontnum == 0)
6481 continue;
6483 TextFont (fontnum);
6484 scriptcode = FontToScript (fontnum);
6485 text_encoding_info = assq_no_quit (make_number (scriptcode),
6486 text_encoding_info_alist);
6487 if (!NILP (text_encoding_info))
6488 decode_mac_font_name (name, sizeof (name),
6489 XCAR (XCDR (text_encoding_info)));
6490 else
6491 text_encoding_info = assq_no_quit (make_number (smRoman),
6492 text_encoding_info_alist);
6495 HLock (font_handle);
6497 if (GetResourceSizeOnDisk (font_handle)
6498 >= sizeof (struct FamRec))
6500 fat = (struct FontAssoc *) (*font_handle
6501 + sizeof (struct FamRec));
6502 assc_entry
6503 = (struct AsscEntry *) (*font_handle
6504 + sizeof (struct FamRec)
6505 + sizeof (struct FontAssoc));
6507 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6509 Lisp_Object rest = XCDR (XCDR (text_encoding_info));
6511 for (; !NILP (rest); rest = XCDR (rest))
6513 char *cs = SDATA (XCAR (rest));
6515 add_font_name_table_entry (mac_to_x_fontname (name,
6516 assc_entry->fontSize,
6517 assc_entry->fontStyle,
6518 cs));
6523 HUnlock (font_handle);
6524 font_handle_2 = GetNextFOND (font_handle);
6525 ReleaseResource (font_handle);
6526 font_handle = font_handle_2;
6528 while (ResError () == noErr && font_handle);
6531 UNGCPRO;
6533 TextFont (old_fontnum);
6534 #endif /* !TARGET_API_MAC_CARBON */
6538 void
6539 mac_clear_font_name_table ()
6541 int i;
6543 for (i = 0; i < font_name_count; i++)
6544 xfree (font_name_table[i]);
6545 xfree (font_name_table);
6546 font_name_table = NULL;
6547 font_name_table_size = font_name_count = 0;
6551 enum xlfd_scalable_field_index
6553 XLFD_SCL_PIXEL_SIZE,
6554 XLFD_SCL_POINT_SIZE,
6555 XLFD_SCL_AVGWIDTH,
6556 XLFD_SCL_LAST
6559 static int xlfd_scalable_fields[] =
6561 6, /* PIXEL_SIZE */
6562 7, /* POINT_SIZE */
6563 11, /* AVGWIDTH */
6567 static Lisp_Object
6568 mac_c_string_match (regexp, string, nonspecial, exact)
6569 Lisp_Object regexp;
6570 const char *string, *nonspecial;
6571 int exact;
6573 if (exact)
6575 if (strcmp (string, nonspecial) == 0)
6576 return build_string (string);
6578 else if (strstr (string, nonspecial))
6580 Lisp_Object str = build_string (string);
6582 if (fast_string_match (regexp, str) >= 0)
6583 return str;
6586 return Qnil;
6589 static Lisp_Object
6590 mac_do_list_fonts (pattern, maxnames)
6591 char *pattern;
6592 int maxnames;
6594 int i, n_fonts = 0;
6595 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6596 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6597 char scaled[256];
6598 char *ptr;
6599 int scl_val[XLFD_SCL_LAST], *field, *val;
6600 char *longest_start, *cur_start, *nonspecial;
6601 int longest_len, exact;
6603 if (font_name_table == NULL) /* Initialize when first used. */
6604 init_font_name_table ();
6606 for (i = 0; i < XLFD_SCL_LAST; i++)
6607 scl_val[i] = -1;
6609 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6610 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6611 fonts are scaled according to the specified size. */
6612 ptr = pattern;
6613 i = 0;
6614 field = xlfd_scalable_fields;
6615 val = scl_val;
6616 if (*ptr == '-')
6619 ptr++;
6620 if (i == *field)
6622 if ('0' <= *ptr && *ptr <= '9')
6624 *val = *ptr++ - '0';
6625 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6626 *val = *val * 10 + *ptr++ - '0';
6627 if (*ptr != '-')
6628 *val = -1;
6630 field++;
6631 val++;
6633 ptr = strchr (ptr, '-');
6634 i++;
6636 while (ptr && i < 14);
6638 if (i == 14 && ptr == NULL)
6640 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0)
6641 scl_val[XLFD_SCL_PIXEL_SIZE] =
6642 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10
6643 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10
6644 : -1));
6645 if (scl_val[XLFD_SCL_POINT_SIZE] < 0)
6646 scl_val[XLFD_SCL_POINT_SIZE] =
6647 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
6648 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH]
6649 : -1));
6650 if (scl_val[XLFD_SCL_AVGWIDTH] < 0)
6651 scl_val[XLFD_SCL_AVGWIDTH] =
6652 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10
6653 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE]
6654 : -1));
6656 else
6657 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6659 ptr = regex;
6660 *ptr++ = '^';
6662 longest_start = cur_start = ptr;
6663 longest_len = 0;
6664 exact = 1;
6666 /* Turn pattern into a regexp and do a regexp match. Also find the
6667 longest substring containing no special characters. */
6668 for (; *pattern; pattern++)
6670 if (*pattern == '?' || *pattern == '*')
6672 if (ptr - cur_start > longest_len)
6674 longest_start = cur_start;
6675 longest_len = ptr - cur_start;
6677 exact = 0;
6679 if (*pattern == '?')
6680 *ptr++ = '.';
6681 else /* if (*pattern == '*') */
6683 *ptr++ = '.';
6684 *ptr++ = '*';
6686 cur_start = ptr;
6688 else
6689 *ptr++ = tolower (*pattern);
6692 if (ptr - cur_start > longest_len)
6694 longest_start = cur_start;
6695 longest_len = ptr - cur_start;
6698 *ptr = '$';
6699 *(ptr + 1) = '\0';
6701 nonspecial = xmalloc (longest_len + 1);
6702 strncpy (nonspecial, longest_start, longest_len);
6703 nonspecial[longest_len] = '\0';
6705 pattern_regex = build_string (regex);
6707 for (i = 0; i < font_name_count; i++)
6709 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6710 nonspecial, exact);
6711 if (!NILP (fontname))
6713 font_list = Fcons (fontname, font_list);
6714 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6715 break;
6717 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6718 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-")))
6720 int former_len = ptr - font_name_table[i];
6722 memcpy (scaled, font_name_table[i], former_len);
6723 sprintf (scaled + former_len,
6724 "-%d-%d-75-75-m-%d-%s",
6725 scl_val[XLFD_SCL_PIXEL_SIZE],
6726 scl_val[XLFD_SCL_POINT_SIZE],
6727 scl_val[XLFD_SCL_AVGWIDTH],
6728 ptr + sizeof ("-0-0-0-0-m-0-") - 1);
6729 fontname = mac_c_string_match (pattern_regex, scaled,
6730 nonspecial, exact);
6731 if (!NILP (fontname))
6733 font_list = Fcons (fontname, font_list);
6734 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6735 break;
6740 xfree (nonspecial);
6742 return font_list;
6745 /* Return a list of names of available fonts matching PATTERN on frame F.
6747 Frame F null means we have not yet created any frame on Mac, and
6748 consult the first display in x_display_list. MAXNAMES sets a limit
6749 on how many fonts to match. */
6751 Lisp_Object
6752 x_list_fonts (f, pattern, size, maxnames)
6753 struct frame *f;
6754 Lisp_Object pattern;
6755 int size, maxnames;
6757 Lisp_Object list = Qnil, patterns, tem, key;
6758 struct mac_display_info *dpyinfo
6759 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list;
6761 xassert (size <= 0);
6763 patterns = Fassoc (pattern, Valternate_fontname_alist);
6764 if (NILP (patterns))
6765 patterns = Fcons (pattern, Qnil);
6767 for (; CONSP (patterns); patterns = XCDR (patterns))
6769 pattern = XCAR (patterns);
6771 if (!STRINGP (pattern))
6772 continue;
6774 tem = XCAR (XCDR (dpyinfo->name_list_element));
6775 key = Fcons (pattern, make_number (maxnames));
6777 list = Fassoc (key, tem);
6778 if (!NILP (list))
6780 list = Fcdr_safe (list);
6781 /* We have a cashed list. Don't have to get the list again. */
6782 goto label_cached;
6785 BLOCK_INPUT;
6786 list = mac_do_list_fonts (SDATA (pattern), maxnames);
6787 UNBLOCK_INPUT;
6789 /* MAC_TODO: add code for matching outline fonts here */
6791 /* Now store the result in the cache. */
6792 XSETCAR (XCDR (dpyinfo->name_list_element),
6793 Fcons (Fcons (key, list),
6794 XCAR (XCDR (dpyinfo->name_list_element))));
6796 label_cached:
6797 if (NILP (list)) continue; /* Try the remaining alternatives. */
6800 return list;
6804 #if GLYPH_DEBUG
6806 /* Check that FONT is valid on frame F. It is if it can be found in F's
6807 font table. */
6809 static void
6810 x_check_font (f, font)
6811 struct frame *f;
6812 XFontStruct *font;
6814 int i;
6815 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6817 xassert (font != NULL);
6819 for (i = 0; i < dpyinfo->n_fonts; i++)
6820 if (dpyinfo->font_table[i].name
6821 && font == dpyinfo->font_table[i].font)
6822 break;
6824 xassert (i < dpyinfo->n_fonts);
6827 #endif /* GLYPH_DEBUG != 0 */
6829 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6830 Note: There are (broken) X fonts out there with invalid XFontStruct
6831 min_bounds contents. For example, handa@etl.go.jp reports that
6832 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6833 have font->min_bounds.width == 0. */
6835 static INLINE void
6836 x_font_min_bounds (font, w, h)
6837 MacFontStruct *font;
6838 int *w, *h;
6840 *h = FONT_HEIGHT (font);
6841 *w = font->min_bounds.width;
6845 /* Compute the smallest character width and smallest font height over
6846 all fonts available on frame F. Set the members smallest_char_width
6847 and smallest_font_height in F's x_display_info structure to
6848 the values computed. Value is non-zero if smallest_font_height or
6849 smallest_char_width become smaller than they were before. */
6852 x_compute_min_glyph_bounds (f)
6853 struct frame *f;
6855 int i;
6856 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6857 MacFontStruct *font;
6858 int old_width = dpyinfo->smallest_char_width;
6859 int old_height = dpyinfo->smallest_font_height;
6861 dpyinfo->smallest_font_height = 100000;
6862 dpyinfo->smallest_char_width = 100000;
6864 for (i = 0; i < dpyinfo->n_fonts; ++i)
6865 if (dpyinfo->font_table[i].name)
6867 struct font_info *fontp = dpyinfo->font_table + i;
6868 int w, h;
6870 font = (MacFontStruct *) fontp->font;
6871 xassert (font != (MacFontStruct *) ~0);
6872 x_font_min_bounds (font, &w, &h);
6874 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6875 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6878 xassert (dpyinfo->smallest_char_width > 0
6879 && dpyinfo->smallest_font_height > 0);
6881 return (dpyinfo->n_fonts == 1
6882 || dpyinfo->smallest_char_width < old_width
6883 || dpyinfo->smallest_font_height < old_height);
6887 /* Determine whether given string is a fully-specified XLFD: all 14
6888 fields are present, none is '*'. */
6890 static int
6891 is_fully_specified_xlfd (char *p)
6893 int i;
6894 char *q;
6896 if (*p != '-')
6897 return 0;
6899 for (i = 0; i < 13; i++)
6901 q = strchr (p + 1, '-');
6902 if (q == NULL)
6903 return 0;
6904 if (q - p == 2 && *(p + 1) == '*')
6905 return 0;
6906 p = q;
6909 if (strchr (p + 1, '-') != NULL)
6910 return 0;
6912 if (*(p + 1) == '*' && *(p + 2) == '\0')
6913 return 0;
6915 return 1;
6919 const int kDefaultFontSize = 12;
6922 /* XLoadQueryFont creates and returns an internal representation for a
6923 font in a MacFontStruct struct. There is really no concept
6924 corresponding to "loading" a font on the Mac. But we check its
6925 existence and find the font number and all other information for it
6926 and store them in the returned MacFontStruct. */
6928 static MacFontStruct *
6929 XLoadQueryFont (Display *dpy, char *fontname)
6931 int i, size, point_size, avgwidth, is_two_byte_font, char_width;
6932 char *name;
6933 GrafPtr port;
6934 SInt16 old_fontnum, old_fontsize;
6935 Style old_fontface;
6936 Str32 mfontname, mfontname_decoded, charset;
6937 SInt16 fontnum;
6938 Style fontface;
6939 #if TARGET_API_MAC_CARBON
6940 TextEncoding encoding;
6941 int scriptcode;
6942 #else
6943 short scriptcode;
6944 #endif
6945 MacFontStruct *font;
6946 FontInfo the_fontinfo;
6947 #ifdef MAC_OSX
6948 UInt32 old_flags, new_flags;
6949 #endif
6951 if (is_fully_specified_xlfd (fontname))
6952 name = fontname;
6953 else
6955 Lisp_Object matched_fonts;
6957 matched_fonts = mac_do_list_fonts (fontname, 1);
6958 if (NILP (matched_fonts))
6959 return NULL;
6960 name = SDATA (XCAR (matched_fonts));
6963 GetPort (&port); /* save the current font number used */
6964 #if TARGET_API_MAC_CARBON
6965 old_fontnum = GetPortTextFont (port);
6966 old_fontsize = GetPortTextSize (port);
6967 old_fontface = GetPortTextFace (port);
6968 #else
6969 old_fontnum = port->txFont;
6970 old_fontsize = port->txSize;
6971 old_fontface = port->txFace;
6972 #endif
6974 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size, &point_size, &avgwidth) != 3)
6975 size = 0;
6976 else
6978 if (size == 0)
6979 if (point_size > 0)
6980 size = point_size / 10;
6981 else if (avgwidth > 0)
6982 size = avgwidth / 10;
6984 if (size == 0)
6985 size = kDefaultFontSize;
6987 x_font_name_to_mac_font_name (name, mfontname, mfontname_decoded,
6988 &fontface, charset);
6989 c2pstr (mfontname);
6990 #if TARGET_API_MAC_CARBON
6991 fontnum = FMGetFontFamilyFromName (mfontname);
6992 if (fontnum == kInvalidFontFamily
6993 || FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr)
6994 return NULL;
6995 scriptcode = GetTextEncodingBase (encoding);
6996 #else
6997 GetFNum (mfontname, &fontnum);
6998 if (fontnum == 0)
6999 return NULL;
7000 scriptcode = FontToScript (fontnum);
7001 #endif
7003 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
7005 font->mac_fontnum = fontnum;
7006 font->mac_fontsize = size;
7007 font->mac_fontface = fontface;
7008 font->mac_scriptcode = scriptcode;
7010 /* Apple Japanese (SJIS) font is listed as both
7011 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7012 (Roman script) in init_font_name_table (). The latter should be
7013 treated as a one-byte font. */
7014 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0)
7015 font->mac_scriptcode = smRoman;
7017 font->full_name = mac_to_x_fontname (mfontname_decoded, size, fontface, charset);
7019 is_two_byte_font = font->mac_scriptcode == smJapanese ||
7020 font->mac_scriptcode == smTradChinese ||
7021 font->mac_scriptcode == smSimpChinese ||
7022 font->mac_scriptcode == smKorean;
7024 TextFont (fontnum);
7025 TextSize (size);
7026 TextFace (fontface);
7028 GetFontInfo (&the_fontinfo);
7030 font->ascent = the_fontinfo.ascent;
7031 font->descent = the_fontinfo.descent;
7033 font->min_byte1 = 0;
7034 if (is_two_byte_font)
7035 font->max_byte1 = 1;
7036 else
7037 font->max_byte1 = 0;
7038 font->min_char_or_byte2 = 0x20;
7039 font->max_char_or_byte2 = 0xff;
7041 if (is_two_byte_font)
7043 /* Use the width of an "ideographic space" of that font because
7044 the_fontinfo.widMax returns the wrong width for some fonts. */
7045 switch (font->mac_scriptcode)
7047 case smJapanese:
7048 char_width = StringWidth("\p\x81\x40");
7049 break;
7050 case smTradChinese:
7051 char_width = StringWidth("\p\xa1\x40");
7052 break;
7053 case smSimpChinese:
7054 char_width = StringWidth("\p\xa1\xa1");
7055 break;
7056 case smKorean:
7057 char_width = StringWidth("\p\xa1\xa1");
7058 break;
7061 else
7062 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7063 returns 15 for 12-point Monaco! */
7064 char_width = CharWidth ('m');
7066 if (is_two_byte_font)
7068 font->per_char = NULL;
7070 if (fontface & italic)
7071 font->max_bounds.rbearing = char_width + 1;
7072 else
7073 font->max_bounds.rbearing = char_width;
7074 font->max_bounds.lbearing = 0;
7075 font->max_bounds.width = char_width;
7076 font->max_bounds.ascent = the_fontinfo.ascent;
7077 font->max_bounds.descent = the_fontinfo.descent;
7079 font->min_bounds = font->max_bounds;
7081 else
7083 font->per_char = (XCharStruct *)
7084 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
7086 int c, min_width, max_width;
7087 Rect char_bounds, min_bounds, max_bounds;
7088 char ch;
7090 min_width = max_width = char_width;
7091 SetRect (&min_bounds, -32767, -32767, 32767, 32767);
7092 SetRect (&max_bounds, 0, 0, 0, 0);
7093 for (c = 0x20; c <= 0xff; c++)
7095 ch = c;
7096 char_width = CharWidth (ch);
7097 QDTextBounds (1, &ch, &char_bounds);
7098 STORE_XCHARSTRUCT (font->per_char[c - 0x20],
7099 char_width, char_bounds);
7100 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7101 character width of 0x7f. */
7102 if (char_width > 0)
7104 min_width = min (min_width, char_width);
7105 max_width = max (max_width, char_width);
7107 if (!EmptyRect (&char_bounds))
7109 SetRect (&min_bounds,
7110 max (min_bounds.left, char_bounds.left),
7111 max (min_bounds.top, char_bounds.top),
7112 min (min_bounds.right, char_bounds.right),
7113 min (min_bounds.bottom, char_bounds.bottom));
7114 UnionRect (&max_bounds, &char_bounds, &max_bounds);
7117 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
7118 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
7119 if (min_width == max_width
7120 && max_bounds.left >= 0 && max_bounds.right <= max_width)
7122 /* Fixed width and no overhangs. */
7123 xfree (font->per_char);
7124 font->per_char = NULL;
7129 TextFont (old_fontnum); /* restore previous font number, size and face */
7130 TextSize (old_fontsize);
7131 TextFace (old_fontface);
7133 return font;
7137 void
7138 mac_unload_font (dpyinfo, font)
7139 struct mac_display_info *dpyinfo;
7140 XFontStruct *font;
7142 xfree (font->full_name);
7143 if (font->per_char)
7144 xfree (font->per_char);
7145 xfree (font);
7149 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7150 pointer to the structure font_info while allocating it dynamically.
7151 If SIZE is 0, load any size of font.
7152 If loading is failed, return NULL. */
7154 struct font_info *
7155 x_load_font (f, fontname, size)
7156 struct frame *f;
7157 register char *fontname;
7158 int size;
7160 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7161 Lisp_Object font_names;
7163 /* Get a list of all the fonts that match this name. Once we
7164 have a list of matching fonts, we compare them against the fonts
7165 we already have by comparing names. */
7166 font_names = x_list_fonts (f, build_string (fontname), size, 1);
7168 if (!NILP (font_names))
7170 Lisp_Object tail;
7171 int i;
7173 for (i = 0; i < dpyinfo->n_fonts; i++)
7174 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
7175 if (dpyinfo->font_table[i].name
7176 && (!strcmp (dpyinfo->font_table[i].name,
7177 SDATA (XCAR (tail)))
7178 || !strcmp (dpyinfo->font_table[i].full_name,
7179 SDATA (XCAR (tail)))))
7180 return (dpyinfo->font_table + i);
7182 else
7183 return NULL;
7185 /* Load the font and add it to the table. */
7187 char *full_name;
7188 struct MacFontStruct *font;
7189 struct font_info *fontp;
7190 unsigned long value;
7191 int i;
7193 fontname = (char *) SDATA (XCAR (font_names));
7195 BLOCK_INPUT;
7196 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
7197 UNBLOCK_INPUT;
7198 if (!font)
7199 return NULL;
7201 /* Find a free slot in the font table. */
7202 for (i = 0; i < dpyinfo->n_fonts; ++i)
7203 if (dpyinfo->font_table[i].name == NULL)
7204 break;
7206 /* If no free slot found, maybe enlarge the font table. */
7207 if (i == dpyinfo->n_fonts
7208 && dpyinfo->n_fonts == dpyinfo->font_table_size)
7210 int sz;
7211 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
7212 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
7213 dpyinfo->font_table
7214 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
7217 fontp = dpyinfo->font_table + i;
7218 if (i == dpyinfo->n_fonts)
7219 ++dpyinfo->n_fonts;
7221 /* Now fill in the slots of *FONTP. */
7222 BLOCK_INPUT;
7223 bzero (fontp, sizeof (*fontp));
7224 fontp->font = font;
7225 fontp->font_idx = i;
7226 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
7227 bcopy (fontname, fontp->name, strlen (fontname) + 1);
7229 if (font->min_bounds.width == font->max_bounds.width)
7231 /* Fixed width font. */
7232 fontp->average_width = fontp->space_width = font->min_bounds.width;
7234 else
7236 XChar2b char2b;
7237 XCharStruct *pcm;
7239 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
7240 pcm = mac_per_char_metric (font, &char2b, 0);
7241 if (pcm)
7242 fontp->space_width = pcm->width;
7243 else
7244 fontp->space_width = FONT_WIDTH (font);
7246 if (pcm)
7248 int width = pcm->width;
7249 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
7250 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
7251 width += pcm->width;
7252 fontp->average_width = width / 95;
7254 else
7255 fontp->average_width = FONT_WIDTH (font);
7258 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1);
7259 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1);
7261 fontp->size = font->max_bounds.width;
7262 fontp->height = FONT_HEIGHT (font);
7264 /* For some font, ascent and descent in max_bounds field is
7265 larger than the above value. */
7266 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
7267 if (max_height > fontp->height)
7268 fontp->height = max_height;
7271 /* The slot `encoding' specifies how to map a character
7272 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7273 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7274 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7275 2:0xA020..0xFF7F). For the moment, we don't know which charset
7276 uses this font. So, we set information in fontp->encoding[1]
7277 which is never used by any charset. If mapping can't be
7278 decided, set FONT_ENCODING_NOT_DECIDED. */
7279 if (font->mac_scriptcode == smJapanese)
7280 fontp->encoding[1] = 4;
7281 else
7283 fontp->encoding[1]
7284 = (font->max_byte1 == 0
7285 /* 1-byte font */
7286 ? (font->min_char_or_byte2 < 0x80
7287 ? (font->max_char_or_byte2 < 0x80
7288 ? 0 /* 0x20..0x7F */
7289 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
7290 : 1) /* 0xA0..0xFF */
7291 /* 2-byte font */
7292 : (font->min_byte1 < 0x80
7293 ? (font->max_byte1 < 0x80
7294 ? (font->min_char_or_byte2 < 0x80
7295 ? (font->max_char_or_byte2 < 0x80
7296 ? 0 /* 0x2020..0x7F7F */
7297 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
7298 : 3) /* 0x20A0..0x7FFF */
7299 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
7300 : (font->min_char_or_byte2 < 0x80
7301 ? (font->max_char_or_byte2 < 0x80
7302 ? 2 /* 0xA020..0xFF7F */
7303 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
7304 : 1))); /* 0xA0A0..0xFFFF */
7307 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7308 fontp->baseline_offset
7309 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
7310 ? (long) value : 0);
7311 fontp->relative_compose
7312 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
7313 ? (long) value : 0);
7314 fontp->default_ascent
7315 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
7316 ? (long) value : 0);
7317 #else
7318 fontp->baseline_offset = 0;
7319 fontp->relative_compose = 0;
7320 fontp->default_ascent = 0;
7321 #endif
7323 /* Set global flag fonts_changed_p to non-zero if the font loaded
7324 has a character with a smaller width than any other character
7325 before, or if the font loaded has a smalle>r height than any
7326 other font loaded before. If this happens, it will make a
7327 glyph matrix reallocation necessary. */
7328 fonts_changed_p = x_compute_min_glyph_bounds (f);
7329 UNBLOCK_INPUT;
7330 return fontp;
7335 /* Return a pointer to struct font_info of a font named FONTNAME for
7336 frame F. If no such font is loaded, return NULL. */
7338 struct font_info *
7339 x_query_font (f, fontname)
7340 struct frame *f;
7341 register char *fontname;
7343 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7344 int i;
7346 for (i = 0; i < dpyinfo->n_fonts; i++)
7347 if (dpyinfo->font_table[i].name
7348 && (!strcmp (dpyinfo->font_table[i].name, fontname)
7349 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
7350 return (dpyinfo->font_table + i);
7351 return NULL;
7355 /* Find a CCL program for a font specified by FONTP, and set the member
7356 `encoder' of the structure. */
7358 void
7359 x_find_ccl_program (fontp)
7360 struct font_info *fontp;
7362 Lisp_Object list, elt;
7364 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7366 elt = XCAR (list);
7367 if (CONSP (elt)
7368 && STRINGP (XCAR (elt))
7369 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7370 >= 0))
7371 break;
7373 if (! NILP (list))
7375 struct ccl_program *ccl
7376 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7378 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7379 xfree (ccl);
7380 else
7381 fontp->font_encoder = ccl;
7387 /* The Mac Event loop code */
7389 #if !TARGET_API_MAC_CARBON
7390 #include <Events.h>
7391 #include <Quickdraw.h>
7392 #include <Balloons.h>
7393 #include <Devices.h>
7394 #include <Fonts.h>
7395 #include <Gestalt.h>
7396 #include <Menus.h>
7397 #include <Processes.h>
7398 #include <Sound.h>
7399 #include <ToolUtils.h>
7400 #include <TextUtils.h>
7401 #include <Dialogs.h>
7402 #include <Script.h>
7403 #include <Types.h>
7404 #include <Resources.h>
7406 #if __MWERKS__
7407 #include <unix.h>
7408 #endif
7409 #endif /* ! TARGET_API_MAC_CARBON */
7411 #define M_APPLE 128
7412 #define I_ABOUT 1
7414 #define WINDOW_RESOURCE 128
7415 #define TERM_WINDOW_RESOURCE 129
7417 #define DEFAULT_NUM_COLS 80
7419 #define MIN_DOC_SIZE 64
7420 #define MAX_DOC_SIZE 32767
7422 #if 0
7423 /* sleep time for WaitNextEvent */
7424 #define WNE_SLEEP_AT_SUSPEND 10
7425 #define WNE_SLEEP_AT_RESUME 1
7427 /* the flag appl_is_suspended is used both for determining the sleep
7428 time to be passed to WaitNextEvent and whether the cursor should be
7429 drawn when updating the display. The cursor is turned off when
7430 Emacs is suspended. Redrawing it is unnecessary and what needs to
7431 be done depends on whether the cursor lies inside or outside the
7432 redraw region. So we might as well skip drawing it when Emacs is
7433 suspended. */
7434 static Boolean app_is_suspended = false;
7435 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
7436 #endif
7438 #define EXTRA_STACK_ALLOC (256 * 1024)
7440 #define ARGV_STRING_LIST_ID 129
7441 #define ABOUT_ALERT_ID 128
7442 #define RAM_TOO_LARGE_ALERT_ID 129
7444 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7445 Lisp_Object Qreverse;
7447 /* True if using command key as meta key. */
7448 Lisp_Object Vmac_command_key_is_meta;
7450 /* Modifier associated with the option key, or nil for normal behavior. */
7451 Lisp_Object Vmac_option_modifier;
7453 /* True if the ctrl and meta keys should be reversed. */
7454 Lisp_Object Vmac_reverse_ctrl_meta;
7456 /* True if the option and command modifiers should be used to emulate
7457 a three button mouse */
7458 Lisp_Object Vmac_emulate_three_button_mouse;
7460 #if USE_CARBON_EVENTS
7461 /* True if the mouse wheel button (i.e. button 4) should map to
7462 mouse-2, instead of mouse-3. */
7463 Lisp_Object Vmac_wheel_button_is_mouse_2;
7465 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7466 for processing before Emacs sees it. */
7467 Lisp_Object Vmac_pass_command_to_system;
7469 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7470 for processing before Emacs sees it. */
7471 Lisp_Object Vmac_pass_control_to_system;
7472 #endif
7474 /* Set in term/mac-win.el to indicate that event loop can now generate
7475 drag and drop events. */
7476 Lisp_Object Qmac_ready_for_drag_n_drop;
7478 Lisp_Object drag_and_drop_file_list;
7480 Point saved_menu_event_location;
7482 /* Apple Events */
7483 static void init_required_apple_events (void);
7484 static pascal OSErr
7485 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7486 static pascal OSErr
7487 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7488 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7489 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7491 #if TARGET_API_MAC_CARBON
7492 /* Drag and Drop */
7493 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
7494 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7495 static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
7496 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
7497 #endif
7499 static Lisp_Object Qapplication, Qabout;
7500 #if USE_CARBON_EVENTS
7501 #ifdef MAC_OSX
7502 extern void init_service_handler ();
7503 static Lisp_Object Qpreferences, Qservices, Qpaste, Qperform;
7504 #endif
7505 /* Window Event Handler */
7506 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7507 EventRef, void *);
7508 #endif
7509 OSErr install_window_handler (WindowPtr);
7511 extern void init_emacs_passwd_dir ();
7512 extern int emacs_main (int, char **, char **);
7514 extern void initialize_applescript();
7515 extern void terminate_applescript();
7517 static unsigned int
7518 #if USE_CARBON_EVENTS
7519 mac_to_emacs_modifiers (UInt32 mods)
7520 #else
7521 mac_to_emacs_modifiers (EventModifiers mods)
7522 #endif
7524 unsigned int result = 0;
7525 if (mods & macShiftKey)
7526 result |= shift_modifier;
7527 if (mods & macCtrlKey)
7528 result |= ctrl_modifier;
7529 if (mods & macMetaKey)
7530 result |= meta_modifier;
7531 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7532 result |= alt_modifier;
7533 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7534 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7535 if (!NILP(val))
7536 result |= XUINT(val);
7539 return result;
7542 static int
7543 mac_get_emulated_btn ( UInt32 modifiers )
7545 int result = 0;
7546 if (!NILP (Vmac_emulate_three_button_mouse)) {
7547 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7548 if (modifiers & cmdKey)
7549 result = cmdIs3 ? 2 : 1;
7550 else if (modifiers & optionKey)
7551 result = cmdIs3 ? 1 : 2;
7553 return result;
7556 #if USE_CARBON_EVENTS
7557 /* Obtains the event modifiers from the event ref and then calls
7558 mac_to_emacs_modifiers. */
7559 static int
7560 mac_event_to_emacs_modifiers (EventRef eventRef)
7562 UInt32 mods = 0;
7563 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7564 sizeof (UInt32), NULL, &mods);
7565 if (!NILP (Vmac_emulate_three_button_mouse) &&
7566 GetEventClass(eventRef) == kEventClassMouse)
7568 mods &= ~(optionKey | cmdKey);
7570 return mac_to_emacs_modifiers (mods);
7573 /* Given an event ref, return the code to use for the mouse button
7574 code in the emacs input_event. */
7575 static int
7576 mac_get_mouse_btn (EventRef ref)
7578 EventMouseButton result = kEventMouseButtonPrimary;
7579 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7580 sizeof (EventMouseButton), NULL, &result);
7581 switch (result)
7583 case kEventMouseButtonPrimary:
7584 if (NILP (Vmac_emulate_three_button_mouse))
7585 return 0;
7586 else {
7587 UInt32 mods = 0;
7588 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7589 sizeof (UInt32), NULL, &mods);
7590 return mac_get_emulated_btn(mods);
7592 case kEventMouseButtonSecondary:
7593 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7594 case kEventMouseButtonTertiary:
7595 case 4: /* 4 is the number for the mouse wheel button */
7596 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7597 default:
7598 return 0;
7602 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7603 events. However the click of the mouse wheel is not converted to a
7604 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7605 checks to see if it is a mouse up or down carbon event that has not
7606 been converted, and if so, converts it by hand (to be picked up in
7607 the XTread_socket loop). */
7608 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7610 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7611 /* Do special case for mouse wheel button. */
7612 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7614 UInt32 kind = GetEventKind (eventRef);
7615 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7617 eventRec->what = mouseDown;
7618 result=1;
7620 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7622 eventRec->what = mouseUp;
7623 result=1;
7625 if (result)
7627 /* Need where and when. */
7628 UInt32 mods;
7629 GetEventParameter (eventRef, kEventParamMouseLocation,
7630 typeQDPoint, NULL, sizeof (Point),
7631 NULL, &eventRec->where);
7632 /* Use two step process because new event modifiers are
7633 32-bit and old are 16-bit. Currently, only loss is
7634 NumLock & Fn. */
7635 GetEventParameter (eventRef, kEventParamKeyModifiers,
7636 typeUInt32, NULL, sizeof (UInt32),
7637 NULL, &mods);
7638 eventRec->modifiers = mods;
7640 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7643 return result;
7646 #endif
7648 static void
7649 do_get_menus (void)
7651 Handle menubar_handle;
7652 MenuHandle menu_handle;
7654 menubar_handle = GetNewMBar (128);
7655 if(menubar_handle == NULL)
7656 abort ();
7657 SetMenuBar (menubar_handle);
7658 DrawMenuBar ();
7660 #if !TARGET_API_MAC_CARBON
7661 menu_handle = GetMenuHandle (M_APPLE);
7662 if(menu_handle != NULL)
7663 AppendResMenu (menu_handle,'DRVR');
7664 else
7665 abort ();
7666 #endif
7670 static void
7671 do_init_managers (void)
7673 #if !TARGET_API_MAC_CARBON
7674 InitGraf (&qd.thePort);
7675 InitFonts ();
7676 FlushEvents (everyEvent, 0);
7677 InitWindows ();
7678 InitMenus ();
7679 TEInit ();
7680 InitDialogs (NULL);
7681 #endif /* !TARGET_API_MAC_CARBON */
7682 InitCursor ();
7684 #if !TARGET_API_MAC_CARBON
7685 /* set up some extra stack space for use by emacs */
7686 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7688 /* MaxApplZone must be called for AppleScript to execute more
7689 complicated scripts */
7690 MaxApplZone ();
7691 MoreMasters ();
7692 #endif /* !TARGET_API_MAC_CARBON */
7695 static void
7696 do_check_ram_size (void)
7698 SInt32 physical_ram_size, logical_ram_size;
7700 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7701 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7702 || physical_ram_size > (1 << VALBITS)
7703 || logical_ram_size > (1 << VALBITS))
7705 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7706 exit (1);
7710 static void
7711 do_window_update (WindowPtr win)
7713 struct frame *f = mac_window_to_frame (win);
7715 BeginUpdate (win);
7717 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7718 below. */
7719 if (win != tip_window)
7721 if (f->async_visible == 0)
7723 f->async_visible = 1;
7724 f->async_iconified = 0;
7725 SET_FRAME_GARBAGED (f);
7727 /* An update event is equivalent to MapNotify on X, so report
7728 visibility changes properly. */
7729 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7730 /* Force a redisplay sooner or later to update the
7731 frame titles in case this is the second frame. */
7732 record_asynch_buffer_change ();
7734 else
7736 Rect r;
7738 #if TARGET_API_MAC_CARBON
7740 RgnHandle region = NewRgn ();
7742 GetPortVisibleRegion (GetWindowPort (win), region);
7743 GetRegionBounds (region, &r);
7744 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7745 UpdateControls (win, region);
7746 DisposeRgn (region);
7748 #else
7749 r = (*win->visRgn)->rgnBBox;
7750 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7751 UpdateControls (win, win->visRgn);
7752 #endif
7756 EndUpdate (win);
7759 static int
7760 is_emacs_window (WindowPtr win)
7762 Lisp_Object tail, frame;
7764 if (!win)
7765 return 0;
7767 FOR_EACH_FRAME (tail, frame)
7768 if (FRAME_MAC_P (XFRAME (frame)))
7769 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7770 return 1;
7772 return 0;
7775 static void
7776 do_app_resume ()
7778 /* Window-activate events will do the job. */
7779 #if 0
7780 app_is_suspended = false;
7781 app_sleep_time = WNE_SLEEP_AT_RESUME;
7782 #endif
7785 static void
7786 do_app_suspend ()
7788 /* Window-deactivate events will do the job. */
7789 #if 0
7790 app_is_suspended = true;
7791 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7792 #endif
7796 static void
7797 do_apple_menu (SInt16 menu_item)
7799 #if !TARGET_API_MAC_CARBON
7800 Str255 item_name;
7801 SInt16 da_driver_refnum;
7803 if (menu_item == I_ABOUT)
7804 NoteAlert (ABOUT_ALERT_ID, NULL);
7805 else
7807 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7808 da_driver_refnum = OpenDeskAcc (item_name);
7810 #endif /* !TARGET_API_MAC_CARBON */
7813 void
7814 do_menu_choice (SInt32 menu_choice)
7816 SInt16 menu_id, menu_item;
7818 menu_id = HiWord (menu_choice);
7819 menu_item = LoWord (menu_choice);
7821 switch (menu_id)
7823 case 0:
7824 break;
7826 case M_APPLE:
7827 do_apple_menu (menu_item);
7828 break;
7830 default:
7832 struct frame *f = mac_focus_frame (&one_mac_display_info);
7833 MenuHandle menu = GetMenuHandle (menu_id);
7834 if (menu)
7836 UInt32 refcon;
7838 GetMenuItemRefCon (menu, menu_item, &refcon);
7839 menubar_selection_callback (f, refcon);
7844 HiliteMenu (0);
7848 /* Handle drags in size box. Based on code contributed by Ben
7849 Mesander and IM - Window Manager A. */
7851 static void
7852 do_grow_window (WindowPtr w, EventRecord *e)
7854 Rect limit_rect;
7855 int rows, columns, width, height;
7856 struct frame *f = mac_window_to_frame (w);
7857 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7858 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7859 #if TARGET_API_MAC_CARBON
7860 Rect new_rect;
7861 #else
7862 long grow_size;
7863 #endif
7865 if (size_hints->flags & PMinSize)
7867 min_width = size_hints->min_width;
7868 min_height = size_hints->min_height;
7870 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
7872 #if TARGET_API_MAC_CARBON
7873 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7874 return;
7875 height = new_rect.bottom - new_rect.top;
7876 width = new_rect.right - new_rect.left;
7877 #else
7878 grow_size = GrowWindow (w, e->where, &limit_rect);
7879 /* see if it really changed size */
7880 if (grow_size == 0)
7881 return;
7882 height = HiWord (grow_size);
7883 width = LoWord (grow_size);
7884 #endif
7886 if (width != FRAME_PIXEL_WIDTH (f)
7887 || height != FRAME_PIXEL_HEIGHT (f))
7889 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7890 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7892 x_set_window_size (f, 0, columns, rows);
7897 /* Handle clicks in zoom box. Calculation of "standard state" based
7898 on code in IM - Window Manager A and code contributed by Ben
7899 Mesander. The standard state of an Emacs window is 80-characters
7900 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7902 static void
7903 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7905 GrafPtr save_port;
7906 Rect zoom_rect, port_rect;
7907 Point top_left;
7908 int w_title_height, columns, rows, width, height;
7909 struct frame *f = mac_window_to_frame (w);
7910 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7912 #if TARGET_API_MAC_CARBON
7914 Point standard_size;
7916 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7917 standard_size.v = dpyinfo->height;
7919 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7920 zoom_in_or_out = inZoomIn;
7921 else
7923 /* Adjust the standard size according to character boundaries. */
7925 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7926 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7927 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7928 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7929 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7930 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7931 && port_rect.left == zoom_rect.left
7932 && port_rect.top == zoom_rect.top)
7933 zoom_in_or_out = inZoomIn;
7934 else
7935 zoom_in_or_out = inZoomOut;
7938 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7940 #else /* not TARGET_API_MAC_CARBON */
7941 GetPort (&save_port);
7943 SetPortWindowPort (w);
7945 /* Clear window to avoid flicker. */
7946 EraseRect (&(w->portRect));
7947 if (zoom_in_or_out == inZoomOut)
7949 SetPt (&top_left, w->portRect.left, w->portRect.top);
7950 LocalToGlobal (&top_left);
7952 /* calculate height of window's title bar */
7953 w_title_height = top_left.v - 1
7954 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7956 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7957 zoom_rect = qd.screenBits.bounds;
7958 zoom_rect.top += w_title_height;
7959 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7961 zoom_rect.right = zoom_rect.left
7962 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7964 /* Adjust the standard size according to character boundaries. */
7965 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7966 zoom_rect.bottom =
7967 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7969 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7970 = zoom_rect;
7973 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
7975 SetPort (save_port);
7976 #endif /* not TARGET_API_MAC_CARBON */
7978 /* retrieve window size and update application values */
7979 #if TARGET_API_MAC_CARBON
7980 GetWindowPortBounds (w, &port_rect);
7981 #else
7982 port_rect = w->portRect;
7983 #endif
7984 height = port_rect.bottom - port_rect.top;
7985 width = port_rect.right - port_rect.left;
7987 if (width != FRAME_PIXEL_WIDTH (f)
7988 || height != FRAME_PIXEL_HEIGHT (f))
7990 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7991 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7993 change_frame_size (f, rows, columns, 0, 1, 0);
7994 SET_FRAME_GARBAGED (f);
7995 cancel_mouse_face (f);
7997 FRAME_PIXEL_WIDTH (f) = width;
7998 FRAME_PIXEL_HEIGHT (f) = height;
8000 x_real_positions (f, &f->left_pos, &f->top_pos);
8003 /* Intialize AppleEvent dispatcher table for the required events. */
8004 void
8005 init_required_apple_events ()
8007 OSErr err;
8008 long result;
8010 /* Make sure we have apple events before starting. */
8011 err = Gestalt (gestaltAppleEventsAttr, &result);
8012 if (err != noErr)
8013 abort ();
8015 if (!(result & (1 << gestaltAppleEventsPresent)))
8016 abort ();
8018 #if TARGET_API_MAC_CARBON
8019 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
8020 NewAEEventHandlerUPP
8021 ((AEEventHandlerProcPtr) do_ae_open_application),
8022 0L, false);
8023 #else
8024 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
8025 NewAEEventHandlerProc
8026 ((AEEventHandlerProcPtr) do_ae_open_application),
8027 0L, false);
8028 #endif
8029 if (err != noErr)
8030 abort ();
8032 #if TARGET_API_MAC_CARBON
8033 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
8034 NewAEEventHandlerUPP
8035 ((AEEventHandlerProcPtr) do_ae_open_documents),
8036 0L, false);
8037 #else
8038 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
8039 NewAEEventHandlerProc
8040 ((AEEventHandlerProcPtr) do_ae_open_documents),
8041 0L, false);
8042 #endif
8043 if (err != noErr)
8044 abort ();
8046 #if TARGET_API_MAC_CARBON
8047 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
8048 NewAEEventHandlerUPP
8049 ((AEEventHandlerProcPtr) do_ae_print_documents),
8050 0L, false);
8051 #else
8052 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
8053 NewAEEventHandlerProc
8054 ((AEEventHandlerProcPtr) do_ae_print_documents),
8055 0L, false);
8056 #endif
8057 if (err != noErr)
8058 abort ();
8060 #if TARGET_API_MAC_CARBON
8061 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
8062 NewAEEventHandlerUPP
8063 ((AEEventHandlerProcPtr) do_ae_quit_application),
8064 0L, false);
8065 #else
8066 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
8067 NewAEEventHandlerProc
8068 ((AEEventHandlerProcPtr) do_ae_quit_application),
8069 0L, false);
8070 #endif
8071 if (err != noErr)
8072 abort ();
8075 void
8076 mac_store_application_menu_event (event)
8077 #if USE_CARBON_EVENTS
8078 EventRef event;
8079 #else
8080 UInt32 event;
8081 #endif
8083 struct input_event buf;
8084 Lisp_Object frame, entry;
8086 EVENT_INIT (buf);
8088 XSETFRAME (frame, mac_focus_frame (&one_mac_display_info));
8089 buf.kind = MENU_BAR_EVENT;
8090 buf.frame_or_window = frame;
8091 buf.arg = frame;
8092 kbd_buffer_store_event (&buf);
8094 buf.arg = Qapplication;
8095 kbd_buffer_store_event (&buf);
8097 #if USE_CARBON_EVENTS
8098 switch (GetEventClass (event))
8100 #ifdef MAC_OSX
8101 case kEventClassService:
8102 buf.arg = Qservices;
8103 kbd_buffer_store_event (&buf);
8104 switch (GetEventKind (event))
8106 case kEventServicePaste:
8107 entry = Qpaste;
8108 break;
8110 case kEventServicePerform:
8112 OSErr err;
8113 CFStringRef message;
8115 err = GetEventParameter (event, kEventParamServiceMessageName,
8116 typeCFStringRef, NULL,
8117 sizeof (CFStringRef), NULL, &message);
8118 buf.arg = Qperform;
8119 kbd_buffer_store_event (&buf);
8120 if (err == noErr && message)
8121 entry = intern (SDATA (cfstring_to_lisp (message)));
8122 else
8123 entry = Qnil;
8125 break;
8127 default:
8128 abort ();
8130 break;
8131 #endif /* MAC_OSX */
8132 case kEventClassCommand:
8134 HICommand command;
8136 GetEventParameter(event, kEventParamDirectObject, typeHICommand,
8137 NULL, sizeof (HICommand), NULL, &command);
8138 switch (command.commandID)
8140 case kHICommandAbout:
8141 entry = Qabout;
8142 break;
8143 #ifdef MAC_OSX
8144 case kHICommandPreferences:
8145 entry = Qpreferences;
8146 break;
8147 #endif /* MAC_OSX */
8148 case kHICommandQuit:
8149 entry = Qquit;
8150 break;
8151 default:
8152 abort ();
8155 break;
8157 default:
8158 abort ();
8160 #else /* USE_CARBON_EVENTS */
8161 switch (event)
8163 case kHICommandAbout:
8164 entry = Qabout;
8165 break;
8166 case kHICommandQuit:
8167 entry = Qquit;
8168 break;
8169 default:
8170 abort ();
8172 #endif
8174 buf.arg = entry;
8175 kbd_buffer_store_event (&buf);
8178 #if USE_CARBON_EVENTS
8179 static pascal OSStatus
8180 mac_handle_command_event (next_handler, event, data)
8181 EventHandlerCallRef next_handler;
8182 EventRef event;
8183 void *data;
8185 HICommand command;
8186 OSErr result;
8188 GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL,
8189 sizeof (HICommand), NULL, &command);
8191 switch (command.commandID)
8193 case kHICommandAbout:
8194 #ifdef MAC_OSX
8195 case kHICommandPreferences:
8196 #endif /* MAC_OSX */
8197 result = CallNextEventHandler (next_handler, event);
8198 if (result != eventNotHandledErr)
8199 return result;
8201 mac_store_application_menu_event (event);
8202 return noErr;
8204 default:
8205 break;
8208 return eventNotHandledErr;
8211 static OSErr
8212 init_command_handler (window)
8213 WindowPtr window;
8215 OSErr err = noErr;
8216 EventTypeSpec specs[] = {{kEventClassCommand, kEventCommandProcess}};
8217 static EventHandlerUPP handle_command_eventUPP = NULL;
8219 if (handle_command_eventUPP == NULL)
8220 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event);
8221 return InstallApplicationEventHandler (handle_command_eventUPP,
8222 GetEventTypeCount (specs), specs,
8223 NULL, NULL);
8226 static pascal OSStatus
8227 mac_handle_window_event (next_handler, event, data)
8228 EventHandlerCallRef next_handler;
8229 EventRef event;
8230 void *data;
8232 WindowPtr wp;
8233 OSStatus result;
8234 UInt32 attributes;
8235 XSizeHints *size_hints;
8237 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
8238 NULL, sizeof (WindowPtr), NULL, &wp);
8240 switch (GetEventKind (event))
8242 case kEventWindowUpdate:
8243 result = CallNextEventHandler (next_handler, event);
8244 if (result != eventNotHandledErr)
8245 return result;
8247 do_window_update (wp);
8248 return noErr;
8250 case kEventWindowBoundsChanging:
8251 result = CallNextEventHandler (next_handler, event);
8252 if (result != eventNotHandledErr)
8253 return result;
8255 GetEventParameter (event, kEventParamAttributes, typeUInt32,
8256 NULL, sizeof (UInt32), NULL, &attributes);
8257 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
8258 if ((attributes & kWindowBoundsChangeUserResize)
8259 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
8260 == (PResizeInc | PBaseSize | PMinSize)))
8262 Rect bounds;
8263 int width, height;
8265 GetEventParameter (event, kEventParamCurrentBounds,
8266 typeQDRectangle,
8267 NULL, sizeof (Rect), NULL, &bounds);
8268 width = bounds.right - bounds.left;
8269 height = bounds.bottom - bounds.top;
8271 if (width < size_hints->min_width)
8272 width = size_hints->min_width;
8273 else
8274 width = size_hints->base_width
8275 + (int) ((width - size_hints->base_width)
8276 / (float) size_hints->width_inc + .5)
8277 * size_hints->width_inc;
8279 if (height < size_hints->min_height)
8280 height = size_hints->min_height;
8281 else
8282 height = size_hints->base_height
8283 + (int) ((height - size_hints->base_height)
8284 / (float) size_hints->height_inc + .5)
8285 * size_hints->height_inc;
8287 bounds.right = bounds.left + width;
8288 bounds.bottom = bounds.top + height;
8289 SetEventParameter (event, kEventParamCurrentBounds,
8290 typeQDRectangle, sizeof (Rect), &bounds);
8291 return noErr;
8293 break;
8296 return eventNotHandledErr;
8298 #endif /* USE_CARBON_EVENTS */
8301 OSErr
8302 install_window_handler (window)
8303 WindowPtr window;
8305 OSErr err = noErr;
8306 #if USE_CARBON_EVENTS
8307 EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate},
8308 {kEventClassWindow, kEventWindowBoundsChanging}};
8309 static EventHandlerUPP handle_window_event_UPP = NULL;
8311 if (handle_window_event_UPP == NULL)
8312 handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
8314 err = InstallWindowEventHandler (window, handle_window_event_UPP,
8315 GetEventTypeCount (specs), specs,
8316 NULL, NULL);
8317 #endif
8318 #if TARGET_API_MAC_CARBON
8319 if (mac_do_track_dragUPP == NULL)
8320 mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
8321 if (mac_do_receive_dragUPP == NULL)
8322 mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
8324 if (err == noErr)
8325 err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
8326 if (err == noErr)
8327 err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
8328 #endif
8329 return err;
8332 void
8333 remove_window_handler (window)
8334 WindowPtr window;
8336 #if TARGET_API_MAC_CARBON
8337 if (mac_do_track_dragUPP)
8338 RemoveTrackingHandler (mac_do_track_dragUPP, window);
8339 if (mac_do_receive_dragUPP)
8340 RemoveReceiveHandler (mac_do_receive_dragUPP, window);
8341 #endif
8344 /* Open Application Apple Event */
8345 static pascal OSErr
8346 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
8348 return noErr;
8352 /* Defined in mac.c. */
8353 extern int
8354 path_from_vol_dir_name (char *, int, short, long, char *);
8357 /* Called when we receive an AppleEvent with an ID of
8358 "kAEOpenDocuments". This routine gets the direct parameter,
8359 extracts the FSSpecs in it, and puts their names on a list. */
8360 #pragma options align=mac68k
8361 typedef struct SelectionRange {
8362 short unused1; // 0 (not used)
8363 short lineNum; // line to select (<0 to specify range)
8364 long startRange; // start of selection range (if line < 0)
8365 long endRange; // end of selection range (if line < 0)
8366 long unused2; // 0 (not used)
8367 long theDate; // modification date/time
8368 } SelectionRange;
8369 #pragma options align=reset
8371 static pascal OSErr
8372 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
8374 OSErr err, err2;
8375 AEDesc the_desc;
8376 AEKeyword keyword;
8377 DescType actual_type;
8378 Size actual_size;
8379 SelectionRange position;
8381 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
8382 if (err != noErr)
8383 goto descriptor_error_exit;
8385 err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
8386 if (err == noErr)
8387 drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1),
8388 make_number (position.startRange + 1),
8389 make_number (position.endRange + 1)),
8390 drag_and_drop_file_list);
8392 /* Check to see that we got all of the required parameters from the
8393 event descriptor. For an 'odoc' event this should just be the
8394 file list. */
8395 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
8396 &actual_type, (Ptr) &keyword,
8397 sizeof (keyword), &actual_size);
8398 /* No error means that we found some unused parameters.
8399 errAEDescNotFound means that there are no more parameters. If we
8400 get an error code other than that, flag it. */
8401 if ((err == noErr) || (err != errAEDescNotFound))
8403 err = errAEEventNotHandled;
8404 goto error_exit;
8406 err = noErr;
8408 /* Got all the parameters we need. Now, go through the direct
8409 object list and parse it up. */
8411 long num_files_to_open;
8413 err = AECountItems (&the_desc, &num_files_to_open);
8414 if (err == noErr)
8416 int i;
8418 /* AE file list is one based so just use that for indexing here. */
8419 for (i = 1; i <= num_files_to_open; i++)
8421 char unix_path_name[MAXPATHLEN];
8422 #ifdef MAC_OSX
8423 FSRef fref;
8425 err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
8426 &actual_type, &fref, sizeof (FSRef),
8427 &actual_size);
8428 if (err != noErr || actual_type != typeFSRef)
8429 continue;
8431 if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
8432 == noErr)
8433 #else
8434 FSSpec fs;
8436 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
8437 (Ptr) &fs, sizeof (fs), &actual_size);
8438 if (err != noErr) continue;
8440 if (fsspec_to_posix_pathname (&fs, unix_path_name,
8441 sizeof (unix_path_name) - 1) == noErr)
8442 #endif
8443 /* x-dnd functions expect undecoded filenames. */
8444 drag_and_drop_file_list =
8445 Fcons (make_unibyte_string (unix_path_name,
8446 strlen (unix_path_name)),
8447 drag_and_drop_file_list);
8452 error_exit:
8453 /* Nuke the coerced file list in any case */
8454 err2 = AEDisposeDesc(&the_desc);
8456 descriptor_error_exit:
8457 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8458 return err;
8462 #if TARGET_API_MAC_CARBON
8463 static pascal OSErr
8464 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
8465 void *handlerRefCon, DragReference theDrag)
8467 static int can_accept;
8468 short items;
8469 short index;
8470 ItemReference theItem;
8471 FlavorFlags theFlags;
8472 OSErr result;
8474 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8475 return dragNotAcceptedErr;
8477 switch (message)
8479 case kDragTrackingEnterHandler:
8480 CountDragItems (theDrag, &items);
8481 can_accept = 0;
8482 for (index = 1; index <= items; index++)
8484 GetDragItemReferenceNumber (theDrag, index, &theItem);
8485 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8486 if (result == noErr)
8488 can_accept = 1;
8489 break;
8492 break;
8494 case kDragTrackingEnterWindow:
8495 if (can_accept)
8497 RgnHandle hilite_rgn = NewRgn ();
8498 Rect r;
8499 struct frame *f = mac_window_to_frame (window);
8501 GetWindowPortBounds (window, &r);
8502 OffsetRect (&r, -r.left, -r.top);
8503 RectRgn (hilite_rgn, &r);
8504 ShowDragHilite (theDrag, hilite_rgn, true);
8505 DisposeRgn (hilite_rgn);
8506 SetThemeCursor (kThemeCopyArrowCursor);
8508 break;
8510 case kDragTrackingInWindow:
8511 break;
8513 case kDragTrackingLeaveWindow:
8514 if (can_accept)
8516 struct frame *f = mac_window_to_frame (window);
8518 HideDragHilite (theDrag);
8519 SetThemeCursor (kThemeArrowCursor);
8521 break;
8523 case kDragTrackingLeaveHandler:
8524 break;
8527 return noErr;
8530 static pascal OSErr
8531 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8532 DragReference theDrag)
8534 short items;
8535 short index;
8536 FlavorFlags theFlags;
8537 Point mouse;
8538 OSErr result;
8539 ItemReference theItem;
8540 HFSFlavor data;
8541 Size size = sizeof (HFSFlavor);
8543 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8544 return dragNotAcceptedErr;
8546 drag_and_drop_file_list = Qnil;
8547 GetDragMouse (theDrag, &mouse, 0L);
8548 CountDragItems (theDrag, &items);
8549 for (index = 1; index <= items; index++)
8551 /* Only handle file references. */
8552 GetDragItemReferenceNumber (theDrag, index, &theItem);
8553 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8554 if (result == noErr)
8556 #ifdef MAC_OSX
8557 FSRef fref;
8558 #endif
8559 char unix_path_name[MAXPATHLEN];
8561 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8562 #ifdef MAC_OSX
8563 /* Use Carbon routines, otherwise it converts the file name
8564 to /Macintosh HD/..., which is not correct. */
8565 FSpMakeFSRef (&data.fileSpec, &fref);
8566 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8567 #else
8568 if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
8569 sizeof (unix_path_name) - 1) == noErr)
8570 #endif
8571 /* x-dnd functions expect undecoded filenames. */
8572 drag_and_drop_file_list =
8573 Fcons (make_unibyte_string (unix_path_name,
8574 strlen (unix_path_name)),
8575 drag_and_drop_file_list);
8578 /* If there are items in the list, construct an event and post it to
8579 the queue like an interrupt using kbd_buffer_store_event. */
8580 if (!NILP (drag_and_drop_file_list))
8582 struct input_event event;
8583 Lisp_Object frame;
8584 struct frame *f = mac_window_to_frame (window);
8585 SInt16 modifiers;
8587 GlobalToLocal (&mouse);
8588 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
8590 event.kind = DRAG_N_DROP_EVENT;
8591 event.code = 0;
8592 event.modifiers = mac_to_emacs_modifiers (modifiers);
8593 event.timestamp = TickCount () * (1000 / 60);
8594 XSETINT (event.x, mouse.h);
8595 XSETINT (event.y, mouse.v);
8596 XSETFRAME (frame, f);
8597 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8598 event.arg = Qnil;
8599 /* Post to the interrupt queue */
8600 kbd_buffer_store_event (&event);
8601 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8603 ProcessSerialNumber psn;
8604 GetCurrentProcess (&psn);
8605 SetFrontProcess (&psn);
8608 return noErr;
8610 else
8611 return dragNotAcceptedErr;
8613 #endif
8616 /* Print Document Apple Event */
8617 static pascal OSErr
8618 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8620 return errAEEventNotHandled;
8624 static pascal OSErr
8625 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8627 #if USE_CARBON_EVENTS
8628 OSErr err;
8629 EventRef event = NULL;
8630 static const HICommand quit_command = {kEventAttributeNone, kHICommandQuit};
8632 err = CreateEvent (NULL, kEventClassCommand, kEventCommandProcess, 0,
8633 kEventAttributeUserEvent, &event);
8634 if (err == noErr)
8635 err = SetEventParameter (event, kEventParamDirectObject, typeHICommand,
8636 sizeof (HICommand), &quit_command);
8637 if (err == noErr)
8638 mac_store_application_menu_event (event);
8639 if (event)
8640 ReleaseEvent (event);
8642 if (err == noErr)
8643 return noErr;
8644 else
8645 return errAEEventNotHandled;
8646 #else
8647 mac_store_application_menu_event (kHICommandQuit);
8649 return noErr;
8650 #endif
8654 #if __profile__
8655 void
8656 profiler_exit_proc ()
8658 ProfilerDump ("\pEmacs.prof");
8659 ProfilerTerm ();
8661 #endif
8663 /* These few functions implement Emacs as a normal Mac application
8664 (almost): set up the heap and the Toolbox, handle necessary system
8665 events plus a few simple menu events. They also set up Emacs's
8666 access to functions defined in the rest of this file. Emacs uses
8667 function hooks to perform all its terminal I/O. A complete list of
8668 these functions appear in termhooks.h. For what they do, read the
8669 comments there and see also w32term.c and xterm.c. What's
8670 noticeably missing here is the event loop, which is normally
8671 present in most Mac application. After performing the necessary
8672 Mac initializations, main passes off control to emacs_main
8673 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
8674 (defined further below) to read input. This is where
8675 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
8677 #ifdef MAC_OS8
8678 #undef main
8680 main (void)
8682 #if __profile__ /* is the profiler on? */
8683 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8684 exit(1);
8685 #endif
8687 #if __MWERKS__
8688 /* set creator and type for files created by MSL */
8689 _fcreator = 'EMAx';
8690 _ftype = 'TEXT';
8691 #endif
8693 do_init_managers ();
8695 do_get_menus ();
8697 #ifndef USE_LSB_TAG
8698 do_check_ram_size ();
8699 #endif
8701 init_emacs_passwd_dir ();
8703 init_environ ();
8705 initialize_applescript ();
8707 init_required_apple_events ();
8710 char **argv;
8711 int argc = 0;
8713 /* set up argv array from STR# resource */
8714 get_string_list (&argv, ARGV_STRING_LIST_ID);
8715 while (argv[argc])
8716 argc++;
8718 /* free up AppleScript resources on exit */
8719 atexit (terminate_applescript);
8721 #if __profile__ /* is the profiler on? */
8722 atexit (profiler_exit_proc);
8723 #endif
8725 /* 3rd param "envp" never used in emacs_main */
8726 (void) emacs_main (argc, argv, 0);
8729 /* Never reached - real exit in Fkill_emacs */
8730 return 0;
8732 #endif
8734 /* Table for translating Mac keycode to X keysym values. Contributed
8735 by Sudhir Shenoy.
8736 Mapping for special keys is now identical to that in Apple X11
8737 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8738 on the right of the Cmd key on laptops, and fn + `enter' (->
8739 <linefeed>). */
8740 static unsigned char keycode_to_xkeysym_table[] = {
8741 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8742 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8743 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8745 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8746 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8747 /*0x38*/ 0, 0, 0, 0,
8748 /*0x3C*/ 0, 0, 0, 0,
8750 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8751 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8752 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8753 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8755 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8756 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8757 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8758 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8760 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8761 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8762 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8763 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8765 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8766 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8767 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8768 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8771 static int
8772 keycode_to_xkeysym (int keyCode, int *xKeySym)
8774 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8775 return *xKeySym != 0;
8778 #if !USE_CARBON_EVENTS
8779 static RgnHandle mouse_region = NULL;
8781 Boolean
8782 mac_wait_next_event (er, sleep_time, dequeue)
8783 EventRecord *er;
8784 UInt32 sleep_time;
8785 Boolean dequeue;
8787 static EventRecord er_buf = {nullEvent};
8788 UInt32 target_tick, current_tick;
8789 EventMask event_mask;
8791 if (mouse_region == NULL)
8792 mouse_region = NewRgn ();
8794 event_mask = everyEvent;
8795 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8796 event_mask -= highLevelEventMask;
8798 current_tick = TickCount ();
8799 target_tick = current_tick + sleep_time;
8801 if (er_buf.what == nullEvent)
8802 while (!WaitNextEvent (event_mask, &er_buf,
8803 target_tick - current_tick, mouse_region))
8805 current_tick = TickCount ();
8806 if (target_tick <= current_tick)
8807 return false;
8810 *er = er_buf;
8811 if (dequeue)
8812 er_buf.what = nullEvent;
8813 return true;
8815 #endif /* not USE_CARBON_EVENTS */
8817 /* Emacs calls this whenever it wants to read an input event from the
8818 user. */
8820 XTread_socket (sd, expected, hold_quit)
8821 int sd, expected;
8822 struct input_event *hold_quit;
8824 struct input_event inev;
8825 int count = 0;
8826 #if USE_CARBON_EVENTS
8827 EventRef eventRef;
8828 EventTargetRef toolbox_dispatcher;
8829 #endif
8830 EventRecord er;
8831 struct mac_display_info *dpyinfo = &one_mac_display_info;
8833 if (interrupt_input_blocked)
8835 interrupt_input_pending = 1;
8836 return -1;
8839 interrupt_input_pending = 0;
8840 BLOCK_INPUT;
8842 /* So people can tell when we have read the available input. */
8843 input_signal_count++;
8845 #if USE_CARBON_EVENTS
8846 toolbox_dispatcher = GetEventDispatcherTarget ();
8848 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8849 kEventRemoveFromQueue, &eventRef))
8850 #else /* !USE_CARBON_EVENTS */
8851 while (mac_wait_next_event (&er, 0, true))
8852 #endif /* !USE_CARBON_EVENTS */
8854 int do_help = 0;
8855 struct frame *f;
8857 /* It is necessary to set this (additional) argument slot of an
8858 event to nil because keyboard.c protects incompletely
8859 processed event from being garbage collected by placing them
8860 in the kbd_buffer_gcpro vector. */
8861 EVENT_INIT (inev);
8862 inev.kind = NO_EVENT;
8863 inev.arg = Qnil;
8865 #if USE_CARBON_EVENTS
8866 /* Handle new events */
8867 if (!mac_convert_event_ref (eventRef, &er))
8868 switch (GetEventClass (eventRef))
8870 case kEventClassWindow:
8871 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8873 WindowPtr window_ptr;
8874 GetEventParameter(eventRef, kEventParamDirectObject,
8875 typeWindowRef, NULL, sizeof(WindowPtr),
8876 NULL, &window_ptr);
8877 f = mac_window_to_frame (window_ptr);
8878 if (f && !f->async_iconified)
8879 x_real_positions (f, &f->left_pos, &f->top_pos);
8880 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8882 break;
8883 case kEventClassMouse:
8884 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8886 SInt32 delta;
8887 Point point;
8888 struct frame *f = mac_focus_frame (dpyinfo);
8889 WindowPtr window_ptr;
8891 #if 0
8892 if (dpyinfo->x_focus_frame == NULL)
8894 /* Beep if wheel move occurs when all the frames
8895 are invisible. */
8896 SysBeep(1);
8897 break;
8899 #endif
8901 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8902 typeSInt32, NULL, sizeof (SInt32),
8903 NULL, &delta);
8904 GetEventParameter(eventRef, kEventParamMouseLocation,
8905 typeQDPoint, NULL, sizeof (Point),
8906 NULL, &point);
8907 inev.kind = WHEEL_EVENT;
8908 inev.code = 0;
8909 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8910 | ((delta < 0) ? down_modifier
8911 : up_modifier));
8912 window_ptr = FRAME_MAC_WINDOW (f);
8913 SetPortWindowPort (window_ptr);
8914 GlobalToLocal (&point);
8915 XSETINT (inev.x, point.h);
8916 XSETINT (inev.y, point.v);
8917 XSETFRAME (inev.frame_or_window,
8918 mac_window_to_frame (window_ptr));
8919 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8921 else
8922 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8924 break;
8926 default:
8927 /* Send the event to the appropriate receiver. */
8928 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8930 else
8931 #endif /* USE_CARBON_EVENTS */
8932 switch (er.what)
8934 case mouseDown:
8935 case mouseUp:
8937 WindowPtr window_ptr;
8938 ControlPartCode part_code;
8939 int tool_bar_p = 0;
8941 #if USE_CARBON_EVENTS
8942 /* This is needed to send mouse events like aqua window
8943 buttons to the correct handler. */
8944 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8945 != eventNotHandledErr)
8946 break;
8947 #endif
8949 if (dpyinfo->grabbed && last_mouse_frame
8950 && FRAME_LIVE_P (last_mouse_frame))
8952 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8953 part_code = inContent;
8955 else
8957 part_code = FindWindow (er.where, &window_ptr);
8958 if (tip_window && window_ptr == tip_window)
8960 HideWindow (tip_window);
8961 part_code = FindWindow (er.where, &window_ptr);
8965 if (er.what != mouseDown && part_code != inContent)
8966 break;
8968 switch (part_code)
8970 case inMenuBar:
8971 f = mac_focus_frame (dpyinfo);
8972 saved_menu_event_location = er.where;
8973 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8974 XSETFRAME (inev.frame_or_window, f);
8975 break;
8977 case inContent:
8978 if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
8979 SelectWindow (window_ptr);
8980 else
8982 ControlPartCode control_part_code;
8983 ControlHandle ch;
8984 Point mouse_loc = er.where;
8985 #ifdef MAC_OSX
8986 ControlKind control_kind;
8987 #endif
8989 f = mac_window_to_frame (window_ptr);
8990 /* convert to local coordinates of new window */
8991 SetPortWindowPort (window_ptr);
8993 GlobalToLocal (&mouse_loc);
8994 #if TARGET_API_MAC_CARBON
8995 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8996 &control_part_code);
8997 #ifdef MAC_OSX
8998 if (ch)
8999 GetControlKind (ch, &control_kind);
9000 #endif
9001 #else
9002 control_part_code = FindControl (mouse_loc, window_ptr,
9003 &ch);
9004 #endif
9006 #if USE_CARBON_EVENTS
9007 inev.code = mac_get_mouse_btn (eventRef);
9008 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9009 #else
9010 inev.code = mac_get_emulated_btn (er.modifiers);
9011 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9012 #endif
9013 XSETINT (inev.x, mouse_loc.h);
9014 XSETINT (inev.y, mouse_loc.v);
9015 inev.timestamp = er.when * (1000 / 60);
9016 /* ticks to milliseconds */
9018 if (dpyinfo->grabbed && tracked_scroll_bar
9019 || ch != 0
9020 #ifndef USE_TOOLKIT_SCROLL_BARS
9021 /* control_part_code becomes kControlNoPart if
9022 a progress indicator is clicked. */
9023 && control_part_code != kControlNoPart
9024 #else /* USE_TOOLKIT_SCROLL_BARS */
9025 #ifdef MAC_OSX
9026 && control_kind.kind == kControlKindScrollBar
9027 #endif /* MAC_OSX */
9028 #endif /* USE_TOOLKIT_SCROLL_BARS */
9031 struct scroll_bar *bar;
9033 if (dpyinfo->grabbed && tracked_scroll_bar)
9035 bar = tracked_scroll_bar;
9036 #ifndef USE_TOOLKIT_SCROLL_BARS
9037 control_part_code = kControlIndicatorPart;
9038 #endif
9040 else
9041 bar = (struct scroll_bar *) GetControlReference (ch);
9042 #ifdef USE_TOOLKIT_SCROLL_BARS
9043 /* Make the "Ctrl-Mouse-2 splits window" work
9044 for toolkit scroll bars. */
9045 if (er.modifiers & controlKey)
9046 x_scroll_bar_handle_click (bar, control_part_code,
9047 &er, &inev);
9048 else if (er.what == mouseDown)
9049 x_scroll_bar_handle_press (bar, control_part_code,
9050 inev.timestamp, &inev);
9051 else
9052 x_scroll_bar_handle_release (bar, inev.timestamp,
9053 &inev);
9054 #else /* not USE_TOOLKIT_SCROLL_BARS */
9055 x_scroll_bar_handle_click (bar, control_part_code,
9056 &er, &inev);
9057 if (er.what == mouseDown
9058 && control_part_code == kControlIndicatorPart)
9059 tracked_scroll_bar = bar;
9060 else
9061 tracked_scroll_bar = NULL;
9062 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9064 else
9066 Lisp_Object window;
9067 int x = mouse_loc.h;
9068 int y = mouse_loc.v;
9070 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
9071 if (EQ (window, f->tool_bar_window))
9073 if (er.what == mouseDown)
9074 handle_tool_bar_click (f, x, y, 1, 0);
9075 else
9076 handle_tool_bar_click (f, x, y, 0,
9077 inev.modifiers);
9078 tool_bar_p = 1;
9080 else
9082 XSETFRAME (inev.frame_or_window, f);
9083 inev.kind = MOUSE_CLICK_EVENT;
9087 if (er.what == mouseDown)
9089 dpyinfo->grabbed |= (1 << inev.code);
9090 last_mouse_frame = f;
9091 /* Ignore any mouse motion that happened
9092 before this event; any subsequent
9093 mouse-movement Emacs events should reflect
9094 only motion after the ButtonPress. */
9095 if (f != 0)
9096 f->mouse_moved = 0;
9098 if (!tool_bar_p)
9099 last_tool_bar_item = -1;
9101 else
9103 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
9104 /* If a button is released though it was not
9105 previously pressed, that would be because
9106 of multi-button emulation. */
9107 dpyinfo->grabbed = 0;
9108 else
9109 dpyinfo->grabbed &= ~(1 << inev.code);
9112 #ifdef USE_TOOLKIT_SCROLL_BARS
9113 if (inev.kind == MOUSE_CLICK_EVENT)
9114 #endif
9115 switch (er.what)
9117 case mouseDown:
9118 inev.modifiers |= down_modifier;
9119 break;
9120 case mouseUp:
9121 inev.modifiers |= up_modifier;
9122 break;
9125 break;
9127 case inDrag:
9128 #if TARGET_API_MAC_CARBON
9129 DragWindow (window_ptr, er.where, NULL);
9130 #else /* not TARGET_API_MAC_CARBON */
9131 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
9132 #endif /* not TARGET_API_MAC_CARBON */
9133 /* Update the frame parameters. */
9135 struct frame *f = mac_window_to_frame (window_ptr);
9137 if (f && !f->async_iconified)
9138 x_real_positions (f, &f->left_pos, &f->top_pos);
9140 break;
9142 case inGoAway:
9143 if (TrackGoAway (window_ptr, er.where))
9145 inev.kind = DELETE_WINDOW_EVENT;
9146 XSETFRAME (inev.frame_or_window,
9147 mac_window_to_frame (window_ptr));
9149 break;
9151 /* window resize handling added --ben */
9152 case inGrow:
9153 do_grow_window (window_ptr, &er);
9154 break;
9156 /* window zoom handling added --ben */
9157 case inZoomIn:
9158 case inZoomOut:
9159 if (TrackBox (window_ptr, er.where, part_code))
9160 do_zoom_window (window_ptr, part_code);
9161 break;
9163 default:
9164 break;
9167 break;
9169 case updateEvt:
9170 #if USE_CARBON_EVENTS
9171 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9172 != eventNotHandledErr)
9173 break;
9174 #else
9175 do_window_update ((WindowPtr) er.message);
9176 #endif
9177 break;
9179 case osEvt:
9180 #if USE_CARBON_EVENTS
9181 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9182 != eventNotHandledErr)
9183 break;
9184 #endif
9185 switch ((er.message >> 24) & 0x000000FF)
9187 case suspendResumeMessage:
9188 if ((er.message & resumeFlag) == 1)
9189 do_app_resume ();
9190 else
9191 do_app_suspend ();
9192 break;
9194 case mouseMovedMessage:
9195 #if !USE_CARBON_EVENTS
9196 SetRectRgn (mouse_region, er.where.h, er.where.v,
9197 er.where.h + 1, er.where.v + 1);
9198 #endif
9199 previous_help_echo_string = help_echo_string;
9200 help_echo_string = help_echo_object = help_echo_window = Qnil;
9201 help_echo_pos = -1;
9203 if (dpyinfo->grabbed && last_mouse_frame
9204 && FRAME_LIVE_P (last_mouse_frame))
9205 f = last_mouse_frame;
9206 else
9207 f = dpyinfo->x_focus_frame;
9209 if (dpyinfo->mouse_face_hidden)
9211 dpyinfo->mouse_face_hidden = 0;
9212 clear_mouse_face (dpyinfo);
9215 if (f)
9217 WindowPtr wp = FRAME_MAC_WINDOW (f);
9218 Point mouse_pos = er.where;
9220 SetPortWindowPort (wp);
9222 GlobalToLocal (&mouse_pos);
9224 if (dpyinfo->grabbed && tracked_scroll_bar)
9225 #ifdef USE_TOOLKIT_SCROLL_BARS
9226 x_scroll_bar_handle_drag (wp, tracked_scroll_bar,
9227 mouse_pos, er.when * (1000 / 60),
9228 &inev);
9229 #else /* not USE_TOOLKIT_SCROLL_BARS */
9230 x_scroll_bar_note_movement (tracked_scroll_bar,
9231 mouse_pos.v
9232 - XINT (tracked_scroll_bar->top),
9233 er.when * (1000 / 60));
9234 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9235 else
9237 /* Generate SELECT_WINDOW_EVENTs when needed. */
9238 if (mouse_autoselect_window)
9240 Lisp_Object window;
9242 window = window_from_coordinates (f,
9243 mouse_pos.h,
9244 mouse_pos.v,
9245 0, 0, 0, 0);
9247 /* Window will be selected only when it is
9248 not selected now and last mouse movement
9249 event was not in it. Minibuffer window
9250 will be selected iff it is active. */
9251 if (WINDOWP (window)
9252 && !EQ (window, last_window)
9253 && !EQ (window, selected_window))
9255 inev.kind = SELECT_WINDOW_EVENT;
9256 inev.frame_or_window = window;
9259 last_window=window;
9261 note_mouse_movement (f, &mouse_pos);
9265 /* If the contents of the global variable
9266 help_echo_string has changed, generate a
9267 HELP_EVENT. */
9268 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
9269 do_help = 1;
9270 break;
9272 break;
9274 case activateEvt:
9276 WindowPtr window_ptr = (WindowPtr) er.message;
9278 #if USE_CARBON_EVENTS
9279 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9280 != eventNotHandledErr)
9281 break;
9282 #endif
9283 if (window_ptr == tip_window)
9285 HideWindow (tip_window);
9286 break;
9289 if (!is_emacs_window (window_ptr))
9290 break;
9292 if ((er.modifiers & activeFlag) != 0)
9294 /* A window has been activated */
9295 Point mouse_loc = er.where;
9297 x_detect_focus_change (dpyinfo, &er, &inev);
9299 SetPortWindowPort (window_ptr);
9300 GlobalToLocal (&mouse_loc);
9301 /* Window-activated event counts as mouse movement,
9302 so update things that depend on mouse position. */
9303 note_mouse_movement (mac_window_to_frame (window_ptr),
9304 &mouse_loc);
9306 else
9308 /* A window has been deactivated */
9309 #if USE_TOOLKIT_SCROLL_BARS
9310 if (dpyinfo->grabbed && tracked_scroll_bar)
9312 struct input_event event;
9314 EVENT_INIT (event);
9315 event.kind = NO_EVENT;
9316 x_scroll_bar_handle_release (tracked_scroll_bar,
9317 er.when * (1000 / 60),
9318 &event);
9319 if (event.kind != NO_EVENT)
9321 kbd_buffer_store_event_hold (&event, hold_quit);
9322 count++;
9325 #endif
9326 dpyinfo->grabbed = 0;
9328 x_detect_focus_change (dpyinfo, &er, &inev);
9330 f = mac_window_to_frame (window_ptr);
9331 if (f == dpyinfo->mouse_face_mouse_frame)
9333 /* If we move outside the frame, then we're
9334 certainly no longer on any text in the
9335 frame. */
9336 clear_mouse_face (dpyinfo);
9337 dpyinfo->mouse_face_mouse_frame = 0;
9340 /* Generate a nil HELP_EVENT to cancel a help-echo.
9341 Do it only if there's something to cancel.
9342 Otherwise, the startup message is cleared when the
9343 mouse leaves the frame. */
9344 if (any_help_event_p)
9345 do_help = -1;
9348 break;
9350 case keyDown:
9351 case autoKey:
9353 int keycode = (er.message & keyCodeMask) >> 8;
9354 int xkeysym;
9356 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9357 /* When using Carbon Events, we need to pass raw keyboard
9358 events to the TSM ourselves. If TSM handles it, it
9359 will pass back noErr, otherwise it will pass back
9360 "eventNotHandledErr" and we can process it
9361 normally. */
9362 if ((!NILP (Vmac_pass_command_to_system)
9363 || !(er.modifiers & cmdKey))
9364 && (!NILP (Vmac_pass_control_to_system)
9365 || !(er.modifiers & controlKey)))
9366 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
9367 != eventNotHandledErr)
9368 break;
9369 #endif
9371 #if 0
9372 if (dpyinfo->x_focus_frame == NULL)
9374 /* Beep if keyboard input occurs when all the frames
9375 are invisible. */
9376 SysBeep (1);
9377 break;
9379 #endif
9382 static SInt16 last_key_script = -1;
9383 SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
9385 if (last_key_script != current_key_script)
9387 struct input_event event;
9389 EVENT_INIT (event);
9390 event.kind = LANGUAGE_CHANGE_EVENT;
9391 event.arg = Qnil;
9392 event.code = current_key_script;
9393 kbd_buffer_store_event (&event);
9394 count++;
9396 last_key_script = current_key_script;
9399 ObscureCursor ();
9401 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
9403 clear_mouse_face (dpyinfo);
9404 dpyinfo->mouse_face_hidden = 1;
9407 if (keycode_to_xkeysym (keycode, &xkeysym))
9409 inev.code = 0xff00 | xkeysym;
9410 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
9412 else
9414 if (er.modifiers & (controlKey |
9415 (NILP (Vmac_command_key_is_meta) ? optionKey
9416 : cmdKey)))
9418 /* This code comes from Keyboard Resource,
9419 Appendix C of IM - Text. This is necessary
9420 since shift is ignored in KCHR table
9421 translation when option or command is pressed.
9422 It also does not translate correctly
9423 control-shift chars like C-% so mask off shift
9424 here also */
9425 int new_modifiers = er.modifiers & 0xe600;
9426 /* mask off option and command */
9427 int new_keycode = keycode | new_modifiers;
9428 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9429 unsigned long some_state = 0;
9430 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9431 &some_state) & 0xff;
9433 else if (!NILP (Vmac_option_modifier)
9434 && (er.modifiers & optionKey))
9436 /* When using the option key as an emacs modifier,
9437 convert the pressed key code back to one
9438 without the Mac option modifier applied. */
9439 int new_modifiers = er.modifiers & ~optionKey;
9440 int new_keycode = keycode | new_modifiers;
9441 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9442 unsigned long some_state = 0;
9443 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9444 &some_state) & 0xff;
9446 else
9447 inev.code = er.message & charCodeMask;
9448 inev.kind = ASCII_KEYSTROKE_EVENT;
9452 #if USE_CARBON_EVENTS
9453 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9454 #else
9455 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9456 #endif
9457 XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
9458 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
9459 break;
9461 case kHighLevelEvent:
9462 drag_and_drop_file_list = Qnil;
9464 AEProcessAppleEvent(&er);
9466 /* Build a DRAG_N_DROP_EVENT type event as is done in
9467 constuct_drag_n_drop in w32term.c. */
9468 if (!NILP (drag_and_drop_file_list))
9470 struct frame *f = mac_focus_frame (dpyinfo);
9471 WindowPtr wp;
9472 Lisp_Object frame;
9474 inev.kind = DRAG_N_DROP_EVENT;
9475 inev.code = 0;
9476 inev.timestamp = er.when * (1000 / 60);
9477 /* ticks to milliseconds */
9478 #if USE_CARBON_EVENTS
9479 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9480 #else
9481 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9482 #endif
9484 XSETINT (inev.x, 0);
9485 XSETINT (inev.y, 0);
9487 XSETFRAME (frame, f);
9488 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
9490 #if 0
9491 /* Regardless of whether Emacs was suspended or in the
9492 foreground, ask it to redraw its entire screen.
9493 Otherwise parts of the screen can be left in an
9494 inconsistent state. */
9495 wp = FRAME_MAC_WINDOW (f);
9496 if (wp)
9497 #if TARGET_API_MAC_CARBON
9499 Rect r;
9501 GetWindowPortBounds (wp, &r);
9502 InvalWindowRect (wp, &r);
9504 #else /* not TARGET_API_MAC_CARBON */
9505 InvalRect (&(wp->portRect));
9506 #endif /* not TARGET_API_MAC_CARBON */
9507 #endif
9509 default:
9510 break;
9512 #if USE_CARBON_EVENTS
9513 ReleaseEvent (eventRef);
9514 #endif
9516 if (inev.kind != NO_EVENT)
9518 kbd_buffer_store_event_hold (&inev, hold_quit);
9519 count++;
9522 if (do_help
9523 && !(hold_quit && hold_quit->kind != NO_EVENT))
9525 Lisp_Object frame;
9527 if (f)
9528 XSETFRAME (frame, f);
9529 else
9530 frame = Qnil;
9532 if (do_help > 0)
9534 any_help_event_p = 1;
9535 gen_help_event (help_echo_string, frame, help_echo_window,
9536 help_echo_object, help_echo_pos);
9538 else
9540 help_echo_string = Qnil;
9541 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9543 count++;
9548 /* If the focus was just given to an autoraising frame,
9549 raise it now. */
9550 /* ??? This ought to be able to handle more than one such frame. */
9551 if (pending_autoraise_frame)
9553 x_raise_frame (pending_autoraise_frame);
9554 pending_autoraise_frame = 0;
9557 UNBLOCK_INPUT;
9558 return count;
9562 /* Need to override CodeWarrior's input function so no conversion is
9563 done on newlines Otherwise compiled functions in .elc files will be
9564 read incorrectly. Defined in ...:MSL C:MSL
9565 Common:Source:buffer_io.c. */
9566 #ifdef __MWERKS__
9567 void
9568 __convert_to_newlines (unsigned char * p, size_t * n)
9570 #pragma unused(p,n)
9573 void
9574 __convert_from_newlines (unsigned char * p, size_t * n)
9576 #pragma unused(p,n)
9578 #endif
9580 #ifdef MAC_OS8
9581 void
9582 make_mac_terminal_frame (struct frame *f)
9584 Lisp_Object frame;
9585 Rect r;
9587 XSETFRAME (frame, f);
9589 f->output_method = output_mac;
9590 f->output_data.mac = (struct mac_output *)
9591 xmalloc (sizeof (struct mac_output));
9592 bzero (f->output_data.mac, sizeof (struct mac_output));
9594 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9596 FRAME_COLS (f) = 96;
9597 FRAME_LINES (f) = 4;
9599 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9600 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9602 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9604 f->output_data.mac->cursor_pixel = 0;
9605 f->output_data.mac->border_pixel = 0x00ff00;
9606 f->output_data.mac->mouse_pixel = 0xff00ff;
9607 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9609 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9610 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9611 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9612 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9613 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9614 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9616 FRAME_FONTSET (f) = -1;
9617 f->output_data.mac->explicit_parent = 0;
9618 f->left_pos = 8;
9619 f->top_pos = 32;
9620 f->border_width = 0;
9622 f->internal_border_width = 0;
9624 f->auto_raise = 1;
9625 f->auto_lower = 1;
9627 f->new_text_cols = 0;
9628 f->new_text_lines = 0;
9630 SetRect (&r, f->left_pos, f->top_pos,
9631 f->left_pos + FRAME_PIXEL_WIDTH (f),
9632 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9634 BLOCK_INPUT;
9636 if (!(FRAME_MAC_WINDOW (f) =
9637 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9638 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9639 abort ();
9640 /* so that update events can find this mac_output struct */
9641 f->output_data.mac->mFP = f; /* point back to emacs frame */
9643 UNBLOCK_INPUT;
9645 x_make_gc (f);
9647 /* Need to be initialized for unshow_buffer in window.c. */
9648 selected_window = f->selected_window;
9650 Fmodify_frame_parameters (frame,
9651 Fcons (Fcons (Qfont,
9652 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9653 Fmodify_frame_parameters (frame,
9654 Fcons (Fcons (Qforeground_color,
9655 build_string ("black")), Qnil));
9656 Fmodify_frame_parameters (frame,
9657 Fcons (Fcons (Qbackground_color,
9658 build_string ("white")), Qnil));
9660 #endif
9663 /***********************************************************************
9664 Initialization
9665 ***********************************************************************/
9667 int mac_initialized = 0;
9669 void
9670 mac_initialize_display_info ()
9672 struct mac_display_info *dpyinfo = &one_mac_display_info;
9673 GDHandle main_device_handle;
9675 bzero (dpyinfo, sizeof (*dpyinfo));
9677 #ifdef MAC_OSX
9678 dpyinfo->mac_id_name
9679 = (char *) xmalloc (SCHARS (Vinvocation_name)
9680 + SCHARS (Vsystem_name)
9681 + 2);
9682 sprintf (dpyinfo->mac_id_name, "%s@%s",
9683 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9684 #else
9685 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9686 strcpy (dpyinfo->mac_id_name, "Mac Display");
9687 #endif
9689 main_device_handle = LMGetMainDevice();
9691 dpyinfo->reference_count = 0;
9692 dpyinfo->resx = 75.0;
9693 dpyinfo->resy = 75.0;
9694 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
9695 #ifdef MAC_OSX
9696 /* HasDepth returns true if it is possible to have a 32 bit display,
9697 but this may not be what is actually used. Mac OSX can do better.
9698 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9699 header for CGGetActiveDisplayList says that the first display returned
9700 is the active one, so we use that. */
9702 CGDirectDisplayID disp_id[1];
9703 CGDisplayCount disp_count;
9704 CGDisplayErr error_code;
9706 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9707 if (error_code != 0)
9708 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9710 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9712 #else
9713 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9714 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9715 gdDevType, dpyinfo->color_p))
9716 break;
9717 #endif
9718 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9719 dpyinfo->width = (**main_device_handle).gdRect.right;
9720 dpyinfo->grabbed = 0;
9721 dpyinfo->root_window = NULL;
9722 dpyinfo->image_cache = make_image_cache ();
9724 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9725 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9726 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9727 dpyinfo->mouse_face_window = Qnil;
9728 dpyinfo->mouse_face_overlay = Qnil;
9729 dpyinfo->mouse_face_hidden = 0;
9733 static XrmDatabase
9734 mac_make_rdb (xrm_option)
9735 char *xrm_option;
9737 XrmDatabase database;
9739 database = xrm_get_preference_database (NULL);
9740 if (xrm_option)
9741 xrm_merge_string_database (database, xrm_option);
9743 return database;
9746 struct mac_display_info *
9747 mac_term_init (display_name, xrm_option, resource_name)
9748 Lisp_Object display_name;
9749 char *xrm_option;
9750 char *resource_name;
9752 struct mac_display_info *dpyinfo;
9754 BLOCK_INPUT;
9756 if (!mac_initialized)
9758 mac_initialize ();
9759 mac_initialized = 1;
9762 if (x_display_list)
9763 error ("Sorry, this version can only handle one display");
9765 mac_initialize_display_info ();
9767 dpyinfo = &one_mac_display_info;
9769 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9771 /* Put this display on the chain. */
9772 dpyinfo->next = x_display_list;
9773 x_display_list = dpyinfo;
9775 /* Put it on x_display_name_list. */
9776 x_display_name_list = Fcons (Fcons (display_name,
9777 Fcons (Qnil, dpyinfo->xrdb)),
9778 x_display_name_list);
9779 dpyinfo->name_list_element = XCAR (x_display_name_list);
9781 UNBLOCK_INPUT;
9783 return dpyinfo;
9785 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9787 void
9788 x_delete_display (dpyinfo)
9789 struct mac_display_info *dpyinfo;
9791 int i;
9793 /* Discard this display from x_display_name_list and x_display_list.
9794 We can't use Fdelq because that can quit. */
9795 if (! NILP (x_display_name_list)
9796 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9797 x_display_name_list = XCDR (x_display_name_list);
9798 else
9800 Lisp_Object tail;
9802 tail = x_display_name_list;
9803 while (CONSP (tail) && CONSP (XCDR (tail)))
9805 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9807 XSETCDR (tail, XCDR (XCDR (tail)));
9808 break;
9810 tail = XCDR (tail);
9814 if (x_display_list == dpyinfo)
9815 x_display_list = dpyinfo->next;
9816 else
9818 struct x_display_info *tail;
9820 for (tail = x_display_list; tail; tail = tail->next)
9821 if (tail->next == dpyinfo)
9822 tail->next = tail->next->next;
9825 /* Free the font names in the font table. */
9826 for (i = 0; i < dpyinfo->n_fonts; i++)
9827 if (dpyinfo->font_table[i].name)
9829 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9830 xfree (dpyinfo->font_table[i].full_name);
9831 xfree (dpyinfo->font_table[i].name);
9834 if (dpyinfo->font_table->font_encoder)
9835 xfree (dpyinfo->font_table->font_encoder);
9837 xfree (dpyinfo->font_table);
9838 xfree (dpyinfo->mac_id_name);
9840 if (x_display_list == 0)
9842 mac_clear_font_name_table ();
9843 bzero (dpyinfo, sizeof (*dpyinfo));
9848 #ifdef MAC_OSX
9849 void
9850 mac_check_bundle()
9852 extern int inhibit_window_system;
9853 extern int noninteractive;
9854 CFBundleRef appsBundle;
9855 pid_t child;
9857 /* No need to test if already -nw*/
9858 if (inhibit_window_system || noninteractive)
9859 return;
9861 appsBundle = CFBundleGetMainBundle();
9862 if (appsBundle != NULL)
9864 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9865 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9866 /* We found the bundle identifier, now we know we are valid. */
9867 if (res != NULL)
9869 CFRelease(res);
9870 return;
9873 /* MAC_TODO: Have this start the bundled executable */
9875 /* For now, prevent the fatal error by bringing it up in the terminal */
9876 inhibit_window_system = 1;
9879 void
9880 MakeMeTheFrontProcess ()
9882 ProcessSerialNumber psn;
9883 OSErr err;
9885 err = GetCurrentProcess (&psn);
9886 if (err == noErr)
9887 (void) SetFrontProcess (&psn);
9890 /***** Code to handle C-g testing *****/
9892 /* Contains the Mac modifier formed from quit_char */
9893 static mac_quit_char_modifiers = 0;
9894 static mac_quit_char_keycode;
9895 extern int quit_char;
9897 static void
9898 mac_determine_quit_char_modifiers()
9900 /* Todo: Determine modifiers from quit_char. */
9901 UInt32 qc_modifiers = ctrl_modifier;
9903 /* Map modifiers */
9904 mac_quit_char_modifiers = 0;
9905 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9906 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9907 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9908 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9911 static void
9912 init_quit_char_handler ()
9914 /* TODO: Let this support keys other the 'g' */
9915 mac_quit_char_keycode = 5;
9916 /* Look at <architecture/adb_kb_map.h> for details */
9917 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9919 mac_determine_quit_char_modifiers();
9922 static Boolean
9923 quit_char_comp (EventRef inEvent, void *inCompData)
9925 if (GetEventClass(inEvent) != kEventClassKeyboard)
9926 return false;
9927 if (GetEventKind(inEvent) != kEventRawKeyDown)
9928 return false;
9930 UInt32 keyCode;
9931 UInt32 keyModifiers;
9932 GetEventParameter(inEvent, kEventParamKeyCode,
9933 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9934 if (keyCode != mac_quit_char_keycode)
9935 return false;
9936 GetEventParameter(inEvent, kEventParamKeyModifiers,
9937 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9938 if (keyModifiers != mac_quit_char_modifiers)
9939 return false;
9941 return true;
9944 void
9945 mac_check_for_quit_char ()
9947 EventRef event;
9948 static EMACS_TIME last_check_time = { 0, 0 };
9949 static EMACS_TIME one_second = { 1, 0 };
9950 EMACS_TIME now, t;
9952 /* If windows are not initialized, return immediately (keep it bouncin'). */
9953 if (!mac_quit_char_modifiers)
9954 return;
9956 /* Don't check if last check is less than a second ago. */
9957 EMACS_GET_TIME (now);
9958 EMACS_SUB_TIME (t, now, last_check_time);
9959 if (EMACS_TIME_LT (t, one_second))
9960 return;
9961 last_check_time = now;
9963 /* Redetermine modifiers because they are based on lisp variables */
9964 mac_determine_quit_char_modifiers ();
9966 /* Fill the queue with events */
9967 BLOCK_INPUT;
9968 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9969 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9970 NULL);
9971 UNBLOCK_INPUT;
9972 if (event)
9974 struct input_event e;
9976 /* Use an input_event to emulate what the interrupt handler does. */
9977 EVENT_INIT (e);
9978 e.kind = ASCII_KEYSTROKE_EVENT;
9979 e.code = quit_char;
9980 e.arg = Qnil;
9981 e.modifiers = NULL;
9982 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9983 XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info));
9984 /* Remove event from queue to prevent looping. */
9985 RemoveEventFromQueue (GetMainEventQueue (), event);
9986 ReleaseEvent (event);
9987 kbd_buffer_store_event (&e);
9990 #endif /* MAC_OSX */
9992 static void
9993 init_menu_bar ()
9995 #ifdef MAC_OSX
9996 OSErr err;
9997 MenuRef menu;
9998 MenuItemIndex menu_index;
10000 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1,
10001 &menu, &menu_index);
10002 if (err == noErr)
10003 SetMenuItemCommandKey (menu, menu_index, false, 0);
10004 #if USE_CARBON_EVENTS
10005 EnableMenuCommand (NULL, kHICommandPreferences);
10006 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1,
10007 &menu, &menu_index);
10008 if (err == noErr)
10010 SetMenuItemCommandKey (menu, menu_index, false, 0);
10011 InsertMenuItemTextWithCFString (menu, NULL,
10012 0, kMenuItemAttrSeparator, 0);
10013 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"),
10014 0, 0, kHICommandAbout);
10016 #endif /* USE_CARBON_EVENTS */
10017 #else /* !MAC_OSX */
10018 #if USE_CARBON_EVENTS
10019 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout);
10020 #endif
10021 #endif
10025 /* Set up use of X before we make the first connection. */
10027 extern frame_parm_handler mac_frame_parm_handlers[];
10029 static struct redisplay_interface x_redisplay_interface =
10031 mac_frame_parm_handlers,
10032 x_produce_glyphs,
10033 x_write_glyphs,
10034 x_insert_glyphs,
10035 x_clear_end_of_line,
10036 x_scroll_run,
10037 x_after_update_window_line,
10038 x_update_window_begin,
10039 x_update_window_end,
10040 x_cursor_to,
10041 x_flush,
10042 0, /* flush_display_optional */
10043 x_clear_window_mouse_face,
10044 x_get_glyph_overhangs,
10045 x_fix_overlapping_area,
10046 x_draw_fringe_bitmap,
10047 0, /* define_fringe_bitmap */
10048 0, /* destroy_fringe_bitmap */
10049 mac_per_char_metric,
10050 mac_encode_char,
10051 mac_compute_glyph_string_overhangs,
10052 x_draw_glyph_string,
10053 mac_define_frame_cursor,
10054 mac_clear_frame_area,
10055 mac_draw_window_cursor,
10056 mac_draw_vertical_window_border,
10057 mac_shift_glyphs_for_insert
10060 void
10061 mac_initialize ()
10063 rif = &x_redisplay_interface;
10065 clear_frame_hook = x_clear_frame;
10066 ins_del_lines_hook = x_ins_del_lines;
10067 delete_glyphs_hook = x_delete_glyphs;
10068 ring_bell_hook = XTring_bell;
10069 reset_terminal_modes_hook = XTreset_terminal_modes;
10070 set_terminal_modes_hook = XTset_terminal_modes;
10071 update_begin_hook = x_update_begin;
10072 update_end_hook = x_update_end;
10073 set_terminal_window_hook = XTset_terminal_window;
10074 read_socket_hook = XTread_socket;
10075 frame_up_to_date_hook = XTframe_up_to_date;
10076 mouse_position_hook = XTmouse_position;
10077 frame_rehighlight_hook = XTframe_rehighlight;
10078 frame_raise_lower_hook = XTframe_raise_lower;
10080 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
10081 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
10082 redeem_scroll_bar_hook = XTredeem_scroll_bar;
10083 judge_scroll_bars_hook = XTjudge_scroll_bars;
10085 scroll_region_ok = 1; /* we'll scroll partial frames */
10086 char_ins_del_ok = 1;
10087 line_ins_del_ok = 1; /* we'll just blt 'em */
10088 fast_clear_end_of_line = 1; /* X does this well */
10089 memory_below_frame = 0; /* we don't remember what scrolls
10090 off the bottom */
10091 baud_rate = 19200;
10093 x_noop_count = 0;
10094 last_tool_bar_item = -1;
10095 any_help_event_p = 0;
10097 /* Try to use interrupt input; if we can't, then start polling. */
10098 Fset_input_mode (Qt, Qnil, Qt, Qnil);
10100 BLOCK_INPUT;
10102 #if TARGET_API_MAC_CARBON
10103 init_required_apple_events ();
10105 #if USE_CARBON_EVENTS
10106 #ifdef MAC_OSX
10107 init_service_handler ();
10109 init_quit_char_handler ();
10110 #endif /* MAC_OSX */
10112 init_command_handler ();
10114 init_menu_bar ();
10115 #endif /* USE_CARBON_EVENTS */
10117 #ifdef MAC_OSX
10118 if (!inhibit_window_system)
10119 MakeMeTheFrontProcess ();
10120 #endif
10121 #endif
10122 UNBLOCK_INPUT;
10126 void
10127 syms_of_macterm ()
10129 #if 0
10130 staticpro (&x_error_message_string);
10131 x_error_message_string = Qnil;
10132 #endif
10134 Qmodifier_value = intern ("modifier-value");
10135 Qalt = intern ("alt");
10136 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
10137 Qhyper = intern ("hyper");
10138 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
10139 Qsuper = intern ("super");
10140 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
10142 Qapplication = intern ("application"); staticpro (&Qapplication);
10143 Qabout = intern ("about"); staticpro (&Qabout);
10145 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10146 Qpreferences = intern ("preferences"); staticpro (&Qpreferences);
10147 Qservices = intern ("services"); staticpro (&Qservices);
10148 Qpaste = intern ("paste"); staticpro (&Qpaste);
10149 Qperform = intern ("perform"); staticpro (&Qperform);
10150 #endif
10152 #ifdef MAC_OSX
10153 Fprovide (intern ("mac-carbon"), Qnil);
10154 #endif
10156 staticpro (&Qreverse);
10157 Qreverse = intern ("reverse");
10159 staticpro (&x_display_name_list);
10160 x_display_name_list = Qnil;
10162 staticpro (&last_mouse_scroll_bar);
10163 last_mouse_scroll_bar = Qnil;
10165 staticpro (&Qvendor_specific_keysyms);
10166 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
10168 staticpro (&last_mouse_press_frame);
10169 last_mouse_press_frame = Qnil;
10171 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
10172 staticpro (&Qmac_ready_for_drag_n_drop);
10174 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
10175 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
10176 #ifdef USE_TOOLKIT_SCROLL_BARS
10177 Vx_toolkit_scroll_bars = Qt;
10178 #else
10179 Vx_toolkit_scroll_bars = Qnil;
10180 #endif
10182 DEFVAR_BOOL ("x-use-underline-position-properties",
10183 &x_use_underline_position_properties,
10184 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10185 nil means ignore them. If you encounter fonts with bogus
10186 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10187 to 4.1, set this to nil. */);
10188 x_use_underline_position_properties = 0;
10190 staticpro (&last_mouse_motion_frame);
10191 last_mouse_motion_frame = Qnil;
10193 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
10194 doc: /* Non-nil means that the command key is used as the Emacs meta key.
10195 Otherwise the option key is used. */);
10196 Vmac_command_key_is_meta = Qt;
10198 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
10199 doc: /* Modifier to use for the Mac alt/option key. The value can
10200 be alt, hyper, or super for the respective modifier. If the value is
10201 nil then the key will act as the normal Mac option modifier. */);
10202 Vmac_option_modifier = Qnil;
10204 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
10205 doc: /* Non-nil means that the control and meta keys are reversed. This is
10206 useful for non-standard keyboard layouts. */);
10207 Vmac_reverse_ctrl_meta = Qnil;
10209 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10210 &Vmac_emulate_three_button_mouse,
10211 doc: /* t means that when the option-key is held down while pressing the
10212 mouse button, the click will register as mouse-2 and while the
10213 command-key is held down, the click will register as mouse-3.
10214 'reverse means that the the option-key will register for mouse-3
10215 and the command-key will register for mouse-2. nil means that
10216 no emulation should be done and the modifiers should be placed
10217 on the mouse-1 event. */);
10218 Vmac_emulate_three_button_mouse = Qnil;
10220 #if USE_CARBON_EVENTS
10221 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
10222 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
10223 the right click will be mouse-3.
10224 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10225 Vmac_wheel_button_is_mouse_2 = Qt;
10227 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
10228 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10229 Toolbox for processing before Emacs sees it. */);
10230 Vmac_pass_command_to_system = Qt;
10232 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
10233 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10234 Toolbox for processing before Emacs sees it. */);
10235 Vmac_pass_control_to_system = Qt;
10237 #endif
10239 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
10240 doc: /* If non-nil, allow anti-aliasing.
10241 The text will be rendered using Core Graphics text rendering which
10242 may anti-alias the text. */);
10243 Vmac_use_core_graphics = Qnil;
10245 /* Register an entry for `mac-roman' so that it can be used when
10246 creating the terminal frame on Mac OS 9 before loading
10247 term/mac-win.elc. */
10248 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist,
10249 doc: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10250 Each entry should be of the form:
10252 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10254 where CHARSET-NAME is a string used in font names to identify the
10255 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10256 is a coding system corresponding to TEXT-ENCODING. */);
10257 Vmac_charset_info_alist =
10258 Fcons (list3 (build_string ("mac-roman"),
10259 make_number (smRoman), Qnil), Qnil);
10262 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10263 (do not change this comment) */