Implement context-sentitive dual behaviour for mouse-1 click.
[emacs.git] / src / macterm.c
blob4e3b0ae1b65c7db0fe0c9dc58ffd12663bc77b36
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 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 #ifdef MAC_OSX
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 MAC_OSX */
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 MAC_OSX */
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>
73 #include "keyboard.h"
74 #include "frame.h"
75 #include "dispextern.h"
76 #include "fontset.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #include "gnu.h"
81 #include "disptab.h"
82 #include "buffer.h"
83 #include "window.h"
84 #include "intervals.h"
85 #include "composite.h"
86 #include "coding.h"
88 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
89 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
90 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
91 #define macShiftKey (shiftKey)
92 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
93 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
94 : controlKey)
95 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
99 /* Non-nil means Emacs uses toolkit scroll bars. */
101 Lisp_Object Vx_toolkit_scroll_bars;
103 /* Non-zero means that a HELP_EVENT has been generated since Emacs
104 start. */
106 static int any_help_event_p;
108 /* Non-zero means autoselect window with the mouse cursor. */
110 int x_autoselect_window_p;
112 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
114 int x_use_underline_position_properties;
116 /* Non-zero means draw block and hollow cursor as wide as the glyph
117 under it. For example, if a block cursor is over a tab, it will be
118 drawn as wide as that tab on the display. */
121 /* This is a chain of structures for all the X displays currently in
122 use. */
124 struct x_display_info *x_display_list;
126 /* This is a list of cons cells, each of the form (NAME
127 . FONT-LIST-CACHE), one for each element of x_display_list and in
128 the same order. NAME is the name of the frame. FONT-LIST-CACHE
129 records previous values returned by x-list-fonts. */
131 Lisp_Object x_display_name_list;
133 /* This is display since Mac does not support multiple ones. */
134 struct mac_display_info one_mac_display_info;
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the XT functions.
138 It is zero while not inside an update. In that case, the XT
139 functions assume that `selected_frame' is the frame to apply to. */
141 extern struct frame *updating_frame;
143 extern int waiting_for_input;
145 /* This is a frame waiting to be auto-raised, within XTread_socket. */
147 struct frame *pending_autoraise_frame;
149 /* Non-zero means user is interacting with a toolkit scroll bar. */
151 static int toolkit_scroll_bar_interaction;
153 /* Mouse movement.
155 Formerly, we used PointerMotionHintMask (in standard_event_mask)
156 so that we would have to call XQueryPointer after each MotionNotify
157 event to ask for another such event. However, this made mouse tracking
158 slow, and there was a bug that made it eventually stop.
160 Simply asking for MotionNotify all the time seems to work better.
162 In order to avoid asking for motion events and then throwing most
163 of them away or busy-polling the server for mouse positions, we ask
164 the server for pointer motion hints. This means that we get only
165 one event per group of mouse movements. "Groups" are delimited by
166 other kinds of events (focus changes and button clicks, for
167 example), or by XQueryPointer calls; when one of these happens, we
168 get another MotionNotify event the next time the mouse moves. This
169 is at least as efficient as getting motion events when mouse
170 tracking is on, and I suspect only negligibly worse when tracking
171 is off. */
173 /* Where the mouse was last time we reported a mouse event. */
175 static Rect last_mouse_glyph;
176 static Lisp_Object last_mouse_press_frame;
178 /* The scroll bar in which the last X motion event occurred.
180 If the last X motion event occurred in a scroll bar, we set this so
181 XTmouse_position can know whether to report a scroll bar motion or
182 an ordinary motion.
184 If the last X motion event didn't occur in a scroll bar, we set
185 this to Qnil, to tell XTmouse_position to return an ordinary motion
186 event. */
188 static Lisp_Object last_mouse_scroll_bar;
190 /* This is a hack. We would really prefer that XTmouse_position would
191 return the time associated with the position it returns, but there
192 doesn't seem to be any way to wrest the time-stamp from the server
193 along with the position query. So, we just keep track of the time
194 of the last movement we received, and return that in hopes that
195 it's somewhat accurate. */
197 static Time last_mouse_movement_time;
199 struct scroll_bar *tracked_scroll_bar = NULL;
201 /* Incremented by XTread_socket whenever it really tries to read
202 events. */
204 #ifdef __STDC__
205 static int volatile input_signal_count;
206 #else
207 static int input_signal_count;
208 #endif
210 /* Used locally within XTread_socket. */
212 static int x_noop_count;
214 /* Initial values of argv and argc. */
216 extern char **initial_argv;
217 extern int initial_argc;
219 extern Lisp_Object Vcommand_line_args, Vsystem_name;
221 /* Tells if a window manager is present or not. */
223 extern Lisp_Object Vx_no_window_manager;
225 extern int errno;
227 /* A mask of extra modifier bits to put into every keyboard char. */
229 extern int extra_keyboard_modifiers;
231 /* The keysyms to use for the various modifiers. */
233 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
235 static Lisp_Object Qvendor_specific_keysyms;
237 #if 0
238 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
239 #endif
241 extern int inhibit_window_system;
243 #if __MRC__
244 QDGlobals qd; /* QuickDraw global information structure. */
245 #endif
248 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
249 struct mac_display_info *mac_display_info_for_display (Display *);
250 static void x_update_window_end P_ ((struct window *, int, int));
251 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
252 static int x_io_error_quitter P_ ((Display *));
253 int x_catch_errors P_ ((Display *));
254 void x_uncatch_errors P_ ((Display *, int));
255 void x_lower_frame P_ ((struct frame *));
256 void x_scroll_bar_clear P_ ((struct frame *));
257 int x_had_errors_p P_ ((Display *));
258 void x_wm_set_size_hint P_ ((struct frame *, long, int));
259 void x_raise_frame P_ ((struct frame *));
260 void x_set_window_size P_ ((struct frame *, int, int, int));
261 void x_wm_set_window_state P_ ((struct frame *, int));
262 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
263 void mac_initialize P_ ((void));
264 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
265 static int x_compute_min_glyph_bounds P_ ((struct frame *));
266 static void x_update_end P_ ((struct frame *));
267 static void XTframe_up_to_date P_ ((struct frame *));
268 static void XTreassert_line_highlight P_ ((int, int));
269 static void x_change_line_highlight P_ ((int, int, int, int));
270 static void XTset_terminal_modes P_ ((void));
271 static void XTreset_terminal_modes P_ ((void));
272 static void x_clear_frame P_ ((void));
273 static void frame_highlight P_ ((struct frame *));
274 static void frame_unhighlight P_ ((struct frame *));
275 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
276 static void XTframe_rehighlight P_ ((struct frame *));
277 static void x_frame_rehighlight P_ ((struct x_display_info *));
278 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
279 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
280 enum text_cursor_kinds));
282 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
283 static void x_flush P_ ((struct frame *f));
284 static void x_update_begin P_ ((struct frame *));
285 static void x_update_window_begin P_ ((struct window *));
286 static void x_after_update_window_line P_ ((struct glyph_row *));
288 void activate_scroll_bars (FRAME_PTR);
289 void deactivate_scroll_bars (FRAME_PTR);
291 static int is_emacs_window (WindowPtr);
293 int x_bitmap_icon (struct frame *, Lisp_Object);
294 void x_make_frame_visible (struct frame *);
296 extern void window_scroll (Lisp_Object, int, int, int);
298 /* Defined in macmenu.h. */
299 extern void menubar_selection_callback (FRAME_PTR, int);
300 extern void set_frame_menubar (FRAME_PTR, int, int);
302 /* X display function emulation */
304 void
305 XFreePixmap (display, pixmap)
306 Display *display; /* not used */
307 Pixmap pixmap;
309 DisposeGWorld (pixmap);
313 /* Set foreground color for subsequent QuickDraw commands. Assume
314 graphic port has already been set. */
316 static void
317 mac_set_forecolor (unsigned long color)
319 RGBColor fg_color;
321 fg_color.red = RED16_FROM_ULONG (color);
322 fg_color.green = GREEN16_FROM_ULONG (color);
323 fg_color.blue = BLUE16_FROM_ULONG (color);
325 RGBForeColor (&fg_color);
329 /* Set background color for subsequent QuickDraw commands. Assume
330 graphic port has already been set. */
332 static void
333 mac_set_backcolor (unsigned long color)
335 RGBColor bg_color;
337 bg_color.red = RED16_FROM_ULONG (color);
338 bg_color.green = GREEN16_FROM_ULONG (color);
339 bg_color.blue = BLUE16_FROM_ULONG (color);
341 RGBBackColor (&bg_color);
344 /* Set foreground and background color for subsequent QuickDraw
345 commands. Assume that the graphic port has already been set. */
347 static void
348 mac_set_colors (GC gc)
350 mac_set_forecolor (gc->foreground);
351 mac_set_backcolor (gc->background);
354 /* Mac version of XDrawLine. */
356 static void
357 XDrawLine (display, w, gc, x1, y1, x2, y2)
358 Display *display;
359 WindowPtr w;
360 GC gc;
361 int x1, y1, x2, y2;
363 SetPortWindowPort (w);
365 mac_set_colors (gc);
367 MoveTo (x1, y1);
368 LineTo (x2, y2);
371 void
372 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
373 Display *display;
374 Pixmap p;
375 GC gc;
376 int x1, y1, x2, y2;
378 CGrafPtr old_port;
379 GDHandle old_gdh;
381 GetGWorld (&old_port, &old_gdh);
382 SetGWorld (p, NULL);
384 mac_set_colors (gc);
386 LockPixels (GetGWorldPixMap (p));
387 MoveTo (x1, y1);
388 LineTo (x2, y2);
389 UnlockPixels (GetGWorldPixMap (p));
391 SetGWorld (old_port, old_gdh);
394 /* Mac version of XClearArea. */
396 void
397 XClearArea (display, w, x, y, width, height, exposures)
398 Display *display;
399 WindowPtr w;
400 int x, y;
401 unsigned int width, height;
402 int exposures;
404 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
405 Rect r;
406 XGCValues xgc;
408 xgc.foreground = mwp->x_compatible.foreground_pixel;
409 xgc.background = mwp->x_compatible.background_pixel;
411 SetPortWindowPort (w);
413 mac_set_colors (&xgc);
414 SetRect (&r, x, y, x + width, y + height);
416 EraseRect (&r);
419 /* Mac version of XClearWindow. */
421 static void
422 XClearWindow (display, w)
423 Display *display;
424 WindowPtr w;
426 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
427 XGCValues xgc;
429 xgc.foreground = mwp->x_compatible.foreground_pixel;
430 xgc.background = mwp->x_compatible.background_pixel;
432 SetPortWindowPort (w);
434 mac_set_colors (&xgc);
436 #if TARGET_API_MAC_CARBON
438 Rect r;
440 GetWindowPortBounds (w, &r);
441 EraseRect (&r);
443 #else /* not TARGET_API_MAC_CARBON */
444 EraseRect (&(w->portRect));
445 #endif /* not TARGET_API_MAC_CARBON */
449 /* Mac replacement for XCopyArea. */
451 static void
452 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
453 Display *display;
454 WindowPtr w;
455 GC gc;
456 int x, y, width, height;
457 unsigned short *bits;
458 int overlay_p;
460 BitMap bitmap;
461 Rect r;
463 bitmap.rowBytes = sizeof(unsigned short);
464 bitmap.baseAddr = (char *)bits;
465 SetRect (&(bitmap.bounds), 0, 0, width, height);
467 SetPortWindowPort (w);
469 mac_set_colors (gc);
470 SetRect (&r, x, y, x + width, y + height);
472 #if TARGET_API_MAC_CARBON
473 LockPortBits (GetWindowPort (w));
474 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
475 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
476 UnlockPortBits (GetWindowPort (w));
477 #else /* not TARGET_API_MAC_CARBON */
478 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
479 overlay_p ? srcOr : srcCopy, 0);
480 #endif /* not TARGET_API_MAC_CARBON */
484 /* Mac replacement for XSetClipRectangles. */
486 static void
487 mac_set_clip_rectangle (display, w, r)
488 Display *display;
489 WindowPtr w;
490 Rect *r;
492 SetPortWindowPort (w);
494 ClipRect (r);
498 /* Mac replacement for XSetClipMask. */
500 static void
501 mac_reset_clipping (display, w)
502 Display *display;
503 WindowPtr w;
505 Rect r;
507 SetPortWindowPort (w);
509 SetRect (&r, -32767, -32767, 32767, 32767);
510 ClipRect (&r);
514 /* XBM bits seem to be backward within bytes compared with how
515 Mac does things. */
516 static unsigned char
517 reflect_byte (orig)
518 unsigned char orig;
520 int i;
521 unsigned char reflected = 0x00;
522 for (i = 0; i < 8; i++)
524 if (orig & (0x01 << i))
525 reflected |= 0x80 >> i;
527 return reflected;
531 /* Mac replacement for XCreateBitmapFromBitmapData. */
533 static void
534 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
535 BitMap *bitmap;
536 char *bits;
537 int w, h;
539 int i, j, w1;
540 char *p;
542 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
543 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
544 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
545 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
546 for (i = 0; i < h; i++)
548 p = bitmap->baseAddr + i * bitmap->rowBytes;
549 for (j = 0; j < w1; j++)
550 *p++ = reflect_byte (*bits++);
553 SetRect (&(bitmap->bounds), 0, 0, w, h);
557 static void
558 mac_free_bitmap (bitmap)
559 BitMap *bitmap;
561 xfree (bitmap->baseAddr);
565 Pixmap
566 XCreatePixmap (display, w, width, height, depth)
567 Display *display; /* not used */
568 WindowPtr w;
569 unsigned int width, height;
570 unsigned int depth;
572 Pixmap pixmap;
573 Rect r;
574 QDErr err;
576 SetPortWindowPort (w);
578 SetRect (&r, 0, 0, width, height);
579 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
580 if (err != noErr)
581 return NULL;
582 return pixmap;
586 Pixmap
587 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
588 Display *display; /* not used */
589 WindowPtr w;
590 char *data;
591 unsigned int width, height;
592 unsigned long fg, bg;
593 unsigned int depth; /* not used */
595 Pixmap pixmap;
596 BitMap bitmap;
597 CGrafPtr old_port;
598 GDHandle old_gdh;
600 pixmap = XCreatePixmap (display, w, width, height, depth);
601 if (pixmap == NULL)
602 return NULL;
604 GetGWorld (&old_port, &old_gdh);
605 SetGWorld (pixmap, NULL);
606 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
607 mac_set_forecolor (fg);
608 mac_set_backcolor (bg);
609 LockPixels (GetGWorldPixMap (pixmap));
610 #if TARGET_API_MAC_CARBON
611 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
612 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
613 #else /* not TARGET_API_MAC_CARBON */
614 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
615 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
616 #endif /* not TARGET_API_MAC_CARBON */
617 UnlockPixels (GetGWorldPixMap (pixmap));
618 SetGWorld (old_port, old_gdh);
619 mac_free_bitmap (&bitmap);
621 return pixmap;
625 /* Mac replacement for XFillRectangle. */
627 static void
628 XFillRectangle (display, w, gc, x, y, width, height)
629 Display *display;
630 WindowPtr w;
631 GC gc;
632 int x, y;
633 unsigned int width, height;
635 Rect r;
637 SetPortWindowPort (w);
639 mac_set_colors (gc);
640 SetRect (&r, x, y, x + width, y + height);
642 PaintRect (&r); /* using foreground color of gc */
646 #if 0 /* TODO: figure out if we need to do this on Mac. */
647 static void
648 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
649 Display *display;
650 Pixmap p;
651 GC gc;
652 int x, y;
653 unsigned int width, height;
655 CGrafPtr old_port;
656 GDHandle old_gdh;
657 Rect r;
659 GetGWorld (&old_port, &old_gdh);
660 SetGWorld (p, NULL);
661 mac_set_colors (gc);
662 SetRect (&r, x, y, x + width, y + height);
664 LockPixels (GetGWorldPixMap (p));
665 PaintRect (&r); /* using foreground color of gc */
666 UnlockPixels (GetGWorldPixMap (p));
668 SetGWorld (old_port, old_gdh);
670 #endif
673 /* Mac replacement for XDrawRectangle: dest is a window. */
675 static void
676 mac_draw_rectangle (display, w, gc, x, y, width, height)
677 Display *display;
678 WindowPtr w;
679 GC gc;
680 int x, y;
681 unsigned int width, height;
683 Rect r;
685 SetPortWindowPort (w);
687 mac_set_colors (gc);
688 SetRect (&r, x, y, x + width + 1, y + height + 1);
690 FrameRect (&r); /* using foreground color of gc */
694 #if 0 /* TODO: figure out if we need to do this on Mac. */
695 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
697 static void
698 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
699 Display *display;
700 Pixmap p;
701 GC gc;
702 int x, y;
703 unsigned int width, height;
705 CGrafPtr old_port;
706 GDHandle old_gdh;
707 Rect r;
709 GetGWorld (&old_port, &old_gdh);
710 SetGWorld (p, NULL);
711 mac_set_colors (gc);
712 SetRect (&r, x, y, x + width + 1, y + height + 1);
714 LockPixels (GetGWorldPixMap (p));
715 FrameRect (&r); /* using foreground color of gc */
716 UnlockPixels (GetGWorldPixMap (p));
718 SetGWorld (old_port, old_gdh);
720 #endif
723 static void
724 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
725 bytes_per_char)
726 Display *display;
727 WindowPtr w;
728 GC gc;
729 int x, y;
730 char *buf;
731 int nchars, mode, bytes_per_char;
733 SetPortWindowPort (w);
735 mac_set_colors (gc);
737 TextFont (gc->font->mac_fontnum);
738 TextSize (gc->font->mac_fontsize);
739 TextFace (gc->font->mac_fontface);
740 TextMode (mode);
742 MoveTo (x, y);
743 DrawText (buf, 0, nchars * bytes_per_char);
747 /* Mac replacement for XDrawString. */
749 static void
750 XDrawString (display, w, gc, x, y, buf, nchars)
751 Display *display;
752 WindowPtr w;
753 GC gc;
754 int x, y;
755 char *buf;
756 int nchars;
758 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
762 /* Mac replacement for XDrawString16. */
764 static void
765 XDrawString16 (display, w, gc, x, y, buf, nchars)
766 Display *display;
767 WindowPtr w;
768 GC gc;
769 int x, y;
770 XChar2b *buf;
771 int nchars;
773 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
778 /* Mac replacement for XDrawImageString. */
780 static void
781 XDrawImageString (display, w, gc, x, y, buf, nchars)
782 Display *display;
783 WindowPtr w;
784 GC gc;
785 int x, y;
786 char *buf;
787 int nchars;
789 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
793 /* Mac replacement for XDrawString16. */
795 static void
796 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
797 Display *display;
798 WindowPtr w;
799 GC gc;
800 int x, y;
801 XChar2b *buf;
802 int nchars;
804 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
809 /* Mac replacement for XCopyArea: dest must be window. */
811 static void
812 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
813 dest_y)
814 Display *display;
815 Pixmap src;
816 WindowPtr dest;
817 GC gc;
818 int src_x, src_y;
819 unsigned int width, height;
820 int dest_x, dest_y;
822 Rect src_r, dest_r;
824 SetPortWindowPort (dest);
826 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
827 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
829 ForeColor (blackColor);
830 BackColor (whiteColor);
832 LockPixels (GetGWorldPixMap (src));
833 #if TARGET_API_MAC_CARBON
834 LockPortBits (GetWindowPort (dest));
835 CopyBits (GetPortBitMapForCopyBits (src),
836 GetPortBitMapForCopyBits (GetWindowPort (dest)),
837 &src_r, &dest_r, srcCopy, 0);
838 UnlockPortBits (GetWindowPort (dest));
839 #else /* not TARGET_API_MAC_CARBON */
840 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
841 &src_r, &dest_r, srcCopy, 0);
842 #endif /* not TARGET_API_MAC_CARBON */
843 UnlockPixels (GetGWorldPixMap (src));
847 static void
848 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
849 width, height, dest_x, dest_y)
850 Display *display;
851 Pixmap src, mask;
852 WindowPtr dest;
853 GC gc;
854 int src_x, src_y;
855 unsigned int width, height;
856 int dest_x, dest_y;
858 Rect src_r, dest_r;
860 SetPortWindowPort (dest);
862 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
863 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
865 ForeColor (blackColor);
866 BackColor (whiteColor);
868 LockPixels (GetGWorldPixMap (src));
869 LockPixels (GetGWorldPixMap (mask));
870 #if TARGET_API_MAC_CARBON
871 LockPortBits (GetWindowPort (dest));
872 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
873 GetPortBitMapForCopyBits (GetWindowPort (dest)),
874 &src_r, &src_r, &dest_r);
875 UnlockPortBits (GetWindowPort (dest));
876 #else /* not TARGET_API_MAC_CARBON */
877 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
878 &(dest->portBits), &src_r, &src_r, &dest_r);
879 #endif /* not TARGET_API_MAC_CARBON */
880 UnlockPixels (GetGWorldPixMap (mask));
881 UnlockPixels (GetGWorldPixMap (src));
885 #if 0
886 /* Convert a pair of local coordinates to global (screen) coordinates.
887 Assume graphic port has been properly set. */
888 static void
889 local_to_global_coord (short *h, short *v)
891 Point p;
893 p.h = *h;
894 p.v = *v;
896 LocalToGlobal (&p);
898 *h = p.h;
899 *v = p.v;
901 #endif
903 /* Mac replacement for XCopyArea: used only for scrolling. */
905 static void
906 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
907 Display *display;
908 WindowPtr w;
909 GC gc;
910 int src_x, src_y;
911 unsigned int width, height;
912 int dest_x, dest_y;
914 #if TARGET_API_MAC_CARBON
915 Rect src_r;
916 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
918 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
919 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
920 kScrollWindowNoOptions, dummy);
921 DisposeRgn (dummy);
922 #else /* not TARGET_API_MAC_CARBON */
923 Rect src_r, dest_r;
925 SetPort (w);
926 #if 0
927 mac_set_colors (gc);
928 #endif
930 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
931 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
933 #if 0
934 /* Need to use global coordinates and screenBits since src and dest
935 areas overlap in general. */
936 local_to_global_coord (&src_r.left, &src_r.top);
937 local_to_global_coord (&src_r.right, &src_r.bottom);
938 local_to_global_coord (&dest_r.left, &dest_r.top);
939 local_to_global_coord (&dest_r.right, &dest_r.bottom);
941 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
942 #else
943 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
944 color mapping in CopyBits. Otherwise, it will be slow. */
945 ForeColor (blackColor);
946 BackColor (whiteColor);
947 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
949 mac_set_colors (gc);
950 #endif
951 #endif /* not TARGET_API_MAC_CARBON */
955 #if 0 /* TODO: figure out if we need to do this on Mac. */
956 /* Mac replacement for XCopyArea: dest must be Pixmap. */
958 static void
959 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
960 dest_x, dest_y)
961 Display *display;
962 Pixmap src, dest;
963 GC gc;
964 int src_x, src_y;
965 unsigned int width, height;
966 int dest_x, dest_y;
968 CGrafPtr old_port;
969 GDHandle old_gdh;
970 Rect src_r, dest_r;
972 GetGWorld (&old_port, &old_gdh);
973 SetGWorld (dest, NULL);
974 ForeColor (blackColor);
975 BackColor (whiteColor);
977 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
978 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
980 LockPixels (GetGWorldPixMap (src));
981 LockPixels (GetGWorldPixMap (dest));
982 #if TARGET_API_MAC_CARBON
983 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
984 &src_r, &dest_r, srcCopy, 0);
985 #else /* not TARGET_API_MAC_CARBON */
986 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
987 &src_r, &dest_r, srcCopy, 0);
988 #endif /* not TARGET_API_MAC_CARBON */
989 UnlockPixels (GetGWorldPixMap (dest));
990 UnlockPixels (GetGWorldPixMap (src));
992 SetGWorld (old_port, old_gdh);
996 static void
997 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
998 width, height, dest_x, dest_y)
999 Display *display;
1000 Pixmap src, mask, dest;
1001 GC gc;
1002 int src_x, src_y;
1003 unsigned int width, height;
1004 int dest_x, dest_y;
1006 CGrafPtr old_port;
1007 GDHandle old_gdh;
1008 Rect src_r, dest_r;
1010 GetGWorld (&old_port, &old_gdh);
1011 SetGWorld (dest, NULL);
1012 ForeColor (blackColor);
1013 BackColor (whiteColor);
1015 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1016 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1018 LockPixels (GetGWorldPixMap (src));
1019 LockPixels (GetGWorldPixMap (mask));
1020 LockPixels (GetGWorldPixMap (dest));
1021 #if TARGET_API_MAC_CARBON
1022 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1023 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1024 #else /* not TARGET_API_MAC_CARBON */
1025 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1026 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1027 #endif /* not TARGET_API_MAC_CARBON */
1028 UnlockPixels (GetGWorldPixMap (dest));
1029 UnlockPixels (GetGWorldPixMap (mask));
1030 UnlockPixels (GetGWorldPixMap (src));
1032 SetGWorld (old_port, old_gdh);
1034 #endif
1037 /* Mac replacement for XChangeGC. */
1039 static void
1040 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1041 XGCValues *xgcv)
1043 if (mask & GCForeground)
1044 gc->foreground = xgcv->foreground;
1045 if (mask & GCBackground)
1046 gc->background = xgcv->background;
1047 if (mask & GCFont)
1048 gc->font = xgcv->font;
1052 /* Mac replacement for XCreateGC. */
1054 XGCValues *
1055 XCreateGC (void * ignore, Window window, unsigned long mask,
1056 XGCValues *xgcv)
1058 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1059 bzero (gc, sizeof (XGCValues));
1061 XChangeGC (ignore, gc, mask, xgcv);
1063 return gc;
1067 /* Used in xfaces.c. */
1069 void
1070 XFreeGC (display, gc)
1071 Display *display;
1072 GC gc;
1074 xfree (gc);
1078 /* Mac replacement for XGetGCValues. */
1080 static void
1081 XGetGCValues (void* ignore, XGCValues *gc,
1082 unsigned long mask, XGCValues *xgcv)
1084 XChangeGC (ignore, xgcv, mask, gc);
1088 /* Mac replacement for XSetForeground. */
1090 void
1091 XSetForeground (display, gc, color)
1092 Display *display;
1093 GC gc;
1094 unsigned long color;
1096 gc->foreground = color;
1100 /* Mac replacement for XSetFont. */
1102 static void
1103 XSetFont (display, gc, font)
1104 Display *display;
1105 GC gc;
1106 XFontStruct *font;
1108 gc->font = font;
1112 static void
1113 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1114 int *direction,int *font_ascent,
1115 int *font_descent, XCharStruct *cs)
1117 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1121 /* x_sync is a no-op on Mac. */
1122 void
1123 x_sync (f)
1124 void *f;
1129 /* Flush display of frame F, or of all frames if F is null. */
1131 static void
1132 x_flush (f)
1133 struct frame *f;
1135 #if TARGET_API_MAC_CARBON
1136 BLOCK_INPUT;
1137 if (f)
1138 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1139 else
1140 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1141 UNBLOCK_INPUT;
1142 #endif
1146 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1147 Calls to XFlush should be unnecessary because the X output buffer
1148 is flushed automatically as needed by calls to XPending,
1149 XNextEvent, or XWindowEvent according to the XFlush man page.
1150 XTread_socket calls XPending. Removing XFlush improves
1151 performance. */
1153 #define XFlush(DISPLAY) (void) 0
1156 /* Return the struct mac_display_info corresponding to DPY. There's
1157 only one. */
1159 struct mac_display_info *
1160 mac_display_info_for_display (dpy)
1161 Display *dpy;
1163 return &one_mac_display_info;
1168 /***********************************************************************
1169 Starting and ending an update
1170 ***********************************************************************/
1172 /* Start an update of frame F. This function is installed as a hook
1173 for update_begin, i.e. it is called when update_begin is called.
1174 This function is called prior to calls to x_update_window_begin for
1175 each window being updated. */
1177 static void
1178 x_update_begin (f)
1179 struct frame *f;
1181 /* Nothing to do. */
1185 /* Start update of window W. Set the global variable updated_window
1186 to the window being updated and set output_cursor to the cursor
1187 position of W. */
1189 static void
1190 x_update_window_begin (w)
1191 struct window *w;
1193 struct frame *f = XFRAME (WINDOW_FRAME (w));
1194 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1196 updated_window = w;
1197 set_output_cursor (&w->cursor);
1199 BLOCK_INPUT;
1201 if (f == display_info->mouse_face_mouse_frame)
1203 /* Don't do highlighting for mouse motion during the update. */
1204 display_info->mouse_face_defer = 1;
1206 /* If F needs to be redrawn, simply forget about any prior mouse
1207 highlighting. */
1208 if (FRAME_GARBAGED_P (f))
1209 display_info->mouse_face_window = Qnil;
1211 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1212 their mouse_face_p flag set, which means that they are always
1213 unequal to rows in a desired matrix which never have that
1214 flag set. So, rows containing mouse-face glyphs are never
1215 scrolled, and we don't have to switch the mouse highlight off
1216 here to prevent it from being scrolled. */
1218 /* Can we tell that this update does not affect the window
1219 where the mouse highlight is? If so, no need to turn off.
1220 Likewise, don't do anything if the frame is garbaged;
1221 in that case, the frame's current matrix that we would use
1222 is all wrong, and we will redisplay that line anyway. */
1223 if (!NILP (display_info->mouse_face_window)
1224 && w == XWINDOW (display_info->mouse_face_window))
1226 int i;
1228 for (i = 0; i < w->desired_matrix->nrows; ++i)
1229 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1230 break;
1232 if (i < w->desired_matrix->nrows)
1233 clear_mouse_face (display_info);
1235 #endif /* 0 */
1238 UNBLOCK_INPUT;
1242 /* Draw a vertical window border from (x,y0) to (x,y1) */
1244 static void
1245 mac_draw_vertical_window_border (w, x, y0, y1)
1246 struct window *w;
1247 int x, y0, y1;
1249 struct frame *f = XFRAME (WINDOW_FRAME (w));
1251 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1252 f->output_data.mac->normal_gc, x, y0, x, y1);
1256 /* End update of window W (which is equal to updated_window).
1258 Draw vertical borders between horizontally adjacent windows, and
1259 display W's cursor if CURSOR_ON_P is non-zero.
1261 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1262 glyphs in mouse-face were overwritten. In that case we have to
1263 make sure that the mouse-highlight is properly redrawn.
1265 W may be a menu bar pseudo-window in case we don't have X toolkit
1266 support. Such windows don't have a cursor, so don't display it
1267 here. */
1269 static void
1270 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1271 struct window *w;
1272 int cursor_on_p, mouse_face_overwritten_p;
1274 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1276 if (!w->pseudo_window_p)
1278 BLOCK_INPUT;
1280 if (cursor_on_p)
1281 display_and_set_cursor (w, 1, output_cursor.hpos,
1282 output_cursor.vpos,
1283 output_cursor.x, output_cursor.y);
1285 if (draw_window_fringes (w, 1))
1286 x_draw_vertical_border (w);
1288 UNBLOCK_INPUT;
1291 /* If a row with mouse-face was overwritten, arrange for
1292 XTframe_up_to_date to redisplay the mouse highlight. */
1293 if (mouse_face_overwritten_p)
1295 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1296 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1297 dpyinfo->mouse_face_window = Qnil;
1300 #if 0
1301 /* Unhide the caret. This won't actually show the cursor, unless it
1302 was visible before the corresponding call to HideCaret in
1303 x_update_window_begin. */
1304 if (w32_use_visible_system_caret)
1305 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1306 #endif
1308 updated_window = NULL;
1312 /* End update of frame F. This function is installed as a hook in
1313 update_end. */
1315 static void
1316 x_update_end (f)
1317 struct frame *f;
1319 /* Mouse highlight may be displayed again. */
1320 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1322 BLOCK_INPUT;
1323 /* Reset the background color of Mac OS Window to that of the frame after
1324 update so that it is used by Mac Toolbox to clear the update region before
1325 an update event is generated. */
1326 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1328 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1330 XFlush (FRAME_MAC_DISPLAY (f));
1331 UNBLOCK_INPUT;
1335 /* This function is called from various places in xdisp.c whenever a
1336 complete update has been performed. The global variable
1337 updated_window is not available here. */
1339 static void
1340 XTframe_up_to_date (f)
1341 struct frame *f;
1343 if (FRAME_MAC_P (f))
1345 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1347 if (dpyinfo->mouse_face_deferred_gc
1348 || f == dpyinfo->mouse_face_mouse_frame)
1350 BLOCK_INPUT;
1351 if (dpyinfo->mouse_face_mouse_frame)
1352 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1353 dpyinfo->mouse_face_mouse_x,
1354 dpyinfo->mouse_face_mouse_y);
1355 dpyinfo->mouse_face_deferred_gc = 0;
1356 UNBLOCK_INPUT;
1362 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1363 arrow bitmaps, or clear the fringes if no bitmaps are required
1364 before DESIRED_ROW is made current. The window being updated is
1365 found in updated_window. This function is called from
1366 update_window_line only if it is known that there are differences
1367 between bitmaps to be drawn between current row and DESIRED_ROW. */
1369 static void
1370 x_after_update_window_line (desired_row)
1371 struct glyph_row *desired_row;
1373 struct window *w = updated_window;
1374 struct frame *f;
1375 int width, height;
1377 xassert (w);
1379 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1380 desired_row->redraw_fringe_bitmaps_p = 1;
1382 /* When a window has disappeared, make sure that no rest of
1383 full-width rows stays visible in the internal border. Could
1384 check here if updated_window is the leftmost/rightmost window,
1385 but I guess it's not worth doing since vertically split windows
1386 are almost never used, internal border is rarely set, and the
1387 overhead is very small. */
1388 if (windows_or_buffers_changed
1389 && desired_row->full_width_p
1390 && (f = XFRAME (w->frame),
1391 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1392 width != 0)
1393 && (height = desired_row->visible_height,
1394 height > 0))
1396 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1397 /* Internal border is drawn below the tool bar. */
1398 if (WINDOWP (f->tool_bar_window)
1399 && w == XWINDOW (f->tool_bar_window))
1400 y -= width;
1402 BLOCK_INPUT;
1404 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1405 0, y, width, height, 0);
1406 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1407 FRAME_PIXEL_WIDTH (f) - width, y,
1408 width, height, 0);
1410 UNBLOCK_INPUT;
1415 /* Draw the bitmap WHICH in one of the left or right fringes of
1416 window W. ROW is the glyph row for which to display the bitmap; it
1417 determines the vertical position at which the bitmap has to be
1418 drawn. */
1420 static void
1421 x_draw_fringe_bitmap (w, row, p)
1422 struct window *w;
1423 struct glyph_row *row;
1424 struct draw_fringe_bitmap_params *p;
1426 struct frame *f = XFRAME (WINDOW_FRAME (w));
1427 Display *display = FRAME_MAC_DISPLAY (f);
1428 WindowPtr window = FRAME_MAC_WINDOW (f);
1429 XGCValues gcv;
1430 GC gc = f->output_data.mac->normal_gc;
1431 struct face *face = p->face;
1432 int rowY;
1434 /* Must clip because of partially visible lines. */
1435 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1436 if (p->y < rowY)
1438 /* Adjust position of "bottom aligned" bitmap on partially
1439 visible last row. */
1440 int oldY = row->y;
1441 int oldVH = row->visible_height;
1442 row->visible_height = p->h;
1443 row->y -= rowY - p->y;
1444 x_clip_to_row (w, row, -1, gc);
1445 row->y = oldY;
1446 row->visible_height = oldVH;
1448 else
1449 x_clip_to_row (w, row, -1, gc);
1451 if (p->bx >= 0 && !p->overlay_p)
1453 XGCValues gcv;
1454 gcv.foreground = face->background;
1456 #if 0 /* MAC_TODO: stipple */
1457 /* In case the same realized face is used for fringes and
1458 for something displayed in the text (e.g. face `region' on
1459 mono-displays, the fill style may have been changed to
1460 FillSolid in x_draw_glyph_string_background. */
1461 if (face->stipple)
1462 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1463 else
1464 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1465 #endif
1467 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1468 &gcv,
1469 p->bx, p->by, p->nx, p->ny);
1471 #if 0 /* MAC_TODO: stipple */
1472 if (!face->stipple)
1473 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1474 #endif
1477 if (p->which)
1479 unsigned short *bits = p->bits + p->dh;
1481 gcv.foreground = (p->cursor_p
1482 ? (p->overlay_p ? face->background
1483 : f->output_data.mac->cursor_pixel)
1484 : face->foreground);
1485 gcv.background = face->background;
1487 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1488 p->wd, p->h, bits, p->overlay_p);
1491 mac_reset_clipping (display, window);
1495 /* This is called when starting Emacs and when restarting after
1496 suspend. When starting Emacs, no window is mapped. And nothing
1497 must be done to Emacs's own window if it is suspended (though that
1498 rarely happens). */
1500 static void
1501 XTset_terminal_modes ()
1505 /* This is called when exiting or suspending Emacs. Exiting will make
1506 the windows go away, and suspending requires no action. */
1508 static void
1509 XTreset_terminal_modes ()
1514 /***********************************************************************
1515 Display Iterator
1516 ***********************************************************************/
1518 /* Function prototypes of this page. */
1520 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1521 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1524 /* Return a pointer to per-char metric information in FONT of a
1525 character pointed by B which is a pointer to an XChar2b. */
1527 #define PER_CHAR_METRIC(font, b) \
1528 ((font)->per_char \
1529 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1530 + (((font)->min_byte1 || (font)->max_byte1) \
1531 ? (((b)->byte1 - (font)->min_byte1) \
1532 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1533 : 0)) \
1534 : &((font)->max_bounds))
1537 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1538 is not contained in the font. */
1540 static INLINE XCharStruct *
1541 x_per_char_metric (font, char2b)
1542 XFontStruct *font;
1543 XChar2b *char2b;
1545 /* The result metric information. */
1546 XCharStruct *pcm = NULL;
1548 xassert (font && char2b);
1550 if (font->per_char != NULL)
1552 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1554 /* min_char_or_byte2 specifies the linear character index
1555 corresponding to the first element of the per_char array,
1556 max_char_or_byte2 is the index of the last character. A
1557 character with non-zero CHAR2B->byte1 is not in the font.
1558 A character with byte2 less than min_char_or_byte2 or
1559 greater max_char_or_byte2 is not in the font. */
1560 if (char2b->byte1 == 0
1561 && char2b->byte2 >= font->min_char_or_byte2
1562 && char2b->byte2 <= font->max_char_or_byte2)
1563 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1565 else
1567 /* If either min_byte1 or max_byte1 are nonzero, both
1568 min_char_or_byte2 and max_char_or_byte2 are less than
1569 256, and the 2-byte character index values corresponding
1570 to the per_char array element N (counting from 0) are:
1572 byte1 = N/D + min_byte1
1573 byte2 = N\D + min_char_or_byte2
1575 where:
1577 D = max_char_or_byte2 - min_char_or_byte2 + 1
1578 / = integer division
1579 \ = integer modulus */
1580 if (char2b->byte1 >= font->min_byte1
1581 && char2b->byte1 <= font->max_byte1
1582 && char2b->byte2 >= font->min_char_or_byte2
1583 && char2b->byte2 <= font->max_char_or_byte2)
1585 pcm = (font->per_char
1586 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1587 * (char2b->byte1 - font->min_byte1))
1588 + (char2b->byte2 - font->min_char_or_byte2));
1592 else
1594 /* If the per_char pointer is null, all glyphs between the first
1595 and last character indexes inclusive have the same
1596 information, as given by both min_bounds and max_bounds. */
1597 if (char2b->byte2 >= font->min_char_or_byte2
1598 && char2b->byte2 <= font->max_char_or_byte2)
1599 pcm = &font->max_bounds;
1602 return ((pcm == NULL
1603 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1604 ? NULL : pcm);
1607 /* RIF:
1610 static XCharStruct *
1611 mac_per_char_metric (font, char2b, font_type)
1612 XFontStruct *font;
1613 XChar2b *char2b;
1614 int font_type;
1616 return x_per_char_metric (font, char2b);
1619 /* RIF:
1620 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1621 the two-byte form of C. Encoding is returned in *CHAR2B. */
1623 static int
1624 mac_encode_char (c, char2b, font_info, two_byte_p)
1625 int c;
1626 XChar2b *char2b;
1627 struct font_info *font_info;
1628 int *two_byte_p;
1630 int charset = CHAR_CHARSET (c);
1631 XFontStruct *font = font_info->font;
1633 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1634 This may be either a program in a special encoder language or a
1635 fixed encoding. */
1636 if (font_info->font_encoder)
1638 /* It's a program. */
1639 struct ccl_program *ccl = font_info->font_encoder;
1641 if (CHARSET_DIMENSION (charset) == 1)
1643 ccl->reg[0] = charset;
1644 ccl->reg[1] = char2b->byte2;
1646 else
1648 ccl->reg[0] = charset;
1649 ccl->reg[1] = char2b->byte1;
1650 ccl->reg[2] = char2b->byte2;
1653 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1655 /* We assume that MSBs are appropriately set/reset by CCL
1656 program. */
1657 if (font->max_byte1 == 0) /* 1-byte font */
1658 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1659 else
1660 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1662 else if (font_info->encoding[charset])
1664 /* Fixed encoding scheme. See fontset.h for the meaning of the
1665 encoding numbers. */
1666 int enc = font_info->encoding[charset];
1668 if ((enc == 1 || enc == 2)
1669 && CHARSET_DIMENSION (charset) == 2)
1670 char2b->byte1 |= 0x80;
1672 if (enc == 1 || enc == 3)
1673 char2b->byte2 |= 0x80;
1675 if (enc == 4)
1677 int sjis1, sjis2;
1679 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1680 char2b->byte1 = sjis1;
1681 char2b->byte2 = sjis2;
1685 if (two_byte_p)
1686 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1688 return FONT_TYPE_UNKNOWN;
1693 /***********************************************************************
1694 Glyph display
1695 ***********************************************************************/
1698 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1699 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1700 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1701 int));
1702 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1703 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1704 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1705 static void x_draw_glyph_string P_ ((struct glyph_string *));
1706 static void x_set_cursor_gc P_ ((struct glyph_string *));
1707 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1708 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1709 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1710 unsigned long *, double, int));*/
1711 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1712 double, int, unsigned long));
1713 static void x_setup_relief_colors P_ ((struct glyph_string *));
1714 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1715 static void x_draw_image_relief P_ ((struct glyph_string *));
1716 static void x_draw_image_foreground P_ ((struct glyph_string *));
1717 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1718 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1719 int, int, int));
1720 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1721 int, int, int, int, int, int,
1722 Rect *));
1723 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1724 int, int, int, Rect *));
1726 #if GLYPH_DEBUG
1727 static void x_check_font P_ ((struct frame *, XFontStruct *));
1728 #endif
1731 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1732 face. */
1734 static void
1735 x_set_cursor_gc (s)
1736 struct glyph_string *s;
1738 if (s->font == FRAME_FONT (s->f)
1739 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1740 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1741 && !s->cmp)
1742 s->gc = s->f->output_data.mac->cursor_gc;
1743 else
1745 /* Cursor on non-default face: must merge. */
1746 XGCValues xgcv;
1747 unsigned long mask;
1749 xgcv.background = s->f->output_data.mac->cursor_pixel;
1750 xgcv.foreground = s->face->background;
1752 /* If the glyph would be invisible, try a different foreground. */
1753 if (xgcv.foreground == xgcv.background)
1754 xgcv.foreground = s->face->foreground;
1755 if (xgcv.foreground == xgcv.background)
1756 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1757 if (xgcv.foreground == xgcv.background)
1758 xgcv.foreground = s->face->foreground;
1760 /* Make sure the cursor is distinct from text in this face. */
1761 if (xgcv.background == s->face->background
1762 && xgcv.foreground == s->face->foreground)
1764 xgcv.background = s->face->foreground;
1765 xgcv.foreground = s->face->background;
1768 IF_DEBUG (x_check_font (s->f, s->font));
1769 xgcv.font = s->font;
1770 mask = GCForeground | GCBackground | GCFont;
1772 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1773 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1774 mask, &xgcv);
1775 else
1776 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1777 = XCreateGC (s->display, s->window, mask, &xgcv);
1779 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1784 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1786 static void
1787 x_set_mouse_face_gc (s)
1788 struct glyph_string *s;
1790 int face_id;
1791 struct face *face;
1793 /* What face has to be used last for the mouse face? */
1794 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1795 face = FACE_FROM_ID (s->f, face_id);
1796 if (face == NULL)
1797 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1799 if (s->first_glyph->type == CHAR_GLYPH)
1800 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1801 else
1802 face_id = FACE_FOR_CHAR (s->f, face, 0);
1803 s->face = FACE_FROM_ID (s->f, face_id);
1804 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1806 /* If font in this face is same as S->font, use it. */
1807 if (s->font == s->face->font)
1808 s->gc = s->face->gc;
1809 else
1811 /* Otherwise construct scratch_cursor_gc with values from FACE
1812 but font FONT. */
1813 XGCValues xgcv;
1814 unsigned long mask;
1816 xgcv.background = s->face->background;
1817 xgcv.foreground = s->face->foreground;
1818 IF_DEBUG (x_check_font (s->f, s->font));
1819 xgcv.font = s->font;
1820 mask = GCForeground | GCBackground | GCFont;
1822 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1823 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1824 mask, &xgcv);
1825 else
1826 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1827 = XCreateGC (s->display, s->window, mask, &xgcv);
1829 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1832 xassert (s->gc != 0);
1836 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1837 Faces to use in the mode line have already been computed when the
1838 matrix was built, so there isn't much to do, here. */
1840 static INLINE void
1841 x_set_mode_line_face_gc (s)
1842 struct glyph_string *s;
1844 s->gc = s->face->gc;
1848 /* Set S->gc of glyph string S for drawing that glyph string. Set
1849 S->stippled_p to a non-zero value if the face of S has a stipple
1850 pattern. */
1852 static INLINE void
1853 x_set_glyph_string_gc (s)
1854 struct glyph_string *s;
1856 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1858 if (s->hl == DRAW_NORMAL_TEXT)
1860 s->gc = s->face->gc;
1861 s->stippled_p = s->face->stipple != 0;
1863 else if (s->hl == DRAW_INVERSE_VIDEO)
1865 x_set_mode_line_face_gc (s);
1866 s->stippled_p = s->face->stipple != 0;
1868 else if (s->hl == DRAW_CURSOR)
1870 x_set_cursor_gc (s);
1871 s->stippled_p = 0;
1873 else if (s->hl == DRAW_MOUSE_FACE)
1875 x_set_mouse_face_gc (s);
1876 s->stippled_p = s->face->stipple != 0;
1878 else if (s->hl == DRAW_IMAGE_RAISED
1879 || s->hl == DRAW_IMAGE_SUNKEN)
1881 s->gc = s->face->gc;
1882 s->stippled_p = s->face->stipple != 0;
1884 else
1886 s->gc = s->face->gc;
1887 s->stippled_p = s->face->stipple != 0;
1890 /* GC must have been set. */
1891 xassert (s->gc != 0);
1895 /* Set clipping for output of glyph string S. S may be part of a mode
1896 line or menu if we don't have X toolkit support. */
1898 static INLINE void
1899 x_set_glyph_string_clipping (s)
1900 struct glyph_string *s;
1902 Rect r;
1903 get_glyph_string_clip_rect (s, &r);
1904 mac_set_clip_rectangle (s->display, s->window, &r);
1908 /* RIF:
1909 Compute left and right overhang of glyph string S. If S is a glyph
1910 string for a composition, assume overhangs don't exist. */
1912 static void
1913 mac_compute_glyph_string_overhangs (s)
1914 struct glyph_string *s;
1916 #if 0
1917 /* MAC_TODO: XTextExtents16 does nothing yet... */
1919 if (s->cmp == NULL
1920 && s->first_glyph->type == CHAR_GLYPH)
1922 XCharStruct cs;
1923 int direction, font_ascent, font_descent;
1924 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
1925 &font_ascent, &font_descent, &cs);
1926 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
1927 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
1929 #endif
1933 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1935 static INLINE void
1936 x_clear_glyph_string_rect (s, x, y, w, h)
1937 struct glyph_string *s;
1938 int x, y, w, h;
1940 XGCValues xgcv;
1942 xgcv.foreground = s->gc->background;
1943 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
1947 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
1948 on Mac OS X because:
1949 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1950 into an offscreen graphics world first. So performance gain
1951 cannot be expected.)
1952 - It lowers rendering quality.
1953 - Some fonts leave garbage on cursor movement. */
1955 /* Draw the background of glyph_string S. If S->background_filled_p
1956 is non-zero don't draw it. FORCE_P non-zero means draw the
1957 background even if it wouldn't be drawn normally. This is used
1958 when a string preceding S draws into the background of S, or S
1959 contains the first component of a composition. */
1961 static void
1962 x_draw_glyph_string_background (s, force_p)
1963 struct glyph_string *s;
1964 int force_p;
1966 /* Nothing to do if background has already been drawn or if it
1967 shouldn't be drawn in the first place. */
1968 if (!s->background_filled_p)
1970 int box_line_width = max (s->face->box_line_width, 0);
1972 #if 0 /* MAC_TODO: stipple */
1973 if (s->stippled_p)
1975 /* Fill background with a stipple pattern. */
1976 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1977 XFillRectangle (s->display, s->window, s->gc, s->x,
1978 s->y + box_line_width,
1979 s->background_width,
1980 s->height - 2 * box_line_width);
1981 XSetFillStyle (s->display, s->gc, FillSolid);
1982 s->background_filled_p = 1;
1984 else
1985 #endif
1986 #if 0 /* defined(MAC_OS8)*/
1987 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1988 || s->font_not_found_p
1989 || s->extends_to_end_of_line_p
1990 || force_p)
1991 #endif
1993 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1994 s->background_width,
1995 s->height - 2 * box_line_width);
1996 s->background_filled_p = 1;
2002 /* Draw the foreground of glyph string S. */
2004 static void
2005 x_draw_glyph_string_foreground (s)
2006 struct glyph_string *s;
2008 int i, x;
2010 /* If first glyph of S has a left box line, start drawing the text
2011 of S to the right of that box line. */
2012 if (s->face->box != FACE_NO_BOX
2013 && s->first_glyph->left_box_line_p)
2014 x = s->x + abs (s->face->box_line_width);
2015 else
2016 x = s->x;
2018 /* Draw characters of S as rectangles if S's font could not be
2019 loaded. */
2020 if (s->font_not_found_p)
2022 for (i = 0; i < s->nchars; ++i)
2024 struct glyph *g = s->first_glyph + i;
2025 mac_draw_rectangle (s->display, s->window,
2026 s->gc, x, s->y, g->pixel_width - 1,
2027 s->height - 1);
2028 x += g->pixel_width;
2031 else
2033 char *char1b = (char *) s->char2b;
2034 int boff = s->font_info->baseline_offset;
2036 if (s->font_info->vertical_centering)
2037 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2039 /* If we can use 8-bit functions, condense S->char2b. */
2040 if (!s->two_byte_p)
2041 for (i = 0; i < s->nchars; ++i)
2042 char1b[i] = s->char2b[i].byte2;
2044 #if 0 /* defined(MAC_OS8) */
2045 /* Draw text with XDrawString if background has already been
2046 filled. Otherwise, use XDrawImageString. (Note that
2047 XDrawImageString is usually faster than XDrawString.) Always
2048 use XDrawImageString when drawing the cursor so that there is
2049 no chance that characters under a box cursor are invisible. */
2050 if (s->for_overlaps_p
2051 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2052 #endif
2054 /* Draw characters with 16-bit or 8-bit functions. */
2055 if (s->two_byte_p)
2056 XDrawString16 (s->display, s->window, s->gc, x,
2057 s->ybase - boff, s->char2b, s->nchars);
2058 else
2059 XDrawString (s->display, s->window, s->gc, x,
2060 s->ybase - boff, char1b, s->nchars);
2062 #if 0 /* defined(MAC_OS8)*/
2063 else
2065 if (s->two_byte_p)
2066 XDrawImageString16 (s->display, s->window, s->gc, x,
2067 s->ybase - boff, s->char2b, s->nchars);
2068 else
2069 XDrawImageString (s->display, s->window, s->gc, x,
2070 s->ybase - boff, char1b, s->nchars);
2072 #endif
2076 /* Draw the foreground of composite glyph string S. */
2078 static void
2079 x_draw_composite_glyph_string_foreground (s)
2080 struct glyph_string *s;
2082 int i, x;
2084 /* If first glyph of S has a left box line, start drawing the text
2085 of S to the right of that box line. */
2086 if (s->face->box != FACE_NO_BOX
2087 && s->first_glyph->left_box_line_p)
2088 x = s->x + abs (s->face->box_line_width);
2089 else
2090 x = s->x;
2092 /* S is a glyph string for a composition. S->gidx is the index of
2093 the first character drawn for glyphs of this composition.
2094 S->gidx == 0 means we are drawing the very first character of
2095 this composition. */
2097 /* Draw a rectangle for the composition if the font for the very
2098 first character of the composition could not be loaded. */
2099 if (s->font_not_found_p)
2101 if (s->gidx == 0)
2102 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2103 s->width - 1, s->height - 1);
2105 else
2107 for (i = 0; i < s->nchars; i++, ++s->gidx)
2108 XDrawString16 (s->display, s->window, s->gc,
2109 x + s->cmp->offsets[s->gidx * 2],
2110 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2111 s->char2b + i, 1);
2116 #ifdef USE_X_TOOLKIT
2118 static struct frame *x_frame_of_widget P_ ((Widget));
2121 /* Return the frame on which widget WIDGET is used.. Abort if frame
2122 cannot be determined. */
2124 static struct frame *
2125 x_frame_of_widget (widget)
2126 Widget widget;
2128 struct x_display_info *dpyinfo;
2129 Lisp_Object tail;
2130 struct frame *f;
2132 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2134 /* Find the top-level shell of the widget. Note that this function
2135 can be called when the widget is not yet realized, so XtWindow
2136 (widget) == 0. That's the reason we can't simply use
2137 x_any_window_to_frame. */
2138 while (!XtIsTopLevelShell (widget))
2139 widget = XtParent (widget);
2141 /* Look for a frame with that top-level widget. Allocate the color
2142 on that frame to get the right gamma correction value. */
2143 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2144 if (GC_FRAMEP (XCAR (tail))
2145 && (f = XFRAME (XCAR (tail)),
2146 (f->output_data.nothing != 1
2147 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2148 && f->output_data.x->widget == widget)
2149 return f;
2151 abort ();
2155 /* Allocate the color COLOR->pixel on the screen and display of
2156 widget WIDGET in colormap CMAP. If an exact match cannot be
2157 allocated, try the nearest color available. Value is non-zero
2158 if successful. This is called from lwlib. */
2161 x_alloc_nearest_color_for_widget (widget, cmap, color)
2162 Widget widget;
2163 Colormap cmap;
2164 XColor *color;
2166 struct frame *f = x_frame_of_widget (widget);
2167 return x_alloc_nearest_color (f, cmap, color);
2171 #endif /* USE_X_TOOLKIT */
2173 #if 0 /* MAC_TODO */
2175 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2176 CMAP. If an exact match can't be allocated, try the nearest color
2177 available. Value is non-zero if successful. Set *COLOR to the
2178 color allocated. */
2181 x_alloc_nearest_color (f, cmap, color)
2182 struct frame *f;
2183 Colormap cmap;
2184 XColor *color;
2186 Display *display = FRAME_X_DISPLAY (f);
2187 Screen *screen = FRAME_X_SCREEN (f);
2188 int rc;
2190 gamma_correct (f, color);
2191 rc = XAllocColor (display, cmap, color);
2192 if (rc == 0)
2194 /* If we got to this point, the colormap is full, so we're going
2195 to try to get the next closest color. The algorithm used is
2196 a least-squares matching, which is what X uses for closest
2197 color matching with StaticColor visuals. */
2198 int nearest, i;
2199 unsigned long nearest_delta = ~0;
2200 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2201 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2203 for (i = 0; i < ncells; ++i)
2204 cells[i].pixel = i;
2205 XQueryColors (display, cmap, cells, ncells);
2207 for (nearest = i = 0; i < ncells; ++i)
2209 long dred = (color->red >> 8) - (cells[i].red >> 8);
2210 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2211 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2212 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2214 if (delta < nearest_delta)
2216 nearest = i;
2217 nearest_delta = delta;
2221 color->red = cells[nearest].red;
2222 color->green = cells[nearest].green;
2223 color->blue = cells[nearest].blue;
2224 rc = XAllocColor (display, cmap, color);
2227 #ifdef DEBUG_X_COLORS
2228 if (rc)
2229 register_color (color->pixel);
2230 #endif /* DEBUG_X_COLORS */
2232 return rc;
2236 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2237 It's necessary to do this instead of just using PIXEL directly to
2238 get color reference counts right. */
2240 unsigned long
2241 x_copy_color (f, pixel)
2242 struct frame *f;
2243 unsigned long pixel;
2245 XColor color;
2247 color.pixel = pixel;
2248 BLOCK_INPUT;
2249 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2250 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2251 UNBLOCK_INPUT;
2252 #ifdef DEBUG_X_COLORS
2253 register_color (pixel);
2254 #endif
2255 return color.pixel;
2259 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2260 It's necessary to do this instead of just using PIXEL directly to
2261 get color reference counts right. */
2263 unsigned long
2264 x_copy_dpy_color (dpy, cmap, pixel)
2265 Display *dpy;
2266 Colormap cmap;
2267 unsigned long pixel;
2269 XColor color;
2271 color.pixel = pixel;
2272 BLOCK_INPUT;
2273 XQueryColor (dpy, cmap, &color);
2274 XAllocColor (dpy, cmap, &color);
2275 UNBLOCK_INPUT;
2276 #ifdef DEBUG_X_COLORS
2277 register_color (pixel);
2278 #endif
2279 return color.pixel;
2282 #endif /* MAC_TODO */
2285 /* Brightness beyond which a color won't have its highlight brightness
2286 boosted.
2288 Nominally, highlight colors for `3d' faces are calculated by
2289 brightening an object's color by a constant scale factor, but this
2290 doesn't yield good results for dark colors, so for colors who's
2291 brightness is less than this value (on a scale of 0-255) have to
2292 use an additional additive factor.
2294 The value here is set so that the default menu-bar/mode-line color
2295 (grey75) will not have its highlights changed at all. */
2296 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2299 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2300 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2301 If this produces the same color as COLOR, try a color where all RGB
2302 values have DELTA added. Return the allocated color in *COLOR.
2303 DISPLAY is the X display, CMAP is the colormap to operate on.
2304 Value is non-zero if successful. */
2306 static int
2307 mac_alloc_lighter_color (f, color, factor, delta)
2308 struct frame *f;
2309 unsigned long *color;
2310 double factor;
2311 int delta;
2313 unsigned long new;
2314 long bright;
2316 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2317 delta /= 256;
2319 /* Change RGB values by specified FACTOR. Avoid overflow! */
2320 xassert (factor >= 0);
2321 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2322 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2323 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2325 /* Calculate brightness of COLOR. */
2326 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2327 + BLUE_FROM_ULONG (*color)) / 6;
2329 /* We only boost colors that are darker than
2330 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2331 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2332 /* Make an additive adjustment to NEW, because it's dark enough so
2333 that scaling by FACTOR alone isn't enough. */
2335 /* How far below the limit this color is (0 - 1, 1 being darker). */
2336 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2337 /* The additive adjustment. */
2338 int min_delta = delta * dimness * factor / 2;
2340 if (factor < 1)
2341 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2342 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2343 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2344 else
2345 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2346 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2347 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2350 if (new == *color)
2351 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2352 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2353 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2355 /* MAC_TODO: Map to palette and retry with delta if same? */
2356 /* MAC_TODO: Free colors (if using palette)? */
2358 if (new == *color)
2359 return 0;
2361 *color = new;
2363 return 1;
2367 /* Set up the foreground color for drawing relief lines of glyph
2368 string S. RELIEF is a pointer to a struct relief containing the GC
2369 with which lines will be drawn. Use a color that is FACTOR or
2370 DELTA lighter or darker than the relief's background which is found
2371 in S->f->output_data.x->relief_background. If such a color cannot
2372 be allocated, use DEFAULT_PIXEL, instead. */
2374 static void
2375 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2376 struct frame *f;
2377 struct relief *relief;
2378 double factor;
2379 int delta;
2380 unsigned long default_pixel;
2382 XGCValues xgcv;
2383 struct mac_output *di = f->output_data.mac;
2384 unsigned long mask = GCForeground;
2385 unsigned long pixel;
2386 unsigned long background = di->relief_background;
2387 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2389 /* MAC_TODO: Free colors (if using palette)? */
2391 /* Allocate new color. */
2392 xgcv.foreground = default_pixel;
2393 pixel = background;
2394 if (dpyinfo->n_planes != 1
2395 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2397 relief->allocated_p = 1;
2398 xgcv.foreground = relief->pixel = pixel;
2401 if (relief->gc == 0)
2403 #if 0 /* MAC_TODO: stipple */
2404 xgcv.stipple = dpyinfo->gray;
2405 mask |= GCStipple;
2406 #endif
2407 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2409 else
2410 XChangeGC (NULL, relief->gc, mask, &xgcv);
2414 /* Set up colors for the relief lines around glyph string S. */
2416 static void
2417 x_setup_relief_colors (s)
2418 struct glyph_string *s;
2420 struct mac_output *di = s->f->output_data.mac;
2421 unsigned long color;
2423 if (s->face->use_box_color_for_shadows_p)
2424 color = s->face->box_color;
2425 else if (s->first_glyph->type == IMAGE_GLYPH
2426 && s->img->pixmap
2427 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2428 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2429 else
2431 XGCValues xgcv;
2433 /* Get the background color of the face. */
2434 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2435 color = xgcv.background;
2438 if (di->white_relief.gc == 0
2439 || color != di->relief_background)
2441 di->relief_background = color;
2442 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2443 WHITE_PIX_DEFAULT (s->f));
2444 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2445 BLACK_PIX_DEFAULT (s->f));
2450 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2451 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2452 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2453 relief. LEFT_P non-zero means draw a relief on the left side of
2454 the rectangle. RIGHT_P non-zero means draw a relief on the right
2455 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2456 when drawing. */
2458 static void
2459 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2460 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2461 struct frame *f;
2462 int left_x, top_y, right_x, bottom_y, width;
2463 int top_p, bot_p, left_p, right_p, raised_p;
2464 Rect *clip_rect;
2466 Display *dpy = FRAME_MAC_DISPLAY (f);
2467 Window window = FRAME_MAC_WINDOW (f);
2468 int i;
2469 GC gc;
2471 if (raised_p)
2472 gc = f->output_data.mac->white_relief.gc;
2473 else
2474 gc = f->output_data.mac->black_relief.gc;
2475 mac_set_clip_rectangle (dpy, window, clip_rect);
2477 /* Top. */
2478 if (top_p)
2479 for (i = 0; i < width; ++i)
2480 XDrawLine (dpy, window, gc,
2481 left_x + i * left_p, top_y + i,
2482 right_x - i * right_p, top_y + i);
2484 /* Left. */
2485 if (left_p)
2486 for (i = 0; i < width; ++i)
2487 XDrawLine (dpy, window, gc,
2488 left_x + i, top_y + i, left_x + i, bottom_y - i);
2490 mac_reset_clipping (dpy, window);
2491 if (raised_p)
2492 gc = f->output_data.mac->black_relief.gc;
2493 else
2494 gc = f->output_data.mac->white_relief.gc;
2495 mac_set_clip_rectangle (dpy, window,
2496 clip_rect);
2498 /* Bottom. */
2499 if (bot_p)
2500 for (i = 0; i < width; ++i)
2501 XDrawLine (dpy, window, gc,
2502 left_x + i * left_p, bottom_y - i,
2503 right_x - i * right_p, bottom_y - i);
2505 /* Right. */
2506 if (right_p)
2507 for (i = 0; i < width; ++i)
2508 XDrawLine (dpy, window, gc,
2509 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2511 mac_reset_clipping (dpy, window);
2515 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2516 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2517 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2518 left side of the rectangle. RIGHT_P non-zero means draw a line
2519 on the right side of the rectangle. CLIP_RECT is the clipping
2520 rectangle to use when drawing. */
2522 static void
2523 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2524 left_p, right_p, clip_rect)
2525 struct glyph_string *s;
2526 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2527 Rect *clip_rect;
2529 XGCValues xgcv;
2531 xgcv.foreground = s->face->box_color;
2532 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2534 /* Top. */
2535 XFillRectangle (s->display, s->window, &xgcv,
2536 left_x, top_y, right_x - left_x + 1, width);
2538 /* Left. */
2539 if (left_p)
2540 XFillRectangle (s->display, s->window, &xgcv,
2541 left_x, top_y, width, bottom_y - top_y + 1);
2543 /* Bottom. */
2544 XFillRectangle (s->display, s->window, &xgcv,
2545 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2547 /* Right. */
2548 if (right_p)
2549 XFillRectangle (s->display, s->window, &xgcv,
2550 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2552 mac_reset_clipping (s->display, s->window);
2556 /* Draw a box around glyph string S. */
2558 static void
2559 x_draw_glyph_string_box (s)
2560 struct glyph_string *s;
2562 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2563 int left_p, right_p;
2564 struct glyph *last_glyph;
2565 Rect clip_rect;
2567 last_x = window_box_right (s->w, s->area);
2568 if (s->row->full_width_p
2569 && !s->w->pseudo_window_p)
2571 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2572 if (s->area != RIGHT_MARGIN_AREA
2573 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2574 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2577 /* The glyph that may have a right box line. */
2578 last_glyph = (s->cmp || s->img
2579 ? s->first_glyph
2580 : s->first_glyph + s->nchars - 1);
2582 width = abs (s->face->box_line_width);
2583 raised_p = s->face->box == FACE_RAISED_BOX;
2584 left_x = s->x;
2585 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2586 ? last_x - 1
2587 : min (last_x, s->x + s->background_width) - 1);
2588 top_y = s->y;
2589 bottom_y = top_y + s->height - 1;
2591 left_p = (s->first_glyph->left_box_line_p
2592 || (s->hl == DRAW_MOUSE_FACE
2593 && (s->prev == NULL
2594 || s->prev->hl != s->hl)));
2595 right_p = (last_glyph->right_box_line_p
2596 || (s->hl == DRAW_MOUSE_FACE
2597 && (s->next == NULL
2598 || s->next->hl != s->hl)));
2600 get_glyph_string_clip_rect (s, &clip_rect);
2602 if (s->face->box == FACE_SIMPLE_BOX)
2603 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2604 left_p, right_p, &clip_rect);
2605 else
2607 x_setup_relief_colors (s);
2608 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2609 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2614 /* Draw foreground of image glyph string S. */
2616 static void
2617 x_draw_image_foreground (s)
2618 struct glyph_string *s;
2620 int x = s->x;
2621 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2623 /* If first glyph of S has a left box line, start drawing it to the
2624 right of that line. */
2625 if (s->face->box != FACE_NO_BOX
2626 && s->first_glyph->left_box_line_p
2627 && s->slice.x == 0)
2628 x += abs (s->face->box_line_width);
2630 /* If there is a margin around the image, adjust x- and y-position
2631 by that margin. */
2632 if (s->slice.x == 0)
2633 x += s->img->hmargin;
2634 if (s->slice.y == 0)
2635 y += s->img->vmargin;
2637 if (s->img->pixmap)
2639 x_set_glyph_string_clipping (s);
2641 if (s->img->mask)
2642 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2643 s->window, s->gc, s->slice.x, s->slice.y,
2644 s->slice.width, s->slice.height, x, y);
2645 else
2647 mac_copy_area (s->display, s->img->pixmap,
2648 s->window, s->gc, s->slice.x, s->slice.y,
2649 s->slice.width, s->slice.height, x, y);
2651 /* When the image has a mask, we can expect that at
2652 least part of a mouse highlight or a block cursor will
2653 be visible. If the image doesn't have a mask, make
2654 a block cursor visible by drawing a rectangle around
2655 the image. I believe it's looking better if we do
2656 nothing here for mouse-face. */
2657 if (s->hl == DRAW_CURSOR)
2659 int r = s->img->relief;
2660 if (r < 0) r = -r;
2661 mac_draw_rectangle (s->display, s->window, s->gc,
2662 x - r, y - r,
2663 s->slice.width + r*2 - 1,
2664 s->slice.height + r*2 - 1);
2668 else
2669 /* Draw a rectangle if image could not be loaded. */
2670 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2671 s->slice.width - 1, s->slice.height - 1);
2675 /* Draw a relief around the image glyph string S. */
2677 static void
2678 x_draw_image_relief (s)
2679 struct glyph_string *s;
2681 int x0, y0, x1, y1, thick, raised_p;
2682 Rect r;
2683 int x = s->x;
2684 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2686 /* If first glyph of S has a left box line, start drawing it to the
2687 right of that line. */
2688 if (s->face->box != FACE_NO_BOX
2689 && s->first_glyph->left_box_line_p
2690 && s->slice.x == 0)
2691 x += abs (s->face->box_line_width);
2693 /* If there is a margin around the image, adjust x- and y-position
2694 by that margin. */
2695 if (s->slice.x == 0)
2696 x += s->img->hmargin;
2697 if (s->slice.y == 0)
2698 y += s->img->vmargin;
2700 if (s->hl == DRAW_IMAGE_SUNKEN
2701 || s->hl == DRAW_IMAGE_RAISED)
2703 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2704 raised_p = s->hl == DRAW_IMAGE_RAISED;
2706 else
2708 thick = abs (s->img->relief);
2709 raised_p = s->img->relief > 0;
2712 x0 = x - thick;
2713 y0 = y - thick;
2714 x1 = x + s->slice.width + thick - 1;
2715 y1 = y + s->slice.height + thick - 1;
2717 x_setup_relief_colors (s);
2718 get_glyph_string_clip_rect (s, &r);
2719 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2720 s->slice.y == 0,
2721 s->slice.y + s->slice.height == s->img->height,
2722 s->slice.x == 0,
2723 s->slice.x + s->slice.width == s->img->width,
2724 &r);
2728 #if 0 /* TODO: figure out if we need to do this on Mac. */
2729 /* Draw the foreground of image glyph string S to PIXMAP. */
2731 static void
2732 x_draw_image_foreground_1 (s, pixmap)
2733 struct glyph_string *s;
2734 Pixmap pixmap;
2736 int x = 0;
2737 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2739 /* If first glyph of S has a left box line, start drawing it to the
2740 right of that line. */
2741 if (s->face->box != FACE_NO_BOX
2742 && s->first_glyph->left_box_line_p
2743 && s->slice.x == 0)
2744 x += abs (s->face->box_line_width);
2746 /* If there is a margin around the image, adjust x- and y-position
2747 by that margin. */
2748 if (s->slice.x == 0)
2749 x += s->img->hmargin;
2750 if (s->slice.y == 0)
2751 y += s->img->vmargin;
2753 if (s->img->pixmap)
2755 if (s->img->mask)
2756 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2757 s->img->mask, pixmap, s->gc,
2758 s->slice.x, s->slice.y,
2759 s->slice.width, s->slice.height,
2760 x, y);
2761 else
2763 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2764 s->slice.x, s->slice.y,
2765 s->slice.width, s->slice.height,
2766 x, y);
2768 /* When the image has a mask, we can expect that at
2769 least part of a mouse highlight or a block cursor will
2770 be visible. If the image doesn't have a mask, make
2771 a block cursor visible by drawing a rectangle around
2772 the image. I believe it's looking better if we do
2773 nothing here for mouse-face. */
2774 if (s->hl == DRAW_CURSOR)
2776 int r = s->img->relief;
2777 if (r < 0) r = -r;
2778 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2779 s->slice.width + r*2 - 1,
2780 s->slice.height + r*2 - 1);
2784 else
2785 /* Draw a rectangle if image could not be loaded. */
2786 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2787 s->slice.width - 1, s->slice.height - 1);
2789 #endif
2792 /* Draw part of the background of glyph string S. X, Y, W, and H
2793 give the rectangle to draw. */
2795 static void
2796 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2797 struct glyph_string *s;
2798 int x, y, w, h;
2800 #if 0 /* MAC_TODO: stipple */
2801 if (s->stippled_p)
2803 /* Fill background with a stipple pattern. */
2804 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2805 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2806 XSetFillStyle (s->display, s->gc, FillSolid);
2808 else
2809 #endif /* MAC_TODO */
2810 x_clear_glyph_string_rect (s, x, y, w, h);
2814 /* Draw image glyph string S.
2816 s->y
2817 s->x +-------------------------
2818 | s->face->box
2820 | +-------------------------
2821 | | s->img->margin
2823 | | +-------------------
2824 | | | the image
2828 static void
2829 x_draw_image_glyph_string (s)
2830 struct glyph_string *s;
2832 int x, y;
2833 int box_line_hwidth = abs (s->face->box_line_width);
2834 int box_line_vwidth = max (s->face->box_line_width, 0);
2835 int height;
2836 Pixmap pixmap = 0;
2838 height = s->height - 2 * box_line_vwidth;
2841 /* Fill background with face under the image. Do it only if row is
2842 taller than image or if image has a clip mask to reduce
2843 flickering. */
2844 s->stippled_p = s->face->stipple != 0;
2845 if (height > s->slice.height
2846 || s->img->hmargin
2847 || s->img->vmargin
2848 || s->img->mask
2849 || s->img->pixmap == 0
2850 || s->width != s->background_width)
2852 x = s->x;
2853 if (s->first_glyph->left_box_line_p
2854 && s->slice.x == 0)
2855 x += box_line_hwidth;
2857 y = s->y;
2858 if (s->slice.y == 0)
2859 y += box_line_vwidth;
2861 #if 0 /* TODO: figure out if we need to do this on Mac. */
2862 if (s->img->mask)
2864 /* Create a pixmap as large as the glyph string. Fill it
2865 with the background color. Copy the image to it, using
2866 its mask. Copy the temporary pixmap to the display. */
2867 int depth = one_mac_display_info.n_planes;
2869 /* Create a pixmap as large as the glyph string. */
2870 pixmap = XCreatePixmap (s->display, s->window,
2871 s->background_width,
2872 s->height, depth);
2874 /* Fill the pixmap with the background color/stipple. */
2875 #if 0 /* TODO: stipple */
2876 if (s->stippled_p)
2878 /* Fill background with a stipple pattern. */
2879 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2880 XFillRectangle (s->display, pixmap, s->gc,
2881 0, 0, s->background_width, s->height);
2882 XSetFillStyle (s->display, s->gc, FillSolid);
2884 else
2885 #endif
2887 XGCValues xgcv;
2888 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2889 &xgcv);
2890 XSetForeground (s->display, s->gc, xgcv.background);
2891 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2892 0, 0, s->background_width,
2893 s->height);
2894 XSetForeground (s->display, s->gc, xgcv.foreground);
2897 else
2898 #endif
2899 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2901 s->background_filled_p = 1;
2904 /* Draw the foreground. */
2905 #if 0 /* TODO: figure out if we need to do this on Mac. */
2906 if (pixmap != 0)
2908 x_draw_image_foreground_1 (s, pixmap);
2909 x_set_glyph_string_clipping (s);
2910 mac_copy_area (s->display, pixmap, s->window, s->gc,
2911 0, 0, s->background_width, s->height, s->x, s->y);
2912 mac_reset_clipping (s->display, s->window);
2913 XFreePixmap (s->display, pixmap);
2915 else
2916 #endif
2917 x_draw_image_foreground (s);
2919 /* If we must draw a relief around the image, do it. */
2920 if (s->img->relief
2921 || s->hl == DRAW_IMAGE_RAISED
2922 || s->hl == DRAW_IMAGE_SUNKEN)
2923 x_draw_image_relief (s);
2927 /* Draw stretch glyph string S. */
2929 static void
2930 x_draw_stretch_glyph_string (s)
2931 struct glyph_string *s;
2933 xassert (s->first_glyph->type == STRETCH_GLYPH);
2934 s->stippled_p = s->face->stipple != 0;
2936 if (s->hl == DRAW_CURSOR
2937 && !x_stretch_cursor_p)
2939 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2940 as wide as the stretch glyph. */
2941 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2943 /* Draw cursor. */
2944 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2946 /* Clear rest using the GC of the original non-cursor face. */
2947 if (width < s->background_width)
2949 int x = s->x + width, y = s->y;
2950 int w = s->background_width - width, h = s->height;
2951 Rect r;
2952 GC gc;
2954 if (s->row->mouse_face_p
2955 && cursor_in_mouse_face_p (s->w))
2957 x_set_mouse_face_gc (s);
2958 gc = s->gc;
2960 else
2961 gc = s->face->gc;
2963 get_glyph_string_clip_rect (s, &r);
2964 mac_set_clip_rectangle (s->display, s->window, &r);
2966 #if 0 /* MAC_TODO: stipple */
2967 if (s->face->stipple)
2969 /* Fill background with a stipple pattern. */
2970 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2971 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2972 XSetFillStyle (s->display, gc, FillSolid);
2974 else
2975 #endif /* MAC_TODO */
2977 XGCValues xgcv;
2978 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2979 XSetForeground (s->display, gc, xgcv.background);
2980 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2981 XSetForeground (s->display, gc, xgcv.foreground);
2984 mac_reset_clipping (s->display, s->window);
2987 else if (!s->background_filled_p)
2988 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2989 s->height);
2991 s->background_filled_p = 1;
2995 /* Draw glyph string S. */
2997 static void
2998 x_draw_glyph_string (s)
2999 struct glyph_string *s;
3001 int relief_drawn_p = 0;
3003 /* If S draws into the background of its successor, draw the
3004 background of the successor first so that S can draw into it.
3005 This makes S->next use XDrawString instead of XDrawImageString. */
3006 if (s->next && s->right_overhang && !s->for_overlaps_p)
3008 xassert (s->next->img == NULL);
3009 x_set_glyph_string_gc (s->next);
3010 x_set_glyph_string_clipping (s->next);
3011 x_draw_glyph_string_background (s->next, 1);
3014 /* Set up S->gc, set clipping and draw S. */
3015 x_set_glyph_string_gc (s);
3017 /* Draw relief (if any) in advance for char/composition so that the
3018 glyph string can be drawn over it. */
3019 if (!s->for_overlaps_p
3020 && s->face->box != FACE_NO_BOX
3021 && (s->first_glyph->type == CHAR_GLYPH
3022 || s->first_glyph->type == COMPOSITE_GLYPH))
3025 x_set_glyph_string_clipping (s);
3026 x_draw_glyph_string_background (s, 1);
3027 x_draw_glyph_string_box (s);
3028 x_set_glyph_string_clipping (s);
3029 relief_drawn_p = 1;
3031 else
3032 x_set_glyph_string_clipping (s);
3034 switch (s->first_glyph->type)
3036 case IMAGE_GLYPH:
3037 x_draw_image_glyph_string (s);
3038 break;
3040 case STRETCH_GLYPH:
3041 x_draw_stretch_glyph_string (s);
3042 break;
3044 case CHAR_GLYPH:
3045 if (s->for_overlaps_p)
3046 s->background_filled_p = 1;
3047 else
3048 x_draw_glyph_string_background (s, 0);
3049 x_draw_glyph_string_foreground (s);
3050 break;
3052 case COMPOSITE_GLYPH:
3053 if (s->for_overlaps_p || s->gidx > 0)
3054 s->background_filled_p = 1;
3055 else
3056 x_draw_glyph_string_background (s, 1);
3057 x_draw_composite_glyph_string_foreground (s);
3058 break;
3060 default:
3061 abort ();
3064 if (!s->for_overlaps_p)
3066 /* Draw underline. */
3067 if (s->face->underline_p)
3069 unsigned long h = 1;
3070 unsigned long dy = s->height - h;
3072 if (s->face->underline_defaulted_p)
3073 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3074 s->width, h);
3075 else
3077 XGCValues xgcv;
3078 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3079 XSetForeground (s->display, s->gc, s->face->underline_color);
3080 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3081 s->width, h);
3082 XSetForeground (s->display, s->gc, xgcv.foreground);
3086 /* Draw overline. */
3087 if (s->face->overline_p)
3089 unsigned long dy = 0, h = 1;
3091 if (s->face->overline_color_defaulted_p)
3092 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3093 s->width, h);
3094 else
3096 XGCValues xgcv;
3097 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3098 XSetForeground (s->display, s->gc, s->face->overline_color);
3099 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3100 s->width, h);
3101 XSetForeground (s->display, s->gc, xgcv.foreground);
3105 /* Draw strike-through. */
3106 if (s->face->strike_through_p)
3108 unsigned long h = 1;
3109 unsigned long dy = (s->height - h) / 2;
3111 if (s->face->strike_through_color_defaulted_p)
3112 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3113 s->width, h);
3114 else
3116 XGCValues xgcv;
3117 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3118 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3119 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3120 s->width, h);
3121 XSetForeground (s->display, s->gc, xgcv.foreground);
3125 /* Draw relief if not yet drawn. */
3126 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3127 x_draw_glyph_string_box (s);
3130 /* Reset clipping. */
3131 mac_reset_clipping (s->display, s->window);
3134 /* Shift display to make room for inserted glyphs. */
3136 void
3137 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3138 struct frame *f;
3139 int x, y, width, height, shift_by;
3141 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3142 f->output_data.mac->normal_gc,
3143 x, y, width, height,
3144 x + shift_by, y);
3147 /* Delete N glyphs at the nominal cursor position. Not implemented
3148 for X frames. */
3150 static void
3151 x_delete_glyphs (n)
3152 register int n;
3154 abort ();
3158 /* Clear entire frame. If updating_frame is non-null, clear that
3159 frame. Otherwise clear the selected frame. */
3161 static void
3162 x_clear_frame ()
3164 struct frame *f;
3166 if (updating_frame)
3167 f = updating_frame;
3168 else
3169 f = SELECTED_FRAME ();
3171 /* Clearing the frame will erase any cursor, so mark them all as no
3172 longer visible. */
3173 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3174 output_cursor.hpos = output_cursor.vpos = 0;
3175 output_cursor.x = -1;
3177 /* We don't set the output cursor here because there will always
3178 follow an explicit cursor_to. */
3179 BLOCK_INPUT;
3180 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3182 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3183 /* We have to clear the scroll bars, too. If we have changed
3184 colors or something like that, then they should be notified. */
3185 x_scroll_bar_clear (f);
3186 #endif
3188 XFlush (FRAME_MAC_DISPLAY (f));
3189 UNBLOCK_INPUT;
3194 /* Invert the middle quarter of the frame for .15 sec. */
3196 /* We use the select system call to do the waiting, so we have to make
3197 sure it's available. If it isn't, we just won't do visual bells. */
3199 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3202 /* Subtract the `struct timeval' values X and Y, storing the result in
3203 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3205 static int
3206 timeval_subtract (result, x, y)
3207 struct timeval *result, x, y;
3209 /* Perform the carry for the later subtraction by updating y. This
3210 is safer because on some systems the tv_sec member is unsigned. */
3211 if (x.tv_usec < y.tv_usec)
3213 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3214 y.tv_usec -= 1000000 * nsec;
3215 y.tv_sec += nsec;
3218 if (x.tv_usec - y.tv_usec > 1000000)
3220 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3221 y.tv_usec += 1000000 * nsec;
3222 y.tv_sec -= nsec;
3225 /* Compute the time remaining to wait. tv_usec is certainly
3226 positive. */
3227 result->tv_sec = x.tv_sec - y.tv_sec;
3228 result->tv_usec = x.tv_usec - y.tv_usec;
3230 /* Return indication of whether the result should be considered
3231 negative. */
3232 return x.tv_sec < y.tv_sec;
3235 void
3236 XTflash (f)
3237 struct frame *f;
3239 BLOCK_INPUT;
3241 FlashMenuBar (0);
3244 struct timeval wakeup;
3246 EMACS_GET_TIME (wakeup);
3248 /* Compute time to wait until, propagating carry from usecs. */
3249 wakeup.tv_usec += 150000;
3250 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3251 wakeup.tv_usec %= 1000000;
3253 /* Keep waiting until past the time wakeup. */
3254 while (1)
3256 struct timeval timeout;
3258 EMACS_GET_TIME (timeout);
3260 /* In effect, timeout = wakeup - timeout.
3261 Break if result would be negative. */
3262 if (timeval_subtract (&timeout, wakeup, timeout))
3263 break;
3265 /* Try to wait that long--but we might wake up sooner. */
3266 select (0, NULL, NULL, NULL, &timeout);
3270 FlashMenuBar (0);
3272 UNBLOCK_INPUT;
3275 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3278 /* Make audible bell. */
3280 void
3281 XTring_bell ()
3283 struct frame *f = SELECTED_FRAME ();
3285 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3286 if (visible_bell)
3287 XTflash (f);
3288 else
3289 #endif
3291 BLOCK_INPUT;
3292 SysBeep (1);
3293 XFlush (FRAME_MAC_DISPLAY (f));
3294 UNBLOCK_INPUT;
3300 /* Specify how many text lines, from the top of the window,
3301 should be affected by insert-lines and delete-lines operations.
3302 This, and those operations, are used only within an update
3303 that is bounded by calls to x_update_begin and x_update_end. */
3305 static void
3306 XTset_terminal_window (n)
3307 register int n;
3309 /* This function intentionally left blank. */
3314 /***********************************************************************
3315 Line Dance
3316 ***********************************************************************/
3318 /* Perform an insert-lines or delete-lines operation, inserting N
3319 lines or deleting -N lines at vertical position VPOS. */
3321 static void
3322 x_ins_del_lines (vpos, n)
3323 int vpos, n;
3325 abort ();
3329 /* Scroll part of the display as described by RUN. */
3331 static void
3332 x_scroll_run (w, run)
3333 struct window *w;
3334 struct run *run;
3336 struct frame *f = XFRAME (w->frame);
3337 int x, y, width, height, from_y, to_y, bottom_y;
3339 /* Get frame-relative bounding box of the text display area of W,
3340 without mode lines. Include in this box the left and right
3341 fringe of W. */
3342 window_box (w, -1, &x, &y, &width, &height);
3344 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3345 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3346 bottom_y = y + height;
3348 if (to_y < from_y)
3350 /* Scrolling up. Make sure we don't copy part of the mode
3351 line at the bottom. */
3352 if (from_y + run->height > bottom_y)
3353 height = bottom_y - from_y;
3354 else
3355 height = run->height;
3357 else
3359 /* Scolling down. Make sure we don't copy over the mode line.
3360 at the bottom. */
3361 if (to_y + run->height > bottom_y)
3362 height = bottom_y - to_y;
3363 else
3364 height = run->height;
3367 BLOCK_INPUT;
3369 /* Cursor off. Will be switched on again in x_update_window_end. */
3370 updated_window = w;
3371 x_clear_cursor (w);
3373 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3374 f->output_data.mac->normal_gc,
3375 x, from_y,
3376 width, height,
3377 x, to_y);
3379 UNBLOCK_INPUT;
3384 /***********************************************************************
3385 Exposure Events
3386 ***********************************************************************/
3389 static void
3390 frame_highlight (f)
3391 struct frame *f;
3393 x_update_cursor (f, 1);
3396 static void
3397 frame_unhighlight (f)
3398 struct frame *f;
3400 x_update_cursor (f, 1);
3403 /* The focus has changed. Update the frames as necessary to reflect
3404 the new situation. Note that we can't change the selected frame
3405 here, because the Lisp code we are interrupting might become confused.
3406 Each event gets marked with the frame in which it occurred, so the
3407 Lisp code can tell when the switch took place by examining the events. */
3409 static void
3410 x_new_focus_frame (dpyinfo, frame)
3411 struct x_display_info *dpyinfo;
3412 struct frame *frame;
3414 struct frame *old_focus = dpyinfo->x_focus_frame;
3416 if (frame != dpyinfo->x_focus_frame)
3418 /* Set this before calling other routines, so that they see
3419 the correct value of x_focus_frame. */
3420 dpyinfo->x_focus_frame = frame;
3422 if (old_focus && old_focus->auto_lower)
3423 x_lower_frame (old_focus);
3425 #if 0
3426 selected_frame = frame;
3427 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3428 selected_frame);
3429 Fselect_window (selected_frame->selected_window, Qnil);
3430 choose_minibuf_frame ();
3431 #endif /* ! 0 */
3433 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3434 pending_autoraise_frame = dpyinfo->x_focus_frame;
3435 else
3436 pending_autoraise_frame = 0;
3439 x_frame_rehighlight (dpyinfo);
3442 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3444 void
3445 x_mouse_leave (dpyinfo)
3446 struct x_display_info *dpyinfo;
3448 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3451 /* The focus has changed, or we have redirected a frame's focus to
3452 another frame (this happens when a frame uses a surrogate
3453 mini-buffer frame). Shift the highlight as appropriate.
3455 The FRAME argument doesn't necessarily have anything to do with which
3456 frame is being highlighted or un-highlighted; we only use it to find
3457 the appropriate X display info. */
3459 static void
3460 XTframe_rehighlight (frame)
3461 struct frame *frame;
3463 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3466 static void
3467 x_frame_rehighlight (dpyinfo)
3468 struct x_display_info *dpyinfo;
3470 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3472 if (dpyinfo->x_focus_frame)
3474 dpyinfo->x_highlight_frame
3475 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3476 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3477 : dpyinfo->x_focus_frame);
3478 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3480 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3481 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3484 else
3485 dpyinfo->x_highlight_frame = 0;
3487 if (dpyinfo->x_highlight_frame != old_highlight)
3489 if (old_highlight)
3490 frame_unhighlight (old_highlight);
3491 if (dpyinfo->x_highlight_frame)
3492 frame_highlight (dpyinfo->x_highlight_frame);
3498 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3500 #if 0 /* MAC_TODO */
3501 /* Initialize mode_switch_bit and modifier_meaning. */
3502 static void
3503 x_find_modifier_meanings (dpyinfo)
3504 struct x_display_info *dpyinfo;
3506 int min_code, max_code;
3507 KeySym *syms;
3508 int syms_per_code;
3509 XModifierKeymap *mods;
3511 dpyinfo->meta_mod_mask = 0;
3512 dpyinfo->shift_lock_mask = 0;
3513 dpyinfo->alt_mod_mask = 0;
3514 dpyinfo->super_mod_mask = 0;
3515 dpyinfo->hyper_mod_mask = 0;
3517 #ifdef HAVE_X11R4
3518 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3519 #else
3520 min_code = dpyinfo->display->min_keycode;
3521 max_code = dpyinfo->display->max_keycode;
3522 #endif
3524 syms = XGetKeyboardMapping (dpyinfo->display,
3525 min_code, max_code - min_code + 1,
3526 &syms_per_code);
3527 mods = XGetModifierMapping (dpyinfo->display);
3529 /* Scan the modifier table to see which modifier bits the Meta and
3530 Alt keysyms are on. */
3532 int row, col; /* The row and column in the modifier table. */
3534 for (row = 3; row < 8; row++)
3535 for (col = 0; col < mods->max_keypermod; col++)
3537 KeyCode code
3538 = mods->modifiermap[(row * mods->max_keypermod) + col];
3540 /* Zeroes are used for filler. Skip them. */
3541 if (code == 0)
3542 continue;
3544 /* Are any of this keycode's keysyms a meta key? */
3546 int code_col;
3548 for (code_col = 0; code_col < syms_per_code; code_col++)
3550 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3552 switch (sym)
3554 case XK_Meta_L:
3555 case XK_Meta_R:
3556 dpyinfo->meta_mod_mask |= (1 << row);
3557 break;
3559 case XK_Alt_L:
3560 case XK_Alt_R:
3561 dpyinfo->alt_mod_mask |= (1 << row);
3562 break;
3564 case XK_Hyper_L:
3565 case XK_Hyper_R:
3566 dpyinfo->hyper_mod_mask |= (1 << row);
3567 break;
3569 case XK_Super_L:
3570 case XK_Super_R:
3571 dpyinfo->super_mod_mask |= (1 << row);
3572 break;
3574 case XK_Shift_Lock:
3575 /* Ignore this if it's not on the lock modifier. */
3576 if ((1 << row) == LockMask)
3577 dpyinfo->shift_lock_mask = LockMask;
3578 break;
3585 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3586 if (! dpyinfo->meta_mod_mask)
3588 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3589 dpyinfo->alt_mod_mask = 0;
3592 /* If some keys are both alt and meta,
3593 make them just meta, not alt. */
3594 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3596 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3599 XFree ((char *) syms);
3600 XFreeModifiermap (mods);
3603 #endif /* MAC_TODO */
3605 /* Convert between the modifier bits X uses and the modifier bits
3606 Emacs uses. */
3608 static unsigned int
3609 x_mac_to_emacs_modifiers (dpyinfo, state)
3610 struct x_display_info *dpyinfo;
3611 unsigned short state;
3613 return (((state & shiftKey) ? shift_modifier : 0)
3614 | ((state & controlKey) ? ctrl_modifier : 0)
3615 | ((state & cmdKey) ? meta_modifier : 0)
3616 | ((state & optionKey) ? alt_modifier : 0));
3619 #if 0 /* MAC_TODO */
3620 static unsigned short
3621 x_emacs_to_x_modifiers (dpyinfo, state)
3622 struct x_display_info *dpyinfo;
3623 unsigned int state;
3625 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3626 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3627 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3628 | ((state & shift_modifier) ? ShiftMask : 0)
3629 | ((state & ctrl_modifier) ? ControlMask : 0)
3630 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3632 #endif /* MAC_TODO */
3634 /* Convert a keysym to its name. */
3636 char *
3637 x_get_keysym_name (keysym)
3638 int keysym;
3640 char *value;
3642 BLOCK_INPUT;
3643 #if 0
3644 value = XKeysymToString (keysym);
3645 #else
3646 value = 0;
3647 #endif
3648 UNBLOCK_INPUT;
3650 return value;
3655 /* Mouse clicks and mouse movement. Rah. */
3657 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3659 If the event is a button press, then note that we have grabbed
3660 the mouse. */
3662 static Lisp_Object
3663 construct_mouse_click (result, event, f)
3664 struct input_event *result;
3665 EventRecord *event;
3666 struct frame *f;
3668 Point mouseLoc;
3670 result->kind = MOUSE_CLICK_EVENT;
3671 result->code = 0; /* only one mouse button */
3672 result->timestamp = event->when;
3673 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3675 mouseLoc = event->where;
3677 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3679 GlobalToLocal (&mouseLoc);
3680 XSETINT (result->x, mouseLoc.h);
3681 XSETINT (result->y, mouseLoc.v);
3683 XSETFRAME (result->frame_or_window, f);
3685 result->arg = Qnil;
3686 return Qnil;
3690 /* Function to report a mouse movement to the mainstream Emacs code.
3691 The input handler calls this.
3693 We have received a mouse movement event, which is given in *event.
3694 If the mouse is over a different glyph than it was last time, tell
3695 the mainstream emacs code by setting mouse_moved. If not, ask for
3696 another motion event, so we can check again the next time it moves. */
3698 static Point last_mouse_motion_position;
3699 static Lisp_Object last_mouse_motion_frame;
3701 static void
3702 note_mouse_movement (frame, pos)
3703 FRAME_PTR frame;
3704 Point *pos;
3706 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3707 #if TARGET_API_MAC_CARBON
3708 Rect r;
3709 #endif
3711 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3712 last_mouse_motion_position = *pos;
3713 XSETFRAME (last_mouse_motion_frame, frame);
3715 #if TARGET_API_MAC_CARBON
3716 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3717 #else
3718 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3719 #endif
3721 if (frame == dpyinfo->mouse_face_mouse_frame)
3722 /* This case corresponds to LeaveNotify in X11. */
3724 /* If we move outside the frame, then we're certainly no
3725 longer on any text in the frame. */
3726 clear_mouse_face (dpyinfo);
3727 dpyinfo->mouse_face_mouse_frame = 0;
3728 if (!dpyinfo->grabbed)
3729 rif->define_frame_cursor (frame,
3730 frame->output_data.mac->nontext_cursor);
3733 /* Has the mouse moved off the glyph it was on at the last sighting? */
3734 else if (pos->h < last_mouse_glyph.left
3735 || pos->h >= last_mouse_glyph.right
3736 || pos->v < last_mouse_glyph.top
3737 || pos->v >= last_mouse_glyph.bottom)
3739 frame->mouse_moved = 1;
3740 last_mouse_scroll_bar = Qnil;
3741 note_mouse_highlight (frame, pos->h, pos->v);
3745 /* This is used for debugging, to turn off note_mouse_highlight. */
3747 int disable_mouse_highlight;
3751 /************************************************************************
3752 Mouse Face
3753 ************************************************************************/
3755 static struct scroll_bar *x_window_to_scroll_bar ();
3756 static void x_scroll_bar_report_motion ();
3757 static void x_check_fullscreen P_ ((struct frame *));
3758 static void x_check_fullscreen_move P_ ((struct frame *));
3759 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3762 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3764 static void
3765 redo_mouse_highlight ()
3767 if (!NILP (last_mouse_motion_frame)
3768 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3769 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3770 last_mouse_motion_position.h,
3771 last_mouse_motion_position.v);
3775 /* Try to determine frame pixel position and size of the glyph under
3776 frame pixel coordinates X/Y on frame F . Return the position and
3777 size in *RECT. Value is non-zero if we could compute these
3778 values. */
3780 static int
3781 glyph_rect (f, x, y, rect)
3782 struct frame *f;
3783 int x, y;
3784 Rect *rect;
3786 Lisp_Object window;
3788 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3790 if (!NILP (window))
3792 struct window *w = XWINDOW (window);
3793 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3794 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3796 for (; r < end && r->enabled_p; ++r)
3797 if (r->y <= y && r->y + r->height > y)
3799 /* Found the row at y. */
3800 struct glyph *g = r->glyphs[TEXT_AREA];
3801 struct glyph *end = g + r->used[TEXT_AREA];
3802 int gx;
3804 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3805 rect->bottom = rect->top + r->height;
3807 if (x < r->x)
3809 /* x is to the left of the first glyph in the row. */
3810 /* Shouldn't this be a pixel value?
3811 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3812 ++KFS */
3813 rect->left = WINDOW_LEFT_EDGE_COL (w);
3814 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3815 return 1;
3818 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3819 if (gx <= x && gx + g->pixel_width > x)
3821 /* x is on a glyph. */
3822 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3823 rect->right = rect->left + g->pixel_width;
3824 return 1;
3827 /* x is to the right of the last glyph in the row. */
3828 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3829 /* Shouldn't this be a pixel value?
3830 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3831 ++KFS */
3832 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3833 return 1;
3837 /* The y is not on any row. */
3838 return 0;
3841 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3843 /* Record the position of the mouse in last_mouse_glyph. */
3844 static void
3845 remember_mouse_glyph (f1, gx, gy)
3846 struct frame * f1;
3847 int gx, gy;
3849 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3851 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3852 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3854 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3855 round down even for negative values. */
3856 if (gx < 0)
3857 gx -= width - 1;
3858 if (gy < 0)
3859 gy -= height - 1;
3860 #if 0
3861 /* This was the original code from XTmouse_position, but it seems
3862 to give the position of the glyph diagonally next to the one
3863 the mouse is over. */
3864 gx = (gx + width - 1) / width * width;
3865 gy = (gy + height - 1) / height * height;
3866 #else
3867 gx = gx / width * width;
3868 gy = gy / height * height;
3869 #endif
3871 last_mouse_glyph.left = gx;
3872 last_mouse_glyph.top = gy;
3873 last_mouse_glyph.right = gx + width;
3874 last_mouse_glyph.bottom = gy + height;
3879 static WindowPtr
3880 front_emacs_window ()
3882 #if TARGET_API_MAC_CARBON
3883 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3885 while (wp && !is_emacs_window (wp))
3886 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3887 #else
3888 WindowPtr wp = FrontWindow ();
3890 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3891 wp = GetNextWindow (wp);
3892 #endif
3894 return wp;
3897 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3899 /* Return the current position of the mouse.
3900 *fp should be a frame which indicates which display to ask about.
3902 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3903 and *part to the frame, window, and scroll bar part that the mouse
3904 is over. Set *x and *y to the portion and whole of the mouse's
3905 position on the scroll bar.
3907 If the mouse movement started elsewhere, set *fp to the frame the
3908 mouse is on, *bar_window to nil, and *x and *y to the character cell
3909 the mouse is over.
3911 Set *time to the server time-stamp for the time at which the mouse
3912 was at this position.
3914 Don't store anything if we don't have a valid set of values to report.
3916 This clears the mouse_moved flag, so we can wait for the next mouse
3917 movement. */
3919 static void
3920 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3921 FRAME_PTR *fp;
3922 int insist;
3923 Lisp_Object *bar_window;
3924 enum scroll_bar_part *part;
3925 Lisp_Object *x, *y;
3926 unsigned long *time;
3928 Point mouse_pos;
3929 int ignore1, ignore2;
3930 WindowPtr wp = front_emacs_window ();
3931 struct frame *f;
3932 Lisp_Object frame, tail;
3934 if (is_emacs_window(wp))
3935 f = mac_window_to_frame (wp);
3937 BLOCK_INPUT;
3939 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3940 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3941 else
3943 /* Clear the mouse-moved flag for every frame on this display. */
3944 FOR_EACH_FRAME (tail, frame)
3945 XFRAME (frame)->mouse_moved = 0;
3947 last_mouse_scroll_bar = Qnil;
3949 SetPortWindowPort (wp);
3951 GetMouse (&mouse_pos);
3953 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3954 &last_mouse_glyph, insist);
3956 *bar_window = Qnil;
3957 *part = scroll_bar_handle;
3958 *fp = f;
3959 XSETINT (*x, mouse_pos.h);
3960 XSETINT (*y, mouse_pos.v);
3961 *time = last_mouse_movement_time;
3964 UNBLOCK_INPUT;
3968 /***********************************************************************
3969 Tool-bars
3970 ***********************************************************************/
3972 /* Handle mouse button event on the tool-bar of frame F, at
3973 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3974 or ButtonRelase. */
3976 static void
3977 mac_handle_tool_bar_click (f, button_event)
3978 struct frame *f;
3979 EventRecord *button_event;
3981 int x = button_event->where.h;
3982 int y = button_event->where.v;
3984 if (button_event->what == mouseDown)
3985 handle_tool_bar_click (f, x, y, 1, 0);
3986 else
3987 handle_tool_bar_click (f, x, y, 0,
3988 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
3989 button_event->modifiers));
3993 /************************************************************************
3994 Scroll bars, general
3995 ************************************************************************/
3997 /* Create a scroll bar and return the scroll bar vector for it. W is
3998 the Emacs window on which to create the scroll bar. TOP, LEFT,
3999 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4000 scroll bar. */
4002 static struct scroll_bar *
4003 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4004 struct window *w;
4005 int top, left, width, height, disp_top, disp_height;
4007 struct frame *f = XFRAME (w->frame);
4008 struct scroll_bar *bar
4009 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4010 Rect r;
4011 ControlHandle ch;
4013 BLOCK_INPUT;
4015 r.left = left;
4016 r.top = disp_top;
4017 r.right = left + width;
4018 r.bottom = disp_top + disp_height;
4020 #ifdef TARGET_API_MAC_CARBON
4021 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4022 kControlScrollBarProc, 0L);
4023 #else
4024 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4025 0L);
4026 #endif
4027 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4028 SetControlReference (ch, (long) bar);
4030 XSETWINDOW (bar->window, w);
4031 XSETINT (bar->top, top);
4032 XSETINT (bar->left, left);
4033 XSETINT (bar->width, width);
4034 XSETINT (bar->height, height);
4035 XSETINT (bar->start, 0);
4036 XSETINT (bar->end, 0);
4037 bar->dragging = Qnil;
4039 /* Add bar to its frame's list of scroll bars. */
4040 bar->next = FRAME_SCROLL_BARS (f);
4041 bar->prev = Qnil;
4042 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4043 if (!NILP (bar->next))
4044 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4046 UNBLOCK_INPUT;
4047 return bar;
4051 /* Draw BAR's handle in the proper position.
4053 If the handle is already drawn from START to END, don't bother
4054 redrawing it, unless REBUILD is non-zero; in that case, always
4055 redraw it. (REBUILD is handy for drawing the handle after expose
4056 events.)
4058 Normally, we want to constrain the start and end of the handle to
4059 fit inside its rectangle, but if the user is dragging the scroll
4060 bar handle, we want to let them drag it down all the way, so that
4061 the bar's top is as far down as it goes; otherwise, there's no way
4062 to move to the very end of the buffer. */
4064 static void
4065 x_scroll_bar_set_handle (bar, start, end, rebuild)
4066 struct scroll_bar *bar;
4067 int start, end;
4068 int rebuild;
4070 int dragging = ! NILP (bar->dragging);
4071 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4072 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4073 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4074 int length = end - start;
4076 /* If the display is already accurate, do nothing. */
4077 if (! rebuild
4078 && start == XINT (bar->start)
4079 && end == XINT (bar->end))
4080 return;
4082 BLOCK_INPUT;
4084 /* Make sure the values are reasonable, and try to preserve the
4085 distance between start and end. */
4086 if (start < 0)
4087 start = 0;
4088 else if (start > top_range)
4089 start = top_range;
4090 end = start + length;
4092 if (end < start)
4093 end = start;
4094 else if (end > top_range && ! dragging)
4095 end = top_range;
4097 /* Store the adjusted setting in the scroll bar. */
4098 XSETINT (bar->start, start);
4099 XSETINT (bar->end, end);
4101 /* Clip the end position, just for display. */
4102 if (end > top_range)
4103 end = top_range;
4105 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4106 top positions, to make sure the handle is always at least that
4107 many pixels tall. */
4108 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4110 SetControlMinimum (ch, 0);
4111 /* Don't inadvertently activate deactivated scroll bars */
4112 if (GetControlMaximum (ch) != -1)
4113 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4114 - (end - start));
4115 SetControlValue (ch, start);
4116 #if TARGET_API_MAC_CARBON
4117 SetControlViewSize (ch, end - start);
4118 #endif
4120 UNBLOCK_INPUT;
4124 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4125 nil. */
4127 static void
4128 x_scroll_bar_remove (bar)
4129 struct scroll_bar *bar;
4131 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4133 BLOCK_INPUT;
4135 /* Destroy the Mac scroll bar control */
4136 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4138 /* Disassociate this scroll bar from its window. */
4139 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4141 UNBLOCK_INPUT;
4144 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4145 that we are displaying PORTION characters out of a total of WHOLE
4146 characters, starting at POSITION. If WINDOW has no scroll bar,
4147 create one. */
4148 static void
4149 XTset_vertical_scroll_bar (w, portion, whole, position)
4150 struct window *w;
4151 int portion, whole, position;
4153 struct frame *f = XFRAME (w->frame);
4154 struct scroll_bar *bar;
4155 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4156 int window_y, window_height;
4158 /* Get window dimensions. */
4159 window_box (w, -1, 0, &window_y, 0, &window_height);
4160 top = window_y;
4161 #ifdef MAC_OSX
4162 width = 16;
4163 #else
4164 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4165 #endif
4166 height = window_height;
4168 /* Compute the left edge of the scroll bar area. */
4169 left = WINDOW_SCROLL_BAR_AREA_X (w);
4171 /* Compute the width of the scroll bar which might be less than
4172 the width of the area reserved for the scroll bar. */
4173 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4174 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4175 else
4176 sb_width = width;
4178 /* Compute the left edge of the scroll bar. */
4179 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4180 sb_left = left + width - sb_width - (width - sb_width) / 2;
4181 else
4182 sb_left = left + (width - sb_width) / 2;
4184 /* Adjustments according to Inside Macintosh to make it look nice */
4185 disp_top = top;
4186 disp_height = height;
4187 if (disp_top == 0)
4189 disp_top = -1;
4190 disp_height++;
4192 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4194 disp_top++;
4195 disp_height--;
4198 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4199 sb_left++;
4201 /* Does the scroll bar exist yet? */
4202 if (NILP (w->vertical_scroll_bar))
4204 BLOCK_INPUT;
4205 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4206 left, top, width, height, 0);
4207 UNBLOCK_INPUT;
4208 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4209 disp_height);
4210 XSETVECTOR (w->vertical_scroll_bar, bar);
4212 else
4214 /* It may just need to be moved and resized. */
4215 ControlHandle ch;
4217 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4218 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4220 BLOCK_INPUT;
4222 /* If already correctly positioned, do nothing. */
4223 if (XINT (bar->left) == sb_left
4224 && XINT (bar->top) == top
4225 && XINT (bar->width) == sb_width
4226 && XINT (bar->height) == height)
4227 Draw1Control (ch);
4228 else
4230 /* Clear areas not covered by the scroll bar because it's not as
4231 wide as the area reserved for it . This makes sure a
4232 previous mode line display is cleared after C-x 2 C-x 1, for
4233 example. */
4234 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4235 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4236 left, top, area_width, height, 0);
4238 #if 0
4239 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4240 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4241 sb_left - 1, top, 1, height, 0);
4242 #endif
4244 HideControl (ch);
4245 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4246 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4247 disp_height);
4248 ShowControl (ch);
4250 /* Remember new settings. */
4251 XSETINT (bar->left, sb_left);
4252 XSETINT (bar->top, top);
4253 XSETINT (bar->width, sb_width);
4254 XSETINT (bar->height, height);
4257 UNBLOCK_INPUT;
4260 /* Set the scroll bar's current state, unless we're currently being
4261 dragged. */
4262 if (NILP (bar->dragging))
4264 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4266 if (whole == 0)
4267 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4268 else
4270 int start = ((double) position * top_range) / whole;
4271 int end = ((double) (position + portion) * top_range) / whole;
4272 x_scroll_bar_set_handle (bar, start, end, 0);
4278 /* The following three hooks are used when we're doing a thorough
4279 redisplay of the frame. We don't explicitly know which scroll bars
4280 are going to be deleted, because keeping track of when windows go
4281 away is a real pain - "Can you say set-window-configuration, boys
4282 and girls?" Instead, we just assert at the beginning of redisplay
4283 that *all* scroll bars are to be removed, and then save a scroll bar
4284 from the fiery pit when we actually redisplay its window. */
4286 /* Arrange for all scroll bars on FRAME to be removed at the next call
4287 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4288 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4290 static void
4291 XTcondemn_scroll_bars (frame)
4292 FRAME_PTR frame;
4294 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4295 while (! NILP (FRAME_SCROLL_BARS (frame)))
4297 Lisp_Object bar;
4298 bar = FRAME_SCROLL_BARS (frame);
4299 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4300 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4301 XSCROLL_BAR (bar)->prev = Qnil;
4302 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4303 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4304 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4309 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4310 Note that WINDOW isn't necessarily condemned at all. */
4312 static void
4313 XTredeem_scroll_bar (window)
4314 struct window *window;
4316 struct scroll_bar *bar;
4318 /* We can't redeem this window's scroll bar if it doesn't have one. */
4319 if (NILP (window->vertical_scroll_bar))
4320 abort ();
4322 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4324 /* Unlink it from the condemned list. */
4326 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4328 if (NILP (bar->prev))
4330 /* If the prev pointer is nil, it must be the first in one of
4331 the lists. */
4332 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4333 /* It's not condemned. Everything's fine. */
4334 return;
4335 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4336 window->vertical_scroll_bar))
4337 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4338 else
4339 /* If its prev pointer is nil, it must be at the front of
4340 one or the other! */
4341 abort ();
4343 else
4344 XSCROLL_BAR (bar->prev)->next = bar->next;
4346 if (! NILP (bar->next))
4347 XSCROLL_BAR (bar->next)->prev = bar->prev;
4349 bar->next = FRAME_SCROLL_BARS (f);
4350 bar->prev = Qnil;
4351 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4352 if (! NILP (bar->next))
4353 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4357 /* Remove all scroll bars on FRAME that haven't been saved since the
4358 last call to `*condemn_scroll_bars_hook'. */
4360 static void
4361 XTjudge_scroll_bars (f)
4362 FRAME_PTR f;
4364 Lisp_Object bar, next;
4366 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4368 /* Clear out the condemned list now so we won't try to process any
4369 more events on the hapless scroll bars. */
4370 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4372 for (; ! NILP (bar); bar = next)
4374 struct scroll_bar *b = XSCROLL_BAR (bar);
4376 x_scroll_bar_remove (b);
4378 next = b->next;
4379 b->next = b->prev = Qnil;
4382 /* Now there should be no references to the condemned scroll bars,
4383 and they should get garbage-collected. */
4387 void
4388 activate_scroll_bars (frame)
4389 FRAME_PTR frame;
4391 Lisp_Object bar;
4392 ControlHandle ch;
4394 bar = FRAME_SCROLL_BARS (frame);
4395 while (! NILP (bar))
4397 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4398 #ifdef TARGET_API_MAC_CARBON
4399 ActivateControl (ch);
4400 #else
4401 SetControlMaximum (ch,
4402 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4403 XINT (XSCROLL_BAR (bar)
4404 ->height)) - 1);
4405 #endif
4406 bar = XSCROLL_BAR (bar)->next;
4411 void
4412 deactivate_scroll_bars (frame)
4413 FRAME_PTR frame;
4415 Lisp_Object bar;
4416 ControlHandle ch;
4418 bar = FRAME_SCROLL_BARS (frame);
4419 while (! NILP (bar))
4421 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4422 #ifdef TARGET_API_MAC_CARBON
4423 DeactivateControl (ch);
4424 #else
4425 SetControlMaximum (ch, XINT (-1));
4426 #endif
4427 bar = XSCROLL_BAR (bar)->next;
4431 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4432 is set to something other than NO_EVENT, it is enqueued.
4434 This may be called from a signal handler, so we have to ignore GC
4435 mark bits. */
4437 static void
4438 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4439 struct scroll_bar *bar;
4440 int part_code;
4441 EventRecord *er;
4442 struct input_event *bufp;
4444 int win_y, top_range;
4446 if (! GC_WINDOWP (bar->window))
4447 abort ();
4449 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4450 bufp->frame_or_window = bar->window;
4451 bufp->arg = Qnil;
4453 bar->dragging = Qnil;
4455 switch (part_code)
4457 case kControlUpButtonPart:
4458 bufp->part = scroll_bar_up_arrow;
4459 break;
4460 case kControlDownButtonPart:
4461 bufp->part = scroll_bar_down_arrow;
4462 break;
4463 case kControlPageUpPart:
4464 bufp->part = scroll_bar_above_handle;
4465 break;
4466 case kControlPageDownPart:
4467 bufp->part = scroll_bar_below_handle;
4468 break;
4469 #ifdef TARGET_API_MAC_CARBON
4470 default:
4471 #else
4472 case kControlIndicatorPart:
4473 #endif
4474 if (er->what == mouseDown)
4475 bar->dragging = make_number (0);
4476 XSETVECTOR (last_mouse_scroll_bar, bar);
4477 bufp->part = scroll_bar_handle;
4478 break;
4481 win_y = XINT (bufp->y) - XINT (bar->top);
4482 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4484 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4486 win_y -= 24;
4488 if (! NILP (bar->dragging))
4489 win_y -= XINT (bar->dragging);
4491 if (win_y < 0)
4492 win_y = 0;
4493 if (win_y > top_range)
4494 win_y = top_range;
4496 XSETINT (bufp->x, win_y);
4497 XSETINT (bufp->y, top_range);
4501 /* Handle some mouse motion while someone is dragging the scroll bar.
4503 This may be called from a signal handler, so we have to ignore GC
4504 mark bits. */
4506 static void
4507 x_scroll_bar_note_movement (bar, y_pos, t)
4508 struct scroll_bar *bar;
4509 int y_pos;
4510 Time t;
4512 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4514 last_mouse_movement_time = t;
4516 f->mouse_moved = 1;
4517 XSETVECTOR (last_mouse_scroll_bar, bar);
4519 /* If we're dragging the bar, display it. */
4520 if (! GC_NILP (bar->dragging))
4522 /* Where should the handle be now? */
4523 int new_start = y_pos - 24;
4525 if (new_start != XINT (bar->start))
4527 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4529 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4535 /* Return information to the user about the current position of the
4536 mouse on the scroll bar. */
4538 static void
4539 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4540 FRAME_PTR *fp;
4541 Lisp_Object *bar_window;
4542 enum scroll_bar_part *part;
4543 Lisp_Object *x, *y;
4544 unsigned long *time;
4546 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4547 WindowPtr wp = front_emacs_window ();
4548 Point mouse_pos;
4549 struct frame *f = mac_window_to_frame (wp);
4550 int win_y, top_range;
4552 SetPortWindowPort (wp);
4554 GetMouse (&mouse_pos);
4556 win_y = mouse_pos.v - XINT (bar->top);
4557 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4559 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4561 win_y -= 24;
4563 if (! NILP (bar->dragging))
4564 win_y -= XINT (bar->dragging);
4566 if (win_y < 0)
4567 win_y = 0;
4568 if (win_y > top_range)
4569 win_y = top_range;
4571 *fp = f;
4572 *bar_window = bar->window;
4574 if (! NILP (bar->dragging))
4575 *part = scroll_bar_handle;
4576 else if (win_y < XINT (bar->start))
4577 *part = scroll_bar_above_handle;
4578 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4579 *part = scroll_bar_handle;
4580 else
4581 *part = scroll_bar_below_handle;
4583 XSETINT (*x, win_y);
4584 XSETINT (*y, top_range);
4586 f->mouse_moved = 0;
4587 last_mouse_scroll_bar = Qnil;
4589 *time = last_mouse_movement_time;
4592 /***********************************************************************
4593 Text Cursor
4594 ***********************************************************************/
4596 /* Set clipping for output in glyph row ROW. W is the window in which
4597 we operate. GC is the graphics context to set clipping in.
4599 ROW may be a text row or, e.g., a mode line. Text rows must be
4600 clipped to the interior of the window dedicated to text display,
4601 mode lines must be clipped to the whole window. */
4603 static void
4604 x_clip_to_row (w, row, area, gc)
4605 struct window *w;
4606 struct glyph_row *row;
4607 int area;
4608 GC gc;
4610 struct frame *f = XFRAME (WINDOW_FRAME (w));
4611 Rect clip_rect;
4612 int window_x, window_y, window_width;
4614 window_box (w, area, &window_x, &window_y, &window_width, 0);
4616 clip_rect.left = window_x;
4617 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4618 clip_rect.top = max (clip_rect.top, window_y);
4619 clip_rect.right = clip_rect.left + window_width;
4620 clip_rect.bottom = clip_rect.top + row->visible_height;
4622 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4626 /* Draw a hollow box cursor on window W in glyph row ROW. */
4628 static void
4629 x_draw_hollow_cursor (w, row)
4630 struct window *w;
4631 struct glyph_row *row;
4633 struct frame *f = XFRAME (WINDOW_FRAME (w));
4634 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4635 Display *dpy = FRAME_MAC_DISPLAY (f);
4636 int x, y, wd, h;
4637 XGCValues xgcv;
4638 struct glyph *cursor_glyph;
4639 GC gc;
4641 /* Get the glyph the cursor is on. If we can't tell because
4642 the current matrix is invalid or such, give up. */
4643 cursor_glyph = get_phys_cursor_glyph (w);
4644 if (cursor_glyph == NULL)
4645 return;
4647 /* Compute the width of the rectangle to draw. If on a stretch
4648 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4649 rectangle as wide as the glyph, but use a canonical character
4650 width instead. */
4651 wd = cursor_glyph->pixel_width - 1;
4652 if (cursor_glyph->type == STRETCH_GLYPH
4653 && !x_stretch_cursor_p)
4654 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4655 w->phys_cursor_width = wd;
4657 /* Compute frame-relative coordinates from window-relative
4658 coordinates. */
4659 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4660 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4662 /* Compute the proper height and ascent of the rectangle, based
4663 on the actual glyph. Using the full height of the row looks
4664 bad when there are tall images on that row. */
4665 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4666 cursor_glyph->ascent + cursor_glyph->descent);
4667 if (h < row->height)
4668 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4669 h--;
4671 /* The foreground of cursor_gc is typically the same as the normal
4672 background color, which can cause the cursor box to be invisible. */
4673 xgcv.foreground = f->output_data.mac->cursor_pixel;
4674 if (dpyinfo->scratch_cursor_gc)
4675 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4676 else
4677 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4678 GCForeground, &xgcv);
4679 gc = dpyinfo->scratch_cursor_gc;
4681 /* Set clipping, draw the rectangle, and reset clipping again. */
4682 x_clip_to_row (w, row, TEXT_AREA, gc);
4683 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4684 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4688 /* Draw a bar cursor on window W in glyph row ROW.
4690 Implementation note: One would like to draw a bar cursor with an
4691 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4692 Unfortunately, I didn't find a font yet that has this property set.
4693 --gerd. */
4695 static void
4696 x_draw_bar_cursor (w, row, width, kind)
4697 struct window *w;
4698 struct glyph_row *row;
4699 int width;
4700 enum text_cursor_kinds kind;
4702 struct frame *f = XFRAME (w->frame);
4703 struct glyph *cursor_glyph;
4705 /* If cursor is out of bounds, don't draw garbage. This can happen
4706 in mini-buffer windows when switching between echo area glyphs
4707 and mini-buffer. */
4708 cursor_glyph = get_phys_cursor_glyph (w);
4709 if (cursor_glyph == NULL)
4710 return;
4712 /* If on an image, draw like a normal cursor. That's usually better
4713 visible than drawing a bar, esp. if the image is large so that
4714 the bar might not be in the window. */
4715 if (cursor_glyph->type == IMAGE_GLYPH)
4717 struct glyph_row *row;
4718 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4719 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4721 else
4723 Display *dpy = FRAME_MAC_DISPLAY (f);
4724 Window window = FRAME_MAC_WINDOW (f);
4725 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4726 unsigned long mask = GCForeground | GCBackground;
4727 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4728 XGCValues xgcv;
4730 /* If the glyph's background equals the color we normally draw
4731 the bar cursor in, the bar cursor in its normal color is
4732 invisible. Use the glyph's foreground color instead in this
4733 case, on the assumption that the glyph's colors are chosen so
4734 that the glyph is legible. */
4735 if (face->background == f->output_data.mac->cursor_pixel)
4736 xgcv.background = xgcv.foreground = face->foreground;
4737 else
4738 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4740 if (gc)
4741 XChangeGC (dpy, gc, mask, &xgcv);
4742 else
4744 gc = XCreateGC (dpy, window, mask, &xgcv);
4745 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4748 if (width < 0)
4749 width = FRAME_CURSOR_WIDTH (f);
4750 width = min (cursor_glyph->pixel_width, width);
4752 w->phys_cursor_width = width;
4753 x_clip_to_row (w, row, TEXT_AREA, gc);
4755 if (kind == BAR_CURSOR)
4756 XFillRectangle (dpy, window, gc,
4757 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4758 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4759 width, row->height);
4760 else
4761 XFillRectangle (dpy, window, gc,
4762 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4763 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4764 row->height - width),
4765 cursor_glyph->pixel_width,
4766 width);
4768 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4773 /* RIF: Define cursor CURSOR on frame F. */
4775 static void
4776 mac_define_frame_cursor (f, cursor)
4777 struct frame *f;
4778 Cursor cursor;
4780 #if TARGET_API_MAC_CARBON
4781 SetThemeCursor (cursor);
4782 #else
4783 SetCursor (*cursor);
4784 #endif
4788 /* RIF: Clear area on frame F. */
4790 static void
4791 mac_clear_frame_area (f, x, y, width, height)
4792 struct frame *f;
4793 int x, y, width, height;
4795 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4796 x, y, width, height, 0);
4800 /* RIF: Draw cursor on window W. */
4802 static void
4803 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4804 struct window *w;
4805 struct glyph_row *glyph_row;
4806 int x, y;
4807 int cursor_type, cursor_width;
4808 int on_p, active_p;
4810 if (on_p)
4812 w->phys_cursor_type = cursor_type;
4813 w->phys_cursor_on_p = 1;
4815 if (glyph_row->exact_window_width_line_p
4816 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4818 glyph_row->cursor_in_fringe_p = 1;
4819 draw_fringe_bitmap (w, glyph_row, 0);
4821 else
4822 switch (cursor_type)
4824 case HOLLOW_BOX_CURSOR:
4825 x_draw_hollow_cursor (w, glyph_row);
4826 break;
4828 case FILLED_BOX_CURSOR:
4829 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4830 break;
4832 case BAR_CURSOR:
4833 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4834 break;
4836 case HBAR_CURSOR:
4837 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4838 break;
4840 case NO_CURSOR:
4841 w->phys_cursor_width = 0;
4842 break;
4844 default:
4845 abort ();
4851 /* Icons. */
4853 #if 0 /* MAC_TODO: no icon support yet. */
4855 x_bitmap_icon (f, icon)
4856 struct frame *f;
4857 Lisp_Object icon;
4859 HANDLE hicon;
4861 if (FRAME_W32_WINDOW (f) == 0)
4862 return 1;
4864 if (NILP (icon))
4865 hicon = LoadIcon (hinst, EMACS_CLASS);
4866 else if (STRINGP (icon))
4867 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4868 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4869 else if (SYMBOLP (icon))
4871 LPCTSTR name;
4873 if (EQ (icon, intern ("application")))
4874 name = (LPCTSTR) IDI_APPLICATION;
4875 else if (EQ (icon, intern ("hand")))
4876 name = (LPCTSTR) IDI_HAND;
4877 else if (EQ (icon, intern ("question")))
4878 name = (LPCTSTR) IDI_QUESTION;
4879 else if (EQ (icon, intern ("exclamation")))
4880 name = (LPCTSTR) IDI_EXCLAMATION;
4881 else if (EQ (icon, intern ("asterisk")))
4882 name = (LPCTSTR) IDI_ASTERISK;
4883 else if (EQ (icon, intern ("winlogo")))
4884 name = (LPCTSTR) IDI_WINLOGO;
4885 else
4886 return 1;
4888 hicon = LoadIcon (NULL, name);
4890 else
4891 return 1;
4893 if (hicon == NULL)
4894 return 1;
4896 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4897 (LPARAM) hicon);
4899 return 0;
4901 #endif /* MAC_TODO */
4903 /************************************************************************
4904 Handling X errors
4905 ************************************************************************/
4907 /* Display Error Handling functions not used on W32. Listing them here
4908 helps diff stay in step when comparing w32term.c with xterm.c.
4910 x_error_catcher (display, error)
4911 x_catch_errors (dpy)
4912 x_catch_errors_unwind (old_val)
4913 x_check_errors (dpy, format)
4914 x_had_errors_p (dpy)
4915 x_clear_errors (dpy)
4916 x_uncatch_errors (dpy, count)
4917 x_trace_wire ()
4918 x_connection_signal (signalnum)
4919 x_connection_closed (dpy, error_message)
4920 x_error_quitter (display, error)
4921 x_error_handler (display, error)
4922 x_io_error_quitter (display)
4927 /* Changing the font of the frame. */
4929 /* Give frame F the font named FONTNAME as its default font, and
4930 return the full name of that font. FONTNAME may be a wildcard
4931 pattern; in that case, we choose some font that fits the pattern.
4932 The return value shows which font we chose. */
4934 Lisp_Object
4935 x_new_font (f, fontname)
4936 struct frame *f;
4937 register char *fontname;
4939 struct font_info *fontp
4940 = FS_LOAD_FONT (f, 0, fontname, -1);
4942 if (!fontp)
4943 return Qnil;
4945 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4946 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4947 FRAME_FONTSET (f) = -1;
4949 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4950 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4952 compute_fringe_widths (f, 1);
4954 /* Compute the scroll bar width in character columns. */
4955 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4957 int wid = FRAME_COLUMN_WIDTH (f);
4958 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4959 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4961 else
4963 int wid = FRAME_COLUMN_WIDTH (f);
4964 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4967 /* Now make the frame display the given font. */
4968 if (FRAME_MAC_WINDOW (f) != 0)
4970 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4971 FRAME_FONT (f));
4972 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4973 FRAME_FONT (f));
4974 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4975 FRAME_FONT (f));
4977 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4978 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4981 return build_string (fontp->full_name);
4984 /* Give frame F the fontset named FONTSETNAME as its default font, and
4985 return the full name of that fontset. FONTSETNAME may be a wildcard
4986 pattern; in that case, we choose some fontset that fits the pattern.
4987 The return value shows which fontset we chose. */
4989 Lisp_Object
4990 x_new_fontset (f, fontsetname)
4991 struct frame *f;
4992 char *fontsetname;
4994 int fontset = fs_query_fontset (build_string (fontsetname), 0);
4995 Lisp_Object result;
4997 if (fontset < 0)
4998 return Qnil;
5000 if (FRAME_FONTSET (f) == fontset)
5001 /* This fontset is already set in frame F. There's nothing more
5002 to do. */
5003 return fontset_name (fontset);
5005 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5007 if (!STRINGP (result))
5008 /* Can't load ASCII font. */
5009 return Qnil;
5011 /* Since x_new_font doesn't update any fontset information, do it now. */
5012 FRAME_FONTSET(f) = fontset;
5014 return build_string (fontsetname);
5018 /***********************************************************************
5019 TODO: W32 Input Methods
5020 ***********************************************************************/
5021 /* Listing missing functions from xterm.c helps diff stay in step.
5023 xim_destroy_callback (xim, client_data, call_data)
5024 xim_open_dpy (dpyinfo, resource_name)
5025 struct xim_inst_t
5026 xim_instantiate_callback (display, client_data, call_data)
5027 xim_initialize (dpyinfo, resource_name)
5028 xim_close_dpy (dpyinfo)
5033 void
5034 mac_get_window_bounds (f, inner, outer)
5035 struct frame *f;
5036 Rect *inner, *outer;
5038 #if TARGET_API_MAC_CARBON
5039 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5040 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5041 #else /* not TARGET_API_MAC_CARBON */
5042 RgnHandle region = NewRgn ();
5044 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5045 *inner = (*region)->rgnBBox;
5046 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5047 *outer = (*region)->rgnBBox;
5048 DisposeRgn (region);
5049 #endif /* not TARGET_API_MAC_CARBON */
5053 /* Calculate the absolute position in frame F
5054 from its current recorded position values and gravity. */
5056 void
5057 x_calc_absolute_position (f)
5058 struct frame *f;
5060 int width_diff = 0, height_diff = 0;
5061 int flags = f->size_hint_flags;
5062 Rect inner, outer;
5064 /* We have nothing to do if the current position
5065 is already for the top-left corner. */
5066 if (! ((flags & XNegative) || (flags & YNegative)))
5067 return;
5069 /* Find the offsets of the outside upper-left corner of
5070 the inner window, with respect to the outer window. */
5071 mac_get_window_bounds (f, &inner, &outer);
5073 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5074 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5076 /* Treat negative positions as relative to the leftmost bottommost
5077 position that fits on the screen. */
5078 if (flags & XNegative)
5079 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5080 - width_diff
5081 - FRAME_PIXEL_WIDTH (f)
5082 + f->left_pos);
5084 if (flags & YNegative)
5085 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5086 - height_diff
5087 - FRAME_PIXEL_HEIGHT (f)
5088 + f->top_pos);
5090 /* The left_pos and top_pos
5091 are now relative to the top and left screen edges,
5092 so the flags should correspond. */
5093 f->size_hint_flags &= ~ (XNegative | YNegative);
5096 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5097 to really change the position, and 0 when calling from
5098 x_make_frame_visible (in that case, XOFF and YOFF are the current
5099 position values). It is -1 when calling from x_set_frame_parameters,
5100 which means, do adjust for borders but don't change the gravity. */
5102 void
5103 x_set_offset (f, xoff, yoff, change_gravity)
5104 struct frame *f;
5105 register int xoff, yoff;
5106 int change_gravity;
5108 if (change_gravity > 0)
5110 f->top_pos = yoff;
5111 f->left_pos = xoff;
5112 f->size_hint_flags &= ~ (XNegative | YNegative);
5113 if (xoff < 0)
5114 f->size_hint_flags |= XNegative;
5115 if (yoff < 0)
5116 f->size_hint_flags |= YNegative;
5117 f->win_gravity = NorthWestGravity;
5119 x_calc_absolute_position (f);
5121 BLOCK_INPUT;
5122 x_wm_set_size_hint (f, (long) 0, 0);
5124 #if TARGET_API_MAC_CARBON
5125 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5126 /* If the title bar is completely outside the screen, adjust the
5127 position. */
5128 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5129 kWindowConstrainMoveRegardlessOfFit
5130 | kWindowConstrainAllowPartial, NULL, NULL);
5131 x_real_positions (f, &f->left_pos, &f->top_pos);
5132 #else
5134 Rect inner, outer, screen_rect, dummy;
5135 RgnHandle region = NewRgn ();
5137 mac_get_window_bounds (f, &inner, &outer);
5138 f->x_pixels_diff = inner.left - outer.left;
5139 f->y_pixels_diff = inner.top - outer.top;
5140 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5141 f->top_pos + f->y_pixels_diff, false);
5143 /* If the title bar is completely outside the screen, adjust the
5144 position. The variable `outer' holds the title bar rectangle.
5145 The variable `inner' holds slightly smaller one than `outer',
5146 so that the calculation of overlapping may not become too
5147 strict. */
5148 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5149 outer = (*region)->rgnBBox;
5150 DisposeRgn (region);
5151 inner = outer;
5152 InsetRect (&inner, 8, 8);
5153 screen_rect = qd.screenBits.bounds;
5154 screen_rect.top += GetMBarHeight ();
5156 if (!SectRect (&inner, &screen_rect, &dummy))
5158 if (inner.right <= screen_rect.left)
5159 f->left_pos = screen_rect.left;
5160 else if (inner.left >= screen_rect.right)
5161 f->left_pos = screen_rect.right - (outer.right - outer.left);
5163 if (inner.bottom <= screen_rect.top)
5164 f->top_pos = screen_rect.top;
5165 else if (inner.top >= screen_rect.bottom)
5166 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5168 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5169 f->top_pos + f->y_pixels_diff, false);
5172 #endif
5174 UNBLOCK_INPUT;
5177 /* Call this to change the size of frame F's x-window.
5178 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5179 for this size change and subsequent size changes.
5180 Otherwise we leave the window gravity unchanged. */
5182 void
5183 x_set_window_size (f, change_gravity, cols, rows)
5184 struct frame *f;
5185 int change_gravity;
5186 int cols, rows;
5188 int pixelwidth, pixelheight;
5190 BLOCK_INPUT;
5192 check_frame_size (f, &rows, &cols);
5193 f->scroll_bar_actual_width
5194 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5196 compute_fringe_widths (f, 0);
5198 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5199 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5201 f->win_gravity = NorthWestGravity;
5202 x_wm_set_size_hint (f, (long) 0, 0);
5204 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5206 /* Now, strictly speaking, we can't be sure that this is accurate,
5207 but the window manager will get around to dealing with the size
5208 change request eventually, and we'll hear how it went when the
5209 ConfigureNotify event gets here.
5211 We could just not bother storing any of this information here,
5212 and let the ConfigureNotify event set everything up, but that
5213 might be kind of confusing to the Lisp code, since size changes
5214 wouldn't be reported in the frame parameters until some random
5215 point in the future when the ConfigureNotify event arrives.
5217 We pass 1 for DELAY since we can't run Lisp code inside of
5218 a BLOCK_INPUT. */
5219 change_frame_size (f, rows, cols, 0, 1, 0);
5220 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5221 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5223 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5224 receive in the ConfigureNotify event; if we get what we asked
5225 for, then the event won't cause the screen to become garbaged, so
5226 we have to make sure to do it here. */
5227 SET_FRAME_GARBAGED (f);
5229 XFlush (FRAME_X_DISPLAY (f));
5231 /* If cursor was outside the new size, mark it as off. */
5232 mark_window_cursors_off (XWINDOW (f->root_window));
5234 /* Clear out any recollection of where the mouse highlighting was,
5235 since it might be in a place that's outside the new frame size.
5236 Actually checking whether it is outside is a pain in the neck,
5237 so don't try--just let the highlighting be done afresh with new size. */
5238 cancel_mouse_face (f);
5240 UNBLOCK_INPUT;
5243 /* Mouse warping. */
5245 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5247 void
5248 x_set_mouse_position (f, x, y)
5249 struct frame *f;
5250 int x, y;
5252 int pix_x, pix_y;
5254 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5255 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5257 if (pix_x < 0) pix_x = 0;
5258 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5260 if (pix_y < 0) pix_y = 0;
5261 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5263 x_set_mouse_pixel_position (f, pix_x, pix_y);
5266 void
5267 x_set_mouse_pixel_position (f, pix_x, pix_y)
5268 struct frame *f;
5269 int pix_x, pix_y;
5271 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5272 BLOCK_INPUT;
5274 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5275 0, 0, 0, 0, pix_x, pix_y);
5276 UNBLOCK_INPUT;
5277 #endif
5281 /* focus shifting, raising and lowering. */
5283 void
5284 x_focus_on_frame (f)
5285 struct frame *f;
5287 #if 0 /* This proves to be unpleasant. */
5288 x_raise_frame (f);
5289 #endif
5290 #if 0
5291 /* I don't think that the ICCCM allows programs to do things like this
5292 without the interaction of the window manager. Whatever you end up
5293 doing with this code, do it to x_unfocus_frame too. */
5294 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5295 RevertToPointerRoot, CurrentTime);
5296 #endif /* ! 0 */
5299 void
5300 x_unfocus_frame (f)
5301 struct frame *f;
5305 /* Raise frame F. */
5306 void
5307 x_raise_frame (f)
5308 struct frame *f;
5310 if (f->async_visible)
5312 BLOCK_INPUT;
5313 SelectWindow (FRAME_MAC_WINDOW (f));
5314 UNBLOCK_INPUT;
5318 /* Lower frame F. */
5319 void
5320 x_lower_frame (f)
5321 struct frame *f;
5323 if (f->async_visible)
5325 BLOCK_INPUT;
5326 SendBehind (FRAME_MAC_WINDOW (f), nil);
5327 UNBLOCK_INPUT;
5331 static void
5332 XTframe_raise_lower (f, raise_flag)
5333 FRAME_PTR f;
5334 int raise_flag;
5336 if (raise_flag)
5337 x_raise_frame (f);
5338 else
5339 x_lower_frame (f);
5342 /* Change of visibility. */
5344 /* This tries to wait until the frame is really visible.
5345 However, if the window manager asks the user where to position
5346 the frame, this will return before the user finishes doing that.
5347 The frame will not actually be visible at that time,
5348 but it will become visible later when the window manager
5349 finishes with it. */
5351 void
5352 x_make_frame_visible (f)
5353 struct frame *f;
5355 Lisp_Object type;
5356 int original_top, original_left;
5358 BLOCK_INPUT;
5360 if (! FRAME_VISIBLE_P (f))
5362 /* We test FRAME_GARBAGED_P here to make sure we don't
5363 call x_set_offset a second time
5364 if we get to x_make_frame_visible a second time
5365 before the window gets really visible. */
5366 if (! FRAME_ICONIFIED_P (f)
5367 && ! f->output_data.mac->asked_for_visible)
5368 x_set_offset (f, f->left_pos, f->top_pos, 0);
5370 f->output_data.mac->asked_for_visible = 1;
5372 ShowWindow (FRAME_MAC_WINDOW (f));
5375 XFlush (FRAME_MAC_DISPLAY (f));
5377 /* Synchronize to ensure Emacs knows the frame is visible
5378 before we do anything else. We do this loop with input not blocked
5379 so that incoming events are handled. */
5381 Lisp_Object frame;
5382 int count;
5384 /* This must come after we set COUNT. */
5385 UNBLOCK_INPUT;
5387 XSETFRAME (frame, f);
5389 /* Wait until the frame is visible. Process X events until a
5390 MapNotify event has been seen, or until we think we won't get a
5391 MapNotify at all.. */
5392 for (count = input_signal_count + 10;
5393 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5395 /* Force processing of queued events. */
5396 x_sync (f);
5398 /* Machines that do polling rather than SIGIO have been
5399 observed to go into a busy-wait here. So we'll fake an
5400 alarm signal to let the handler know that there's something
5401 to be read. We used to raise a real alarm, but it seems
5402 that the handler isn't always enabled here. This is
5403 probably a bug. */
5404 if (input_polling_used ())
5406 /* It could be confusing if a real alarm arrives while
5407 processing the fake one. Turn it off and let the
5408 handler reset it. */
5409 extern void poll_for_input_1 P_ ((void));
5410 int old_poll_suppress_count = poll_suppress_count;
5411 poll_suppress_count = 1;
5412 poll_for_input_1 ();
5413 poll_suppress_count = old_poll_suppress_count;
5416 /* See if a MapNotify event has been processed. */
5417 FRAME_SAMPLE_VISIBILITY (f);
5422 /* Change from mapped state to withdrawn state. */
5424 /* Make the frame visible (mapped and not iconified). */
5426 void
5427 x_make_frame_invisible (f)
5428 struct frame *f;
5430 /* Don't keep the highlight on an invisible frame. */
5431 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5432 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5434 BLOCK_INPUT;
5436 HideWindow (FRAME_MAC_WINDOW (f));
5438 /* We can't distinguish this from iconification
5439 just by the event that we get from the server.
5440 So we can't win using the usual strategy of letting
5441 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5442 and synchronize with the server to make sure we agree. */
5443 f->visible = 0;
5444 FRAME_ICONIFIED_P (f) = 0;
5445 f->async_visible = 0;
5446 f->async_iconified = 0;
5448 UNBLOCK_INPUT;
5451 /* Change window state from mapped to iconified. */
5453 void
5454 x_iconify_frame (f)
5455 struct frame *f;
5457 /* Don't keep the highlight on an invisible frame. */
5458 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5459 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5461 #if 0
5462 /* Review: Since window is still visible in dock, still allow updates? */
5463 if (f->async_iconified)
5464 return;
5465 #endif
5467 BLOCK_INPUT;
5469 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5471 UNBLOCK_INPUT;
5475 /* Free X resources of frame F. */
5477 void
5478 x_free_frame_resources (f)
5479 struct frame *f;
5481 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5482 WindowPtr wp = FRAME_MAC_WINDOW (f);
5484 BLOCK_INPUT;
5486 DisposeWindow (wp);
5487 if (wp == tip_window)
5488 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5489 closed' event. So we reset tip_window here. */
5490 tip_window = NULL;
5492 free_frame_menubar (f);
5494 if (FRAME_FACE_CACHE (f))
5495 free_frame_faces (f);
5497 x_free_gcs (f);
5499 xfree (f->output_data.mac);
5500 f->output_data.mac = NULL;
5502 if (f == dpyinfo->x_focus_frame)
5503 dpyinfo->x_focus_frame = 0;
5504 if (f == dpyinfo->x_focus_event_frame)
5505 dpyinfo->x_focus_event_frame = 0;
5506 if (f == dpyinfo->x_highlight_frame)
5507 dpyinfo->x_highlight_frame = 0;
5509 if (f == dpyinfo->mouse_face_mouse_frame)
5511 dpyinfo->mouse_face_beg_row
5512 = dpyinfo->mouse_face_beg_col = -1;
5513 dpyinfo->mouse_face_end_row
5514 = dpyinfo->mouse_face_end_col = -1;
5515 dpyinfo->mouse_face_window = Qnil;
5516 dpyinfo->mouse_face_deferred_gc = 0;
5517 dpyinfo->mouse_face_mouse_frame = 0;
5520 UNBLOCK_INPUT;
5524 /* Destroy the X window of frame F. */
5526 void
5527 x_destroy_window (f)
5528 struct frame *f;
5530 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5532 x_free_frame_resources (f);
5534 dpyinfo->reference_count--;
5538 /* Setting window manager hints. */
5540 /* Set the normal size hints for the window manager, for frame F.
5541 FLAGS is the flags word to use--or 0 meaning preserve the flags
5542 that the window now has.
5543 If USER_POSITION is nonzero, we set the USPosition
5544 flag (this is useful when FLAGS is 0). */
5545 void
5546 x_wm_set_size_hint (f, flags, user_position)
5547 struct frame *f;
5548 long flags;
5549 int user_position;
5551 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5552 XSizeHints size_hints;
5554 #ifdef USE_X_TOOLKIT
5555 Arg al[2];
5556 int ac = 0;
5557 Dimension widget_width, widget_height;
5558 Window window = XtWindow (f->output_data.x->widget);
5559 #else /* not USE_X_TOOLKIT */
5560 Window window = FRAME_X_WINDOW (f);
5561 #endif /* not USE_X_TOOLKIT */
5563 /* Setting PMaxSize caused various problems. */
5564 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5566 size_hints.x = f->left_pos;
5567 size_hints.y = f->top_pos;
5569 #ifdef USE_X_TOOLKIT
5570 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5571 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5572 XtGetValues (f->output_data.x->widget, al, ac);
5573 size_hints.height = widget_height;
5574 size_hints.width = widget_width;
5575 #else /* not USE_X_TOOLKIT */
5576 size_hints.height = FRAME_PIXEL_HEIGHT (f);
5577 size_hints.width = FRAME_PIXEL_WIDTH (f);
5578 #endif /* not USE_X_TOOLKIT */
5580 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
5581 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
5582 size_hints.max_width
5583 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5584 size_hints.max_height
5585 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5587 /* Calculate the base and minimum sizes.
5589 (When we use the X toolkit, we don't do it here.
5590 Instead we copy the values that the widgets are using, below.) */
5591 #ifndef USE_X_TOOLKIT
5593 int base_width, base_height;
5594 int min_rows = 0, min_cols = 0;
5596 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5597 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5599 check_frame_size (f, &min_rows, &min_cols);
5601 /* The window manager uses the base width hints to calculate the
5602 current number of rows and columns in the frame while
5603 resizing; min_width and min_height aren't useful for this
5604 purpose, since they might not give the dimensions for a
5605 zero-row, zero-column frame.
5607 We use the base_width and base_height members if we have
5608 them; otherwise, we set the min_width and min_height members
5609 to the size for a zero x zero frame. */
5611 #ifdef HAVE_X11R4
5612 size_hints.flags |= PBaseSize;
5613 size_hints.base_width = base_width;
5614 size_hints.base_height = base_height;
5615 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5616 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5617 #else
5618 size_hints.min_width = base_width;
5619 size_hints.min_height = base_height;
5620 #endif
5623 /* If we don't need the old flags, we don't need the old hint at all. */
5624 if (flags)
5626 size_hints.flags |= flags;
5627 goto no_read;
5629 #endif /* not USE_X_TOOLKIT */
5632 XSizeHints hints; /* Sometimes I hate X Windows... */
5633 long supplied_return;
5634 int value;
5636 #ifdef HAVE_X11R4
5637 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5638 &supplied_return);
5639 #else
5640 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5641 #endif
5643 #ifdef USE_X_TOOLKIT
5644 size_hints.base_height = hints.base_height;
5645 size_hints.base_width = hints.base_width;
5646 size_hints.min_height = hints.min_height;
5647 size_hints.min_width = hints.min_width;
5648 #endif
5650 if (flags)
5651 size_hints.flags |= flags;
5652 else
5654 if (value == 0)
5655 hints.flags = 0;
5656 if (hints.flags & PSize)
5657 size_hints.flags |= PSize;
5658 if (hints.flags & PPosition)
5659 size_hints.flags |= PPosition;
5660 if (hints.flags & USPosition)
5661 size_hints.flags |= USPosition;
5662 if (hints.flags & USSize)
5663 size_hints.flags |= USSize;
5667 #ifndef USE_X_TOOLKIT
5668 no_read:
5669 #endif
5671 #ifdef PWinGravity
5672 size_hints.win_gravity = f->win_gravity;
5673 size_hints.flags |= PWinGravity;
5675 if (user_position)
5677 size_hints.flags &= ~ PPosition;
5678 size_hints.flags |= USPosition;
5680 #endif /* PWinGravity */
5682 #ifdef HAVE_X11R4
5683 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5684 #else
5685 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5686 #endif
5687 #endif /* MAC_TODO */
5690 #if 0 /* MAC_TODO: hide application instead of iconify? */
5691 /* Used for IconicState or NormalState */
5693 void
5694 x_wm_set_window_state (f, state)
5695 struct frame *f;
5696 int state;
5698 #ifdef USE_X_TOOLKIT
5699 Arg al[1];
5701 XtSetArg (al[0], XtNinitialState, state);
5702 XtSetValues (f->output_data.x->widget, al, 1);
5703 #else /* not USE_X_TOOLKIT */
5704 Window window = FRAME_X_WINDOW (f);
5706 f->output_data.x->wm_hints.flags |= StateHint;
5707 f->output_data.x->wm_hints.initial_state = state;
5709 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5710 #endif /* not USE_X_TOOLKIT */
5713 void
5714 x_wm_set_icon_pixmap (f, pixmap_id)
5715 struct frame *f;
5716 int pixmap_id;
5718 Pixmap icon_pixmap;
5720 #ifndef USE_X_TOOLKIT
5721 Window window = FRAME_X_WINDOW (f);
5722 #endif
5724 if (pixmap_id > 0)
5726 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5727 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5729 else
5731 /* It seems there is no way to turn off use of an icon pixmap.
5732 The following line does it, only if no icon has yet been created,
5733 for some window managers. But with mwm it crashes.
5734 Some people say it should clear the IconPixmapHint bit in this case,
5735 but that doesn't work, and the X consortium said it isn't the
5736 right thing at all. Since there is no way to win,
5737 best to explicitly give up. */
5738 #if 0
5739 f->output_data.x->wm_hints.icon_pixmap = None;
5740 #else
5741 return;
5742 #endif
5745 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5748 Arg al[1];
5749 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5750 XtSetValues (f->output_data.x->widget, al, 1);
5753 #else /* not USE_X_TOOLKIT */
5755 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5756 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5758 #endif /* not USE_X_TOOLKIT */
5761 #endif /* MAC_TODO */
5763 void
5764 x_wm_set_icon_position (f, icon_x, icon_y)
5765 struct frame *f;
5766 int icon_x, icon_y;
5768 #if 0 /* MAC_TODO: no icons on Mac */
5769 #ifdef USE_X_TOOLKIT
5770 Window window = XtWindow (f->output_data.x->widget);
5771 #else
5772 Window window = FRAME_X_WINDOW (f);
5773 #endif
5775 f->output_data.x->wm_hints.flags |= IconPositionHint;
5776 f->output_data.x->wm_hints.icon_x = icon_x;
5777 f->output_data.x->wm_hints.icon_y = icon_y;
5779 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5780 #endif /* MAC_TODO */
5784 /***********************************************************************
5785 Fonts
5786 ***********************************************************************/
5788 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5790 struct font_info *
5791 x_get_font_info (f, font_idx)
5792 FRAME_PTR f;
5793 int font_idx;
5795 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5798 /* the global font name table */
5799 char **font_name_table = NULL;
5800 int font_name_table_size = 0;
5801 int font_name_count = 0;
5803 #if 0
5804 /* compare two strings ignoring case */
5805 static int
5806 stricmp (const char *s, const char *t)
5808 for ( ; tolower (*s) == tolower (*t); s++, t++)
5809 if (*s == '\0')
5810 return 0;
5811 return tolower (*s) - tolower (*t);
5814 /* compare two strings ignoring case and handling wildcard */
5815 static int
5816 wildstrieq (char *s1, char *s2)
5818 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5819 return true;
5821 return stricmp (s1, s2) == 0;
5824 /* Assume parameter 1 is fully qualified, no wildcards. */
5825 static int
5826 mac_font_pattern_match (fontname, pattern)
5827 char * fontname;
5828 char * pattern;
5830 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5831 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5832 char *ptr;
5834 /* Copy fontname so we can modify it during comparison. */
5835 strcpy (font_name_copy, fontname);
5837 ptr = regex;
5838 *ptr++ = '^';
5840 /* Turn pattern into a regexp and do a regexp match. */
5841 for (; *pattern; pattern++)
5843 if (*pattern == '?')
5844 *ptr++ = '.';
5845 else if (*pattern == '*')
5847 *ptr++ = '.';
5848 *ptr++ = '*';
5850 else
5851 *ptr++ = *pattern;
5853 *ptr = '$';
5854 *(ptr + 1) = '\0';
5856 return (fast_c_string_match_ignore_case (build_string (regex),
5857 font_name_copy) >= 0);
5860 /* Two font specs are considered to match if their foundry, family,
5861 weight, slant, and charset match. */
5862 static int
5863 mac_font_match (char *mf, char *xf)
5865 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5866 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5868 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5869 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5870 return mac_font_pattern_match (mf, xf);
5872 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5873 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5874 return mac_font_pattern_match (mf, xf);
5876 return (wildstrieq (m_foundry, x_foundry)
5877 && wildstrieq (m_family, x_family)
5878 && wildstrieq (m_weight, x_weight)
5879 && wildstrieq (m_slant, x_slant)
5880 && wildstrieq (m_charset, x_charset))
5881 || mac_font_pattern_match (mf, xf);
5883 #endif
5885 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5887 static void
5888 decode_mac_font_name (name, size, scriptcode)
5889 char *name;
5890 int size;
5891 #if TARGET_API_MAC_CARBON
5892 int scriptcode;
5893 #else
5894 short scriptcode;
5895 #endif
5897 Lisp_Object coding_system;
5898 struct coding_system coding;
5899 char *buf;
5901 switch (scriptcode)
5903 case smTradChinese:
5904 coding_system = Qbig5;
5905 break;
5906 case smSimpChinese:
5907 coding_system = Qcn_gb;
5908 break;
5909 case smJapanese:
5910 coding_system = Qsjis;
5911 break;
5912 case smKorean:
5913 coding_system = Qeuc_kr;
5914 break;
5915 default:
5916 return;
5919 setup_coding_system (coding_system, &coding);
5920 coding.src_multibyte = 0;
5921 coding.dst_multibyte = 1;
5922 coding.mode |= CODING_MODE_LAST_BLOCK;
5923 coding.composing = COMPOSITION_DISABLED;
5924 buf = (char *) alloca (size);
5926 decode_coding (&coding, name, buf, strlen (name), size - 1);
5927 bcopy (buf, name, coding.produced);
5928 name[coding.produced] = '\0';
5932 static char *
5933 mac_to_x_fontname (name, size, style, scriptcode, encoding_base)
5934 char *name;
5935 int size;
5936 Style style;
5937 #if TARGET_API_MAC_CARBON
5938 int scriptcode;
5939 #else
5940 short scriptcode;
5941 #endif
5943 char foundry[32], family[32], cs[32];
5944 char xf[256], *result, *p;
5946 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5948 strcpy(foundry, "Apple");
5949 strcpy(family, name);
5951 switch (scriptcode)
5953 case smTradChinese: /* == kTextEncodingMacChineseTrad */
5954 strcpy(cs, "big5-0");
5955 break;
5956 case smSimpChinese: /* == kTextEncodingMacChineseSimp */
5957 strcpy(cs, "gb2312.1980-0");
5958 break;
5959 case smJapanese: /* == kTextEncodingMacJapanese */
5960 strcpy(cs, "jisx0208.1983-sjis");
5961 break;
5962 case -smJapanese:
5963 /* Each Apple Japanese font is entered into the font table
5964 twice: once as a jisx0208.1983-sjis font and once as a
5965 jisx0201.1976-0 font. The latter can be used to display
5966 the ascii charset and katakana-jisx0201 charset. A
5967 negative script code signals that the name of this latter
5968 font is being built. */
5969 strcpy(cs, "jisx0201.1976-0");
5970 break;
5971 case smKorean: /* == kTextEncodingMacKorean */
5972 strcpy(cs, "ksc5601.1989-0");
5973 break;
5974 #if TARGET_API_MAC_CARBON
5975 case kTextEncodingMacCyrillic:
5976 strcpy(cs, "mac-cyrillic");
5977 break;
5978 case kTextEncodingMacCentralEurRoman:
5979 strcpy(cs, "mac-centraleuropean");
5980 break;
5981 case kTextEncodingMacSymbol:
5982 case kTextEncodingMacDingbats:
5983 strcpy(cs, "adobe-fontspecific");
5984 break;
5985 #endif
5986 default:
5987 strcpy(cs, "mac-roman");
5988 break;
5992 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5993 foundry, family, style & bold ? "bold" : "medium",
5994 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5996 result = (char *) xmalloc (strlen (xf) + 1);
5997 strcpy (result, xf);
5998 for (p = result; *p; p++)
5999 *p = tolower(*p);
6000 return result;
6004 /* Convert an X font spec to the corresponding mac font name, which
6005 can then be passed to GetFNum after conversion to a Pascal string.
6006 For ordinary Mac fonts, this should just be their names, like
6007 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6008 collection contain their charset designation in their names, like
6009 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6010 names are handled accordingly. */
6011 static void
6012 x_font_name_to_mac_font_name (char *xf, char *mf)
6014 char foundry[32], family[32], weight[20], slant[2], cs[32];
6015 Lisp_Object coding_system = Qnil;
6016 struct coding_system coding;
6018 strcpy (mf, "");
6020 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6021 foundry, family, weight, slant, cs) != 5 &&
6022 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6023 foundry, family, weight, slant, cs) != 5)
6024 return;
6026 if (strcmp (cs, "big5-0") == 0)
6027 coding_system = Qbig5;
6028 else if (strcmp (cs, "gb2312.1980-0") == 0)
6029 coding_system = Qcn_gb;
6030 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
6031 || strcmp (cs, "jisx0201.1976-0") == 0)
6032 coding_system = Qsjis;
6033 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6034 coding_system = Qeuc_kr;
6035 else if (strcmp (cs, "mac-roman") == 0
6036 || strcmp (cs, "mac-cyrillic") == 0
6037 || strcmp (cs, "mac-centraleuropean") == 0
6038 || strcmp (cs, "adobe-fontspecific") == 0)
6039 strcpy (mf, family);
6040 else
6041 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6043 if (!NILP (coding_system))
6045 setup_coding_system (coding_system, &coding);
6046 coding.src_multibyte = 1;
6047 coding.dst_multibyte = 1;
6048 coding.mode |= CODING_MODE_LAST_BLOCK;
6049 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6050 mf[coding.produced] = '\0';
6055 static void
6056 add_font_name_table_entry (char *font_name)
6058 if (font_name_table_size == 0)
6060 font_name_table_size = 16;
6061 font_name_table = (char **)
6062 xmalloc (font_name_table_size * sizeof (char *));
6064 else if (font_name_count + 1 >= font_name_table_size)
6066 font_name_table_size += 16;
6067 font_name_table = (char **)
6068 xrealloc (font_name_table,
6069 font_name_table_size * sizeof (char *));
6072 font_name_table[font_name_count++] = font_name;
6075 /* Sets up the table font_name_table to contain the list of all fonts
6076 in the system the first time the table is used so that the Resource
6077 Manager need not be accessed every time this information is
6078 needed. */
6080 static void
6081 init_font_name_table ()
6083 #if TARGET_API_MAC_CARBON
6084 SInt32 sv;
6086 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6088 FMFontFamilyIterator ffi;
6089 FMFontFamilyInstanceIterator ffii;
6090 FMFontFamily ff;
6092 /* Create a dummy instance iterator here to avoid creating and
6093 destroying it in the loop. */
6094 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6095 return;
6096 /* Create an iterator to enumerate the font families. */
6097 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6098 != noErr)
6100 FMDisposeFontFamilyInstanceIterator (&ffii);
6101 return;
6104 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6106 Str255 name;
6107 FMFont font;
6108 FMFontStyle style;
6109 FMFontSize size;
6110 TextEncoding encoding;
6111 TextEncodingBase sc;
6113 if (FMGetFontFamilyName (ff, name) != noErr)
6114 break;
6115 p2cstr (name);
6116 if (*name == '.')
6117 continue;
6119 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6120 break;
6121 sc = GetTextEncodingBase (encoding);
6122 decode_mac_font_name (name, sizeof (name), sc);
6124 /* Point the instance iterator at the current font family. */
6125 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6126 break;
6128 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6129 == noErr)
6131 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6132 contained in Apple Japanese (SJIS) font. */
6133 again:
6134 if (size == 0)
6136 add_font_name_table_entry (mac_to_x_fontname (name, size,
6137 style, sc));
6138 add_font_name_table_entry (mac_to_x_fontname (name, size,
6139 italic, sc));
6140 add_font_name_table_entry (mac_to_x_fontname (name, size,
6141 bold, sc));
6142 add_font_name_table_entry (mac_to_x_fontname (name, size,
6143 italic | bold,
6144 sc));
6146 else
6147 add_font_name_table_entry (mac_to_x_fontname (name, size,
6148 style, sc));
6149 if (sc == smJapanese)
6151 sc = -smJapanese;
6152 goto again;
6154 else if (sc == -smJapanese)
6155 sc = smJapanese;
6159 /* Dispose of the iterators. */
6160 FMDisposeFontFamilyIterator (&ffi);
6161 FMDisposeFontFamilyInstanceIterator (&ffii);
6163 else
6165 #endif /* TARGET_API_MAC_CARBON */
6166 GrafPtr port;
6167 SInt16 fontnum, old_fontnum;
6168 int num_mac_fonts = CountResources('FOND');
6169 int i, j;
6170 Handle font_handle, font_handle_2;
6171 short id, scriptcode;
6172 ResType type;
6173 Str32 name;
6174 struct FontAssoc *fat;
6175 struct AsscEntry *assc_entry;
6177 GetPort (&port); /* save the current font number used */
6178 #if TARGET_API_MAC_CARBON
6179 old_fontnum = GetPortTextFont (port);
6180 #else
6181 old_fontnum = port->txFont;
6182 #endif
6184 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6186 font_handle = GetIndResource ('FOND', i);
6187 if (!font_handle)
6188 continue;
6190 GetResInfo (font_handle, &id, &type, name);
6191 GetFNum (name, &fontnum);
6192 p2cstr (name);
6193 if (fontnum == 0)
6194 continue;
6196 TextFont (fontnum);
6197 scriptcode = FontToScript (fontnum);
6198 decode_mac_font_name (name, sizeof (name), scriptcode);
6201 HLock (font_handle);
6203 if (GetResourceSizeOnDisk (font_handle)
6204 >= sizeof (struct FamRec))
6206 fat = (struct FontAssoc *) (*font_handle
6207 + sizeof (struct FamRec));
6208 assc_entry
6209 = (struct AsscEntry *) (*font_handle
6210 + sizeof (struct FamRec)
6211 + sizeof (struct FontAssoc));
6213 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6215 if (font_name_table_size == 0)
6217 font_name_table_size = 16;
6218 font_name_table = (char **)
6219 xmalloc (font_name_table_size * sizeof (char *));
6221 else if (font_name_count >= font_name_table_size)
6223 font_name_table_size += 16;
6224 font_name_table = (char **)
6225 xrealloc (font_name_table,
6226 font_name_table_size * sizeof (char *));
6228 font_name_table[font_name_count++]
6229 = mac_to_x_fontname (name,
6230 assc_entry->fontSize,
6231 assc_entry->fontStyle,
6232 scriptcode);
6233 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6234 parts are contained in Apple Japanese (SJIS)
6235 font. */
6236 if (smJapanese == scriptcode)
6238 font_name_table[font_name_count++]
6239 = mac_to_x_fontname (name,
6240 assc_entry->fontSize,
6241 assc_entry->fontStyle,
6242 -smJapanese);
6247 HUnlock (font_handle);
6248 font_handle_2 = GetNextFOND (font_handle);
6249 ReleaseResource (font_handle);
6250 font_handle = font_handle_2;
6252 while (ResError () == noErr && font_handle);
6255 TextFont (old_fontnum);
6256 #if TARGET_API_MAC_CARBON
6258 #endif /* TARGET_API_MAC_CARBON */
6262 enum xlfd_scalable_field_index
6264 XLFD_SCL_PIXEL_SIZE,
6265 XLFD_SCL_POINT_SIZE,
6266 XLFD_SCL_AVGWIDTH,
6267 XLFD_SCL_LAST
6270 static int xlfd_scalable_fields[] =
6272 6, /* PIXEL_SIZE */
6273 7, /* POINT_SIZE */
6274 11, /* AVGWIDTH */
6278 static Lisp_Object
6279 mac_do_list_fonts (pattern, maxnames)
6280 char *pattern;
6281 int maxnames;
6283 int i, n_fonts = 0;
6284 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6285 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6286 char scaled[256];
6287 char *ptr;
6288 int scl_val[XLFD_SCL_LAST], *field, *val;
6290 for (i = 0; i < XLFD_SCL_LAST; i++)
6291 scl_val[i] = -1;
6293 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6294 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6295 fonts are scaled according to the specified size. */
6296 ptr = pattern;
6297 i = 0;
6298 field = xlfd_scalable_fields;
6299 val = scl_val;
6300 if (*ptr == '-')
6303 ptr++;
6304 if (i == *field)
6306 if ('1' <= *ptr && *ptr <= '9')
6308 *val = *ptr++ - '0';
6309 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6310 *val = *val * 10 + *ptr++ - '0';
6311 if (*ptr != '-')
6312 *val = -1;
6314 field++;
6315 val++;
6317 ptr = strchr (ptr, '-');
6318 i++;
6320 while (ptr && i < 14);
6322 if (i == 14 && ptr == NULL)
6324 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6326 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6327 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6329 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6331 scl_val[XLFD_SCL_POINT_SIZE] =
6332 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6334 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6336 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6337 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6340 else
6341 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6343 ptr = regex;
6344 *ptr++ = '^';
6346 /* Turn pattern into a regexp and do a regexp match. */
6347 for (; *pattern; pattern++)
6349 if (*pattern == '?')
6350 *ptr++ = '.';
6351 else if (*pattern == '*')
6353 *ptr++ = '.';
6354 *ptr++ = '*';
6356 else
6357 *ptr++ = tolower (*pattern);
6359 *ptr = '$';
6360 *(ptr + 1) = '\0';
6362 pattern_regex = build_string (regex);
6364 for (i = 0; i < font_name_count; i++)
6366 fontname = build_string (font_name_table[i]);
6367 if (fast_string_match (pattern_regex, fontname) >= 0)
6369 font_list = Fcons (fontname, font_list);
6371 n_fonts++;
6372 if (maxnames > 0 && n_fonts >= maxnames)
6373 break;
6375 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6376 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6378 int former_len = ptr - font_name_table[i];
6380 memcpy (scaled, font_name_table[i], former_len);
6381 sprintf (scaled + former_len,
6382 "-%d-%d-75-75-m-%d-%s",
6383 scl_val[XLFD_SCL_PIXEL_SIZE],
6384 scl_val[XLFD_SCL_POINT_SIZE],
6385 scl_val[XLFD_SCL_AVGWIDTH],
6386 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6387 fontname = build_string (scaled);
6388 if (fast_string_match (pattern_regex, fontname) >= 0)
6390 font_list = Fcons (fontname, font_list);
6392 n_fonts++;
6393 if (maxnames > 0 && n_fonts >= maxnames)
6394 break;
6398 return font_list;
6401 /* Return a list of at most MAXNAMES font specs matching the one in
6402 PATTERN. Cache matching fonts for patterns in
6403 dpyinfo->name_list_element to avoid looking them up again by
6404 calling mac_font_pattern_match (slow). Return as many matching
6405 fonts as possible if MAXNAMES = -1. */
6407 Lisp_Object
6408 x_list_fonts (struct frame *f,
6409 Lisp_Object pattern,
6410 int size,
6411 int maxnames)
6413 Lisp_Object newlist = Qnil, tem, key;
6414 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6416 if (font_name_table == NULL) /* Initialize when first used. */
6417 init_font_name_table ();
6419 if (dpyinfo)
6421 tem = XCDR (dpyinfo->name_list_element);
6422 key = Fcons (pattern, make_number (maxnames));
6424 newlist = Fassoc (key, tem);
6425 if (!NILP (newlist))
6427 newlist = Fcdr_safe (newlist);
6428 goto label_cached;
6432 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6434 /* MAC_TODO: add code for matching outline fonts here */
6436 if (dpyinfo)
6438 XSETCDR (dpyinfo->name_list_element,
6439 Fcons (Fcons (key, newlist),
6440 XCDR (dpyinfo->name_list_element)));
6442 label_cached:
6444 return newlist;
6448 #if GLYPH_DEBUG
6450 /* Check that FONT is valid on frame F. It is if it can be found in F's
6451 font table. */
6453 static void
6454 x_check_font (f, font)
6455 struct frame *f;
6456 XFontStruct *font;
6458 int i;
6459 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6461 xassert (font != NULL);
6463 for (i = 0; i < dpyinfo->n_fonts; i++)
6464 if (dpyinfo->font_table[i].name
6465 && font == dpyinfo->font_table[i].font)
6466 break;
6468 xassert (i < dpyinfo->n_fonts);
6471 #endif /* GLYPH_DEBUG != 0 */
6473 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6474 Note: There are (broken) X fonts out there with invalid XFontStruct
6475 min_bounds contents. For example, handa@etl.go.jp reports that
6476 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6477 have font->min_bounds.width == 0. */
6479 static INLINE void
6480 x_font_min_bounds (font, w, h)
6481 MacFontStruct *font;
6482 int *w, *h;
6485 * TODO: Windows does not appear to offer min bound, only
6486 * average and maximum width, and maximum height.
6488 *h = FONT_HEIGHT (font);
6489 *w = FONT_WIDTH (font);
6493 /* Compute the smallest character width and smallest font height over
6494 all fonts available on frame F. Set the members smallest_char_width
6495 and smallest_font_height in F's x_display_info structure to
6496 the values computed. Value is non-zero if smallest_font_height or
6497 smallest_char_width become smaller than they were before. */
6500 x_compute_min_glyph_bounds (f)
6501 struct frame *f;
6503 int i;
6504 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6505 MacFontStruct *font;
6506 int old_width = dpyinfo->smallest_char_width;
6507 int old_height = dpyinfo->smallest_font_height;
6509 dpyinfo->smallest_font_height = 100000;
6510 dpyinfo->smallest_char_width = 100000;
6512 for (i = 0; i < dpyinfo->n_fonts; ++i)
6513 if (dpyinfo->font_table[i].name)
6515 struct font_info *fontp = dpyinfo->font_table + i;
6516 int w, h;
6518 font = (MacFontStruct *) fontp->font;
6519 xassert (font != (MacFontStruct *) ~0);
6520 x_font_min_bounds (font, &w, &h);
6522 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6523 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6526 xassert (dpyinfo->smallest_char_width > 0
6527 && dpyinfo->smallest_font_height > 0);
6529 return (dpyinfo->n_fonts == 1
6530 || dpyinfo->smallest_char_width < old_width
6531 || dpyinfo->smallest_font_height < old_height);
6535 /* Determine whether given string is a fully-specified XLFD: all 14
6536 fields are present, none is '*'. */
6538 static int
6539 is_fully_specified_xlfd (char *p)
6541 int i;
6542 char *q;
6544 if (*p != '-')
6545 return 0;
6547 for (i = 0; i < 13; i++)
6549 q = strchr (p + 1, '-');
6550 if (q == NULL)
6551 return 0;
6552 if (q - p == 2 && *(p + 1) == '*')
6553 return 0;
6554 p = q;
6557 if (strchr (p + 1, '-') != NULL)
6558 return 0;
6560 if (*(p + 1) == '*' && *(p + 2) == '\0')
6561 return 0;
6563 return 1;
6567 const int kDefaultFontSize = 9;
6570 /* XLoadQueryFont creates and returns an internal representation for a
6571 font in a MacFontStruct struct. There is really no concept
6572 corresponding to "loading" a font on the Mac. But we check its
6573 existence and find the font number and all other information for it
6574 and store them in the returned MacFontStruct. */
6576 static MacFontStruct *
6577 XLoadQueryFont (Display *dpy, char *fontname)
6579 int i, size, is_two_byte_font, char_width;
6580 char *name;
6581 GrafPtr port;
6582 SInt16 old_fontnum, old_fontsize;
6583 Style old_fontface;
6584 Str32 mfontname;
6585 SInt16 fontnum;
6586 Style fontface = normal;
6587 MacFontStruct *font;
6588 FontInfo the_fontinfo;
6589 char s_weight[7], c_slant;
6591 if (is_fully_specified_xlfd (fontname))
6592 name = fontname;
6593 else
6595 Lisp_Object matched_fonts;
6597 matched_fonts = mac_do_list_fonts (fontname, 1);
6598 if (NILP (matched_fonts))
6599 return NULL;
6600 name = SDATA (XCAR (matched_fonts));
6603 GetPort (&port); /* save the current font number used */
6604 #if TARGET_API_MAC_CARBON
6605 old_fontnum = GetPortTextFont (port);
6606 old_fontsize = GetPortTextSize (port);
6607 old_fontface = GetPortTextFace (port);
6608 #else
6609 old_fontnum = port->txFont;
6610 old_fontsize = port->txSize;
6611 old_fontface = port->txFace;
6612 #endif
6614 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6615 size = kDefaultFontSize;
6617 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6618 if (strcmp (s_weight, "bold") == 0)
6619 fontface |= bold;
6621 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6622 if (c_slant == 'i')
6623 fontface |= italic;
6625 x_font_name_to_mac_font_name (name, mfontname);
6626 c2pstr (mfontname);
6627 GetFNum (mfontname, &fontnum);
6628 if (fontnum == 0)
6629 return NULL;
6631 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6633 font->fontname = (char *) xmalloc (strlen (name) + 1);
6634 bcopy (name, font->fontname, strlen (name) + 1);
6636 font->mac_fontnum = fontnum;
6637 font->mac_fontsize = size;
6638 font->mac_fontface = fontface;
6639 font->mac_scriptcode = FontToScript (fontnum);
6641 /* Apple Japanese (SJIS) font is listed as both
6642 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6643 (Roman script) in init_font_name_table (). The latter should be
6644 treated as a one-byte font. */
6646 char cs[32];
6648 if (sscanf (name,
6649 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6650 cs) == 1
6651 && 0 == strcmp (cs, "jisx0201.1976-0"))
6652 font->mac_scriptcode = smRoman;
6655 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6656 font->mac_scriptcode == smTradChinese ||
6657 font->mac_scriptcode == smSimpChinese ||
6658 font->mac_scriptcode == smKorean;
6660 TextFont (fontnum);
6661 TextSize (size);
6662 TextFace (fontface);
6664 GetFontInfo (&the_fontinfo);
6666 font->ascent = the_fontinfo.ascent;
6667 font->descent = the_fontinfo.descent;
6669 font->min_byte1 = 0;
6670 if (is_two_byte_font)
6671 font->max_byte1 = 1;
6672 else
6673 font->max_byte1 = 0;
6674 font->min_char_or_byte2 = 0x20;
6675 font->max_char_or_byte2 = 0xff;
6677 if (is_two_byte_font)
6679 /* Use the width of an "ideographic space" of that font because
6680 the_fontinfo.widMax returns the wrong width for some fonts. */
6681 switch (font->mac_scriptcode)
6683 case smJapanese:
6684 char_width = StringWidth("\p\x81\x40");
6685 break;
6686 case smTradChinese:
6687 char_width = StringWidth("\p\xa1\x40");
6688 break;
6689 case smSimpChinese:
6690 char_width = StringWidth("\p\xa1\xa1");
6691 break;
6692 case smKorean:
6693 char_width = StringWidth("\p\xa1\xa1");
6694 break;
6697 else
6698 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6699 returns 15 for 12-point Monaco! */
6700 char_width = CharWidth ('m');
6702 font->max_bounds.rbearing = char_width;
6703 font->max_bounds.lbearing = 0;
6704 font->max_bounds.width = char_width;
6705 font->max_bounds.ascent = the_fontinfo.ascent;
6706 font->max_bounds.descent = the_fontinfo.descent;
6708 font->min_bounds = font->max_bounds;
6710 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6711 font->per_char = NULL;
6712 else
6714 font->per_char = (XCharStruct *)
6715 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6717 int c;
6719 for (c = 0x20; c <= 0xff; c++)
6721 font->per_char[c - 0x20] = font->max_bounds;
6722 font->per_char[c - 0x20].width =
6723 font->per_char[c - 0x20].rbearing = CharWidth (c);
6728 TextFont (old_fontnum); /* restore previous font number, size and face */
6729 TextSize (old_fontsize);
6730 TextFace (old_fontface);
6732 return font;
6736 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6737 pointer to the structure font_info while allocating it dynamically.
6738 If SIZE is 0, load any size of font.
6739 If loading is failed, return NULL. */
6741 struct font_info *
6742 x_load_font (f, fontname, size)
6743 struct frame *f;
6744 register char *fontname;
6745 int size;
6747 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6748 Lisp_Object font_names;
6750 /* Get a list of all the fonts that match this name. Once we
6751 have a list of matching fonts, we compare them against the fonts
6752 we already have by comparing names. */
6753 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6755 if (!NILP (font_names))
6757 Lisp_Object tail;
6758 int i;
6760 for (i = 0; i < dpyinfo->n_fonts; i++)
6761 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6762 if (dpyinfo->font_table[i].name
6763 && (!strcmp (dpyinfo->font_table[i].name,
6764 SDATA (XCAR (tail)))
6765 || !strcmp (dpyinfo->font_table[i].full_name,
6766 SDATA (XCAR (tail)))))
6767 return (dpyinfo->font_table + i);
6770 /* Load the font and add it to the table. */
6772 char *full_name;
6773 struct MacFontStruct *font;
6774 struct font_info *fontp;
6775 unsigned long value;
6776 int i;
6778 /* If we have found fonts by x_list_font, load one of them. If
6779 not, we still try to load a font by the name given as FONTNAME
6780 because XListFonts (called in x_list_font) of some X server has
6781 a bug of not finding a font even if the font surely exists and
6782 is loadable by XLoadQueryFont. */
6783 if (size > 0 && !NILP (font_names))
6784 fontname = (char *) SDATA (XCAR (font_names));
6786 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6787 if (!font)
6788 return NULL;
6790 /* Find a free slot in the font table. */
6791 for (i = 0; i < dpyinfo->n_fonts; ++i)
6792 if (dpyinfo->font_table[i].name == NULL)
6793 break;
6795 /* If no free slot found, maybe enlarge the font table. */
6796 if (i == dpyinfo->n_fonts
6797 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6799 int sz;
6800 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6801 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6802 dpyinfo->font_table
6803 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6806 fontp = dpyinfo->font_table + i;
6807 if (i == dpyinfo->n_fonts)
6808 ++dpyinfo->n_fonts;
6810 /* Now fill in the slots of *FONTP. */
6811 BLOCK_INPUT;
6812 bzero (fontp, sizeof (*fontp));
6813 fontp->font = font;
6814 fontp->font_idx = i;
6815 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6816 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6818 fontp->full_name = fontp->name;
6820 fontp->size = font->max_bounds.width;
6821 fontp->height = FONT_HEIGHT (font);
6823 /* For some font, ascent and descent in max_bounds field is
6824 larger than the above value. */
6825 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6826 if (max_height > fontp->height)
6827 fontp->height = max_height;
6830 /* The slot `encoding' specifies how to map a character
6831 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6832 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6833 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6834 2:0xA020..0xFF7F). For the moment, we don't know which charset
6835 uses this font. So, we set information in fontp->encoding[1]
6836 which is never used by any charset. If mapping can't be
6837 decided, set FONT_ENCODING_NOT_DECIDED. */
6838 if (font->mac_scriptcode == smJapanese)
6839 fontp->encoding[1] = 4;
6840 else
6842 fontp->encoding[1]
6843 = (font->max_byte1 == 0
6844 /* 1-byte font */
6845 ? (font->min_char_or_byte2 < 0x80
6846 ? (font->max_char_or_byte2 < 0x80
6847 ? 0 /* 0x20..0x7F */
6848 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6849 : 1) /* 0xA0..0xFF */
6850 /* 2-byte font */
6851 : (font->min_byte1 < 0x80
6852 ? (font->max_byte1 < 0x80
6853 ? (font->min_char_or_byte2 < 0x80
6854 ? (font->max_char_or_byte2 < 0x80
6855 ? 0 /* 0x2020..0x7F7F */
6856 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6857 : 3) /* 0x20A0..0x7FFF */
6858 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6859 : (font->min_char_or_byte2 < 0x80
6860 ? (font->max_char_or_byte2 < 0x80
6861 ? 2 /* 0xA020..0xFF7F */
6862 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6863 : 1))); /* 0xA0A0..0xFFFF */
6866 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6867 fontp->baseline_offset
6868 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6869 ? (long) value : 0);
6870 fontp->relative_compose
6871 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6872 ? (long) value : 0);
6873 fontp->default_ascent
6874 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6875 ? (long) value : 0);
6876 #else
6877 fontp->baseline_offset = 0;
6878 fontp->relative_compose = 0;
6879 fontp->default_ascent = 0;
6880 #endif
6882 /* Set global flag fonts_changed_p to non-zero if the font loaded
6883 has a character with a smaller width than any other character
6884 before, or if the font loaded has a smalle>r height than any
6885 other font loaded before. If this happens, it will make a
6886 glyph matrix reallocation necessary. */
6887 fonts_changed_p = x_compute_min_glyph_bounds (f);
6888 UNBLOCK_INPUT;
6889 return fontp;
6894 /* Return a pointer to struct font_info of a font named FONTNAME for
6895 frame F. If no such font is loaded, return NULL. */
6897 struct font_info *
6898 x_query_font (f, fontname)
6899 struct frame *f;
6900 register char *fontname;
6902 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6903 int i;
6905 for (i = 0; i < dpyinfo->n_fonts; i++)
6906 if (dpyinfo->font_table[i].name
6907 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6908 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6909 return (dpyinfo->font_table + i);
6910 return NULL;
6914 /* Find a CCL program for a font specified by FONTP, and set the member
6915 `encoder' of the structure. */
6917 void
6918 x_find_ccl_program (fontp)
6919 struct font_info *fontp;
6921 Lisp_Object list, elt;
6923 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6925 elt = XCAR (list);
6926 if (CONSP (elt)
6927 && STRINGP (XCAR (elt))
6928 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6929 >= 0))
6930 break;
6932 if (! NILP (list))
6934 struct ccl_program *ccl
6935 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6937 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6938 xfree (ccl);
6939 else
6940 fontp->font_encoder = ccl;
6946 /* The Mac Event loop code */
6948 #ifndef MAC_OSX
6949 #include <Events.h>
6950 #include <Quickdraw.h>
6951 #include <Balloons.h>
6952 #include <Devices.h>
6953 #include <Fonts.h>
6954 #include <Gestalt.h>
6955 #include <Menus.h>
6956 #include <Processes.h>
6957 #include <Sound.h>
6958 #include <ToolUtils.h>
6959 #include <TextUtils.h>
6960 #include <Dialogs.h>
6961 #include <Script.h>
6962 #include <Types.h>
6963 #include <TextEncodingConverter.h>
6964 #include <Resources.h>
6966 #if __MWERKS__
6967 #include <unix.h>
6968 #endif
6969 #endif /* ! MAC_OSX */
6971 #define M_APPLE 128
6972 #define I_ABOUT 1
6974 #define WINDOW_RESOURCE 128
6975 #define TERM_WINDOW_RESOURCE 129
6977 #define DEFAULT_NUM_COLS 80
6979 #define MIN_DOC_SIZE 64
6980 #define MAX_DOC_SIZE 32767
6982 /* sleep time for WaitNextEvent */
6983 #define WNE_SLEEP_AT_SUSPEND 10
6984 #define WNE_SLEEP_AT_RESUME 1
6986 /* true when cannot handle any Mac OS events */
6987 static int handling_window_update = 0;
6989 #if 0
6990 /* the flag appl_is_suspended is used both for determining the sleep
6991 time to be passed to WaitNextEvent and whether the cursor should be
6992 drawn when updating the display. The cursor is turned off when
6993 Emacs is suspended. Redrawing it is unnecessary and what needs to
6994 be done depends on whether the cursor lies inside or outside the
6995 redraw region. So we might as well skip drawing it when Emacs is
6996 suspended. */
6997 static Boolean app_is_suspended = false;
6998 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
6999 #endif
7001 #define EXTRA_STACK_ALLOC (256 * 1024)
7003 #define ARGV_STRING_LIST_ID 129
7004 #define ABOUT_ALERT_ID 128
7005 #define RAM_TOO_LARGE_ALERT_ID 129
7007 Boolean terminate_flag = false;
7009 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7010 Lisp_Object Qreverse;
7012 /* True if using command key as meta key. */
7013 Lisp_Object Vmac_command_key_is_meta;
7015 /* Modifier associated with the option key, or nil for normal behavior. */
7016 Lisp_Object Vmac_option_modifier;
7018 /* True if the ctrl and meta keys should be reversed. */
7019 Lisp_Object Vmac_reverse_ctrl_meta;
7021 /* True if the option and command modifiers should be used to emulate
7022 a three button mouse */
7023 Lisp_Object Vmac_emulate_three_button_mouse;
7025 #if USE_CARBON_EVENTS
7026 /* True if the mouse wheel button (i.e. button 4) should map to
7027 mouse-2, instead of mouse-3. */
7028 Lisp_Object Vmac_wheel_button_is_mouse_2;
7030 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7031 for processing before Emacs sees it. */
7032 Lisp_Object Vmac_pass_command_to_system;
7034 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7035 for processing before Emacs sees it. */
7036 Lisp_Object Vmac_pass_control_to_system;
7037 #endif
7039 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7040 to this text encoding */
7041 int mac_keyboard_text_encoding;
7042 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7044 /* Set in term/mac-win.el to indicate that event loop can now generate
7045 drag and drop events. */
7046 Lisp_Object Qmac_ready_for_drag_n_drop;
7048 Lisp_Object drag_and_drop_file_list;
7050 Point saved_menu_event_location;
7052 #if !TARGET_API_MAC_CARBON
7053 /* Place holder for the default arrow cursor. */
7054 CursPtr arrow_cursor;
7055 #endif
7057 /* Apple Events */
7058 static void init_required_apple_events (void);
7059 static pascal OSErr
7060 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7061 static pascal OSErr
7062 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7063 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7064 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7066 /* Drag and Drop */
7067 static OSErr init_mac_drag_n_drop ();
7068 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7070 #if USE_CARBON_EVENTS
7071 /* Preliminary Support for the OSX Services Menu */
7072 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7073 static void init_service_handler ();
7074 #endif
7076 extern void init_emacs_passwd_dir ();
7077 extern int emacs_main (int, char **, char **);
7078 extern void check_alarm ();
7080 extern void initialize_applescript();
7081 extern void terminate_applescript();
7083 static unsigned int
7084 #if USE_CARBON_EVENTS
7085 mac_to_emacs_modifiers (UInt32 mods)
7086 #else
7087 mac_to_emacs_modifiers (EventModifiers mods)
7088 #endif
7090 unsigned int result = 0;
7091 if (mods & macShiftKey)
7092 result |= shift_modifier;
7093 if (mods & macCtrlKey)
7094 result |= ctrl_modifier;
7095 if (mods & macMetaKey)
7096 result |= meta_modifier;
7097 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7098 result |= alt_modifier;
7099 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7100 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7101 if (!NILP(val))
7102 result |= XUINT(val);
7105 return result;
7108 static int
7109 mac_get_emulated_btn ( UInt32 modifiers )
7111 int result = 0;
7112 if (!NILP (Vmac_emulate_three_button_mouse)) {
7113 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7114 if (modifiers & cmdKey)
7115 result = cmdIs3 ? 2 : 1;
7116 else if (modifiers & optionKey)
7117 result = cmdIs3 ? 1 : 2;
7119 return result;
7122 #if USE_CARBON_EVENTS
7123 /* Obtains the event modifiers from the event ref and then calls
7124 mac_to_emacs_modifiers. */
7125 static int
7126 mac_event_to_emacs_modifiers (EventRef eventRef)
7128 UInt32 mods = 0;
7129 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7130 sizeof (UInt32), NULL, &mods);
7131 if (!NILP (Vmac_emulate_three_button_mouse) &&
7132 GetEventClass(eventRef) == kEventClassMouse)
7134 mods &= ~(optionKey | cmdKey);
7136 return mac_to_emacs_modifiers (mods);
7139 /* Given an event ref, return the code to use for the mouse button
7140 code in the emacs input_event. */
7141 static int
7142 mac_get_mouse_btn (EventRef ref)
7144 EventMouseButton result = kEventMouseButtonPrimary;
7145 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7146 sizeof (EventMouseButton), NULL, &result);
7147 switch (result)
7149 case kEventMouseButtonPrimary:
7150 if (NILP (Vmac_emulate_three_button_mouse))
7151 return 0;
7152 else {
7153 UInt32 mods = 0;
7154 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7155 sizeof (UInt32), NULL, &mods);
7156 return mac_get_emulated_btn(mods);
7158 case kEventMouseButtonSecondary:
7159 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7160 case kEventMouseButtonTertiary:
7161 case 4: /* 4 is the number for the mouse wheel button */
7162 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7163 default:
7164 return 0;
7168 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7169 events. However the click of the mouse wheel is not converted to a
7170 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7171 checks to see if it is a mouse up or down carbon event that has not
7172 been converted, and if so, converts it by hand (to be picked up in
7173 the XTread_socket loop). */
7174 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7176 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7177 /* Do special case for mouse wheel button. */
7178 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7180 UInt32 kind = GetEventKind (eventRef);
7181 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7183 eventRec->what = mouseDown;
7184 result=1;
7186 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7188 eventRec->what = mouseUp;
7189 result=1;
7191 if (result)
7193 /* Need where and when. */
7194 UInt32 mods;
7195 GetEventParameter (eventRef, kEventParamMouseLocation,
7196 typeQDPoint, NULL, sizeof (Point),
7197 NULL, &eventRec->where);
7198 /* Use two step process because new event modifiers are
7199 32-bit and old are 16-bit. Currently, only loss is
7200 NumLock & Fn. */
7201 GetEventParameter (eventRef, kEventParamKeyModifiers,
7202 typeUInt32, NULL, sizeof (UInt32),
7203 NULL, &mods);
7204 eventRec->modifiers = mods;
7206 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7209 return result;
7212 #endif
7214 static void
7215 do_get_menus (void)
7217 Handle menubar_handle;
7218 MenuHandle menu_handle;
7220 menubar_handle = GetNewMBar (128);
7221 if(menubar_handle == NULL)
7222 abort ();
7223 SetMenuBar (menubar_handle);
7224 DrawMenuBar ();
7226 menu_handle = GetMenuHandle (M_APPLE);
7227 if(menu_handle != NULL)
7228 AppendResMenu (menu_handle,'DRVR');
7229 else
7230 abort ();
7234 static void
7235 do_init_managers (void)
7237 #if !TARGET_API_MAC_CARBON
7238 InitGraf (&qd.thePort);
7239 InitFonts ();
7240 FlushEvents (everyEvent, 0);
7241 InitWindows ();
7242 InitMenus ();
7243 TEInit ();
7244 InitDialogs (NULL);
7245 #endif /* !TARGET_API_MAC_CARBON */
7246 InitCursor ();
7248 #if !TARGET_API_MAC_CARBON
7249 arrow_cursor = &qd.arrow;
7251 /* set up some extra stack space for use by emacs */
7252 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7254 /* MaxApplZone must be called for AppleScript to execute more
7255 complicated scripts */
7256 MaxApplZone ();
7257 MoreMasters ();
7258 #endif /* !TARGET_API_MAC_CARBON */
7261 static void
7262 do_check_ram_size (void)
7264 SInt32 physical_ram_size, logical_ram_size;
7266 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7267 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7268 || physical_ram_size > (1 << VALBITS)
7269 || logical_ram_size > (1 << VALBITS))
7271 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7272 exit (1);
7276 static void
7277 do_window_update (WindowPtr win)
7279 struct frame *f = mac_window_to_frame (win);
7281 if (win == tip_window)
7282 /* The tooltip has been drawn already. Avoid the
7283 SET_FRAME_GARBAGED below. */
7284 return;
7286 if (f)
7288 if (f->async_visible == 0)
7290 f->async_visible = 1;
7291 f->async_iconified = 0;
7292 SET_FRAME_GARBAGED (f);
7294 /* An update event is equivalent to MapNotify on X, so report
7295 visibility changes properly. */
7296 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7297 /* Force a redisplay sooner or later to update the
7298 frame titles in case this is the second frame. */
7299 record_asynch_buffer_change ();
7301 else
7303 BeginUpdate (win);
7304 handling_window_update = 1;
7306 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
7308 expose_frame (f, 0, 0, 0, 0);
7310 handling_window_update = 0;
7311 EndUpdate (win);
7316 static int
7317 is_emacs_window (WindowPtr win)
7319 Lisp_Object tail, frame;
7321 if (!win)
7322 return 0;
7324 FOR_EACH_FRAME (tail, frame)
7325 if (FRAME_MAC_P (XFRAME (frame)))
7326 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7327 return 1;
7329 return 0;
7332 static void
7333 do_app_resume ()
7335 /* Window-activate events will do the job. */
7336 #if 0
7337 WindowPtr wp;
7338 struct frame *f;
7340 wp = front_emacs_window ();
7341 if (wp)
7343 f = mac_window_to_frame (wp);
7345 if (f)
7347 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7348 activate_scroll_bars (f);
7352 app_is_suspended = false;
7353 app_sleep_time = WNE_SLEEP_AT_RESUME;
7354 #endif
7357 static void
7358 do_app_suspend ()
7360 /* Window-deactivate events will do the job. */
7361 #if 0
7362 WindowPtr wp;
7363 struct frame *f;
7365 wp = front_emacs_window ();
7366 if (wp)
7368 f = mac_window_to_frame (wp);
7370 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7372 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7373 deactivate_scroll_bars (f);
7377 app_is_suspended = true;
7378 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7379 #endif
7383 static void
7384 do_mouse_moved (mouse_pos, f)
7385 Point mouse_pos;
7386 FRAME_PTR *f;
7388 WindowPtr wp = front_emacs_window ();
7389 struct x_display_info *dpyinfo;
7391 if (wp)
7393 *f = mac_window_to_frame (wp);
7394 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7396 if (dpyinfo->mouse_face_hidden)
7398 dpyinfo->mouse_face_hidden = 0;
7399 clear_mouse_face (dpyinfo);
7402 SetPortWindowPort (wp);
7404 GlobalToLocal (&mouse_pos);
7406 if (dpyinfo->grabbed && tracked_scroll_bar)
7407 x_scroll_bar_note_movement (tracked_scroll_bar,
7408 mouse_pos.v
7409 - XINT (tracked_scroll_bar->top),
7410 TickCount() * (1000 / 60));
7411 else
7412 note_mouse_movement (*f, &mouse_pos);
7417 static void
7418 do_apple_menu (SInt16 menu_item)
7420 #if !TARGET_API_MAC_CARBON
7421 Str255 item_name;
7422 SInt16 da_driver_refnum;
7424 if (menu_item == I_ABOUT)
7425 NoteAlert (ABOUT_ALERT_ID, NULL);
7426 else
7428 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7429 da_driver_refnum = OpenDeskAcc (item_name);
7431 #endif /* !TARGET_API_MAC_CARBON */
7434 void
7435 do_menu_choice (SInt32 menu_choice)
7437 SInt16 menu_id, menu_item;
7439 menu_id = HiWord (menu_choice);
7440 menu_item = LoWord (menu_choice);
7442 if (menu_id == 0)
7443 return;
7445 switch (menu_id)
7447 case M_APPLE:
7448 do_apple_menu (menu_item);
7449 break;
7451 default:
7453 struct frame *f = mac_window_to_frame (front_emacs_window ());
7454 MenuHandle menu = GetMenuHandle (menu_id);
7455 if (menu)
7457 UInt32 refcon;
7459 GetMenuItemRefCon (menu, menu_item, &refcon);
7460 menubar_selection_callback (f, refcon);
7465 HiliteMenu (0);
7469 /* Handle drags in size box. Based on code contributed by Ben
7470 Mesander and IM - Window Manager A. */
7472 static void
7473 do_grow_window (WindowPtr w, EventRecord *e)
7475 long grow_size;
7476 Rect limit_rect;
7477 int rows, columns;
7478 struct frame *f = mac_window_to_frame (w);
7480 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
7482 grow_size = GrowWindow (w, e->where, &limit_rect);
7484 /* see if it really changed size */
7485 if (grow_size != 0)
7487 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
7488 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
7490 x_set_window_size (f, 0, columns, rows);
7495 /* Handle clicks in zoom box. Calculation of "standard state" based
7496 on code in IM - Window Manager A and code contributed by Ben
7497 Mesander. The standard state of an Emacs window is 80-characters
7498 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7500 static void
7501 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7503 GrafPtr save_port;
7504 Rect zoom_rect, port_rect;
7505 Point top_left;
7506 int w_title_height, columns, rows;
7507 struct frame *f = mac_window_to_frame (w);
7509 #if TARGET_API_MAC_CARBON
7511 Point standard_size;
7513 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7514 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7516 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7517 zoom_in_or_out = inZoomIn;
7518 else
7520 /* Adjust the standard size according to character boundaries. */
7522 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7523 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7524 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7525 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7526 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7527 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7528 && port_rect.left == zoom_rect.left
7529 && port_rect.top == zoom_rect.top)
7530 zoom_in_or_out = inZoomIn;
7531 else
7532 zoom_in_or_out = inZoomOut;
7535 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7537 #else /* not TARGET_API_MAC_CARBON */
7538 GetPort (&save_port);
7540 SetPortWindowPort (w);
7542 /* Clear window to avoid flicker. */
7543 EraseRect (&(w->portRect));
7544 if (zoom_in_or_out == inZoomOut)
7546 SetPt (&top_left, w->portRect.left, w->portRect.top);
7547 LocalToGlobal (&top_left);
7549 /* calculate height of window's title bar */
7550 w_title_height = top_left.v - 1
7551 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7553 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7554 zoom_rect = qd.screenBits.bounds;
7555 zoom_rect.top += w_title_height;
7556 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7558 zoom_rect.right = zoom_rect.left
7559 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7561 /* Adjust the standard size according to character boundaries. */
7562 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7563 zoom_rect.bottom =
7564 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7566 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7567 = zoom_rect;
7570 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7572 SetPort (save_port);
7573 #endif /* not TARGET_API_MAC_CARBON */
7575 /* retrieve window size and update application values */
7576 #if TARGET_API_MAC_CARBON
7577 GetWindowPortBounds (w, &port_rect);
7578 #else
7579 port_rect = w->portRect;
7580 #endif
7581 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
7582 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
7583 x_set_window_size (f, 0, columns, rows);
7584 x_real_positions (f, &f->left_pos, &f->top_pos);
7587 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7588 static OSErr
7589 init_mac_drag_n_drop ()
7591 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7592 return result;
7595 /* Intialize AppleEvent dispatcher table for the required events. */
7596 void
7597 init_required_apple_events ()
7599 OSErr err;
7600 long result;
7602 /* Make sure we have apple events before starting. */
7603 err = Gestalt (gestaltAppleEventsAttr, &result);
7604 if (err != noErr)
7605 abort ();
7607 if (!(result & (1 << gestaltAppleEventsPresent)))
7608 abort ();
7610 #if TARGET_API_MAC_CARBON
7611 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7612 NewAEEventHandlerUPP
7613 ((AEEventHandlerProcPtr) do_ae_open_application),
7614 0L, false);
7615 #else
7616 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7617 NewAEEventHandlerProc
7618 ((AEEventHandlerProcPtr) do_ae_open_application),
7619 0L, false);
7620 #endif
7621 if (err != noErr)
7622 abort ();
7624 #if TARGET_API_MAC_CARBON
7625 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7626 NewAEEventHandlerUPP
7627 ((AEEventHandlerProcPtr) do_ae_open_documents),
7628 0L, false);
7629 #else
7630 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7631 NewAEEventHandlerProc
7632 ((AEEventHandlerProcPtr) do_ae_open_documents),
7633 0L, false);
7634 #endif
7635 if (err != noErr)
7636 abort ();
7638 #if TARGET_API_MAC_CARBON
7639 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7640 NewAEEventHandlerUPP
7641 ((AEEventHandlerProcPtr) do_ae_print_documents),
7642 0L, false);
7643 #else
7644 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7645 NewAEEventHandlerProc
7646 ((AEEventHandlerProcPtr) do_ae_print_documents),
7647 0L, false);
7648 #endif
7649 if (err != noErr)
7650 abort ();
7652 #if TARGET_API_MAC_CARBON
7653 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7654 NewAEEventHandlerUPP
7655 ((AEEventHandlerProcPtr) do_ae_quit_application),
7656 0L, false);
7657 #else
7658 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7659 NewAEEventHandlerProc
7660 ((AEEventHandlerProcPtr) do_ae_quit_application),
7661 0L, false);
7662 #endif
7663 if (err != noErr)
7664 abort ();
7667 #if USE_CARBON_EVENTS
7669 void
7670 init_service_handler ()
7672 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7673 {kEventClassService, kEventServiceCopy},
7674 {kEventClassService, kEventServicePaste}};
7675 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7676 3, specs, NULL, NULL);
7680 MAC_TODO: Check to see if this is called by AEProcessDesc...
7682 OSStatus
7683 mac_handle_service_event (EventHandlerCallRef callRef,
7684 EventRef event, void *data)
7686 OSStatus err = noErr;
7687 switch (GetEventKind (event))
7689 case kEventServiceGetTypes:
7691 CFMutableArrayRef copyTypes, pasteTypes;
7692 CFStringRef type;
7693 Boolean selection = true;
7695 GetEventParameter(event, kEventParamServicePasteTypes,
7696 typeCFMutableArrayRef, NULL,
7697 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7699 GetEventParameter(event, kEventParamServiceCopyTypes,
7700 typeCFMutableArrayRef, NULL,
7701 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7702 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7703 if (type) {
7704 CFArrayAppendValue (copyTypes, type);
7705 //CFArrayAppendValue (pasteTypes, type);
7706 CFRelease (type);
7709 case kEventServiceCopy:
7711 ScrapRef currentScrap, specificScrap;
7712 char * buf = "";
7713 Size byteCount = 0;
7715 GetCurrentScrap (&currentScrap);
7717 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7718 if (err == noErr)
7720 void *buffer = xmalloc (byteCount);
7721 if (buffer != NULL)
7723 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7724 sizeof (ScrapRef), NULL, &specificScrap);
7726 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7727 &byteCount, buffer);
7728 if (err == noErr)
7729 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7730 kScrapFlavorMaskNone, byteCount, buffer);
7731 xfree (buffer);
7734 err = noErr;
7736 case kEventServicePaste:
7739 // Get the current location
7740 Size byteCount;
7741 ScrapRef specificScrap;
7742 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7743 sizeof(ScrapRef), NULL, &specificScrap);
7744 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7745 if (err == noErr) {
7746 void * buffer = xmalloc(byteCount);
7747 if (buffer != NULL ) {
7748 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7749 &byteCount, buffer);
7750 if (err == noErr) {
7751 // Actually place in the buffer
7752 BLOCK_INPUT;
7753 // Get the current "selection" string here
7754 UNBLOCK_INPUT;
7757 xfree(buffer);
7762 return err;
7764 #endif
7766 /* Open Application Apple Event */
7767 static pascal OSErr
7768 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7770 return noErr;
7774 /* Defined in mac.c. */
7775 extern int
7776 path_from_vol_dir_name (char *, int, short, long, char *);
7779 /* Called when we receive an AppleEvent with an ID of
7780 "kAEOpenDocuments". This routine gets the direct parameter,
7781 extracts the FSSpecs in it, and puts their names on a list. */
7782 static pascal OSErr
7783 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7785 OSErr err, err2;
7786 AEDesc the_desc;
7787 AEKeyword keyword;
7788 DescType actual_type;
7789 Size actual_size;
7791 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7792 if (err != noErr)
7793 goto descriptor_error_exit;
7795 /* Check to see that we got all of the required parameters from the
7796 event descriptor. For an 'odoc' event this should just be the
7797 file list. */
7798 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
7799 &actual_type, (Ptr) &keyword,
7800 sizeof (keyword), &actual_size);
7801 /* No error means that we found some unused parameters.
7802 errAEDescNotFound means that there are no more parameters. If we
7803 get an error code other than that, flag it. */
7804 if ((err == noErr) || (err != errAEDescNotFound))
7806 err = errAEEventNotHandled;
7807 goto error_exit;
7809 err = noErr;
7811 /* Got all the parameters we need. Now, go through the direct
7812 object list and parse it up. */
7814 long num_files_to_open;
7816 err = AECountItems (&the_desc, &num_files_to_open);
7817 if (err == noErr)
7819 int i;
7821 /* AE file list is one based so just use that for indexing here. */
7822 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7824 FSSpec fs;
7825 Str255 path_name, unix_path_name;
7826 #ifdef MAC_OSX
7827 FSRef fref;
7828 #endif
7830 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7831 (Ptr) &fs, sizeof (fs), &actual_size);
7832 if (err != noErr) break;
7834 #ifdef MAC_OSX
7835 err = FSpMakeFSRef (&fs, &fref);
7836 if (err != noErr) break;
7838 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
7839 #else
7840 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
7841 fs.name) &&
7842 mac_to_posix_pathname (path_name, unix_path_name, 255))
7843 #endif
7844 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7845 drag_and_drop_file_list);
7850 error_exit:
7851 /* Nuke the coerced file list in any case */
7852 err2 = AEDisposeDesc(&the_desc);
7854 descriptor_error_exit:
7855 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7856 return err;
7860 static pascal OSErr
7861 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
7862 DragReference theDrag)
7864 short items;
7865 short index;
7866 FlavorFlags theFlags;
7867 Point mouse;
7868 OSErr result;
7869 ItemReference theItem;
7870 HFSFlavor data;
7871 FSRef fref;
7872 Size size = sizeof (HFSFlavor);
7874 drag_and_drop_file_list = Qnil;
7875 GetDragMouse (theDrag, &mouse, 0L);
7876 CountDragItems (theDrag, &items);
7877 for (index = 1; index <= items; index++)
7879 /* Only handle file references. */
7880 GetDragItemReferenceNumber (theDrag, index, &theItem);
7881 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
7882 if (result == noErr)
7884 #ifdef MAC_OSX
7885 FSRef frref;
7886 #else
7887 Str255 path_name;
7888 #endif
7889 Str255 unix_path_name;
7890 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
7891 #ifdef MAC_OSX
7892 /* Use Carbon routines, otherwise it converts the file name
7893 to /Macintosh HD/..., which is not correct. */
7894 FSpMakeFSRef (&data.fileSpec, &fref);
7895 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
7896 #else
7897 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
7898 data.fileSpec.parID, data.fileSpec.name) &&
7899 mac_to_posix_pathname (path_name, unix_path_name, 255))
7900 #endif
7901 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7902 drag_and_drop_file_list);
7904 else
7905 return;
7907 /* If there are items in the list, construct an event and post it to
7908 the queue like an interrupt using kbd_buffer_store_event. */
7909 if (!NILP (drag_and_drop_file_list))
7911 struct input_event event;
7912 Lisp_Object frame;
7913 struct frame *f = mac_window_to_frame (window);
7914 SetPortWindowPort (window);
7915 GlobalToLocal (&mouse);
7917 event.kind = DRAG_N_DROP_EVENT;
7918 event.code = 0;
7919 event.modifiers = 0;
7920 event.timestamp = TickCount () * (1000 / 60);
7921 XSETINT (event.x, mouse.h);
7922 XSETINT (event.y, mouse.v);
7923 XSETFRAME (frame, f);
7924 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
7925 event.arg = Qnil;
7926 /* Post to the interrupt queue */
7927 kbd_buffer_store_event (&event);
7928 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7930 ProcessSerialNumber psn;
7931 GetCurrentProcess (&psn);
7932 SetFrontProcess (&psn);
7938 /* Print Document Apple Event */
7939 static pascal OSErr
7940 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
7942 return errAEEventNotHandled;
7946 static pascal OSErr
7947 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
7949 /* FixMe: Do we need an unwind-protect or something here? And what
7950 do we do about unsaved files. Currently just forces quit rather
7951 than doing recursive callback to get user input. */
7953 terminate_flag = true;
7955 /* Fkill_emacs doesn't return. We have to return. (TI) */
7956 return noErr;
7960 #if __profile__
7961 void
7962 profiler_exit_proc ()
7964 ProfilerDump ("\pEmacs.prof");
7965 ProfilerTerm ();
7967 #endif
7969 /* These few functions implement Emacs as a normal Mac application
7970 (almost): set up the heap and the Toolbox, handle necessary
7971 system events plus a few simple menu events. They also set up
7972 Emacs's access to functions defined in the rest of this file.
7973 Emacs uses function hooks to perform all its terminal I/O. A
7974 complete list of these functions appear in termhooks.h. For what
7975 they do, read the comments there and see also w32term.c and
7976 xterm.c. What's noticeably missing here is the event loop, which
7977 is normally present in most Mac application. After performing the
7978 necessary Mac initializations, main passes off control to
7979 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7980 mac_read_socket (defined further below) to read input. This is
7981 where WaitNextEvent is called to process Mac events. This is also
7982 where check_alarm in sysdep.c is called to simulate alarm signals.
7983 This makes the cursor jump back to its correct position after
7984 briefly jumping to that of the matching parenthesis, print useful
7985 hints and prompts in the minibuffer after the user stops typing for
7986 a wait, etc. */
7988 #if !TARGET_API_MAC_CARBON
7989 #undef main
7991 main (void)
7993 #if __profile__ /* is the profiler on? */
7994 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
7995 exit(1);
7996 #endif
7998 #if __MWERKS__
7999 /* set creator and type for files created by MSL */
8000 _fcreator = 'EMAx';
8001 _ftype = 'TEXT';
8002 #endif
8004 do_init_managers ();
8006 do_get_menus ();
8008 #ifndef USE_LSB_TAG
8009 do_check_ram_size ();
8010 #endif
8012 init_emacs_passwd_dir ();
8014 init_environ ();
8016 initialize_applescript ();
8018 init_required_apple_events ();
8021 char **argv;
8022 int argc = 0;
8024 /* set up argv array from STR# resource */
8025 get_string_list (&argv, ARGV_STRING_LIST_ID);
8026 while (argv[argc])
8027 argc++;
8029 /* free up AppleScript resources on exit */
8030 atexit (terminate_applescript);
8032 #if __profile__ /* is the profiler on? */
8033 atexit (profiler_exit_proc);
8034 #endif
8036 /* 3rd param "envp" never used in emacs_main */
8037 (void) emacs_main (argc, argv, 0);
8040 /* Never reached - real exit in Fkill_emacs */
8041 return 0;
8043 #endif
8045 /* Table for translating Mac keycode to X keysym values. Contributed
8046 by Sudhir Shenoy. */
8047 static unsigned char keycode_to_xkeysym_table[] = {
8048 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8049 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8050 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8052 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8053 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8054 /*0x38*/ 0, 0, 0, 0,
8055 /*0x3C*/ 0, 0, 0, 0,
8057 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8058 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8059 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8060 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8062 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8063 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8064 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8065 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8067 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8068 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8069 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8070 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8072 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8073 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8074 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8075 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8078 static int
8079 keycode_to_xkeysym (int keyCode, int *xKeySym)
8081 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8082 return *xKeySym != 0;
8085 /* Emacs calls this whenever it wants to read an input event from the
8086 user. */
8088 XTread_socket (sd, expected, hold_quit)
8089 int sd, expected;
8090 struct input_event *hold_quit;
8092 struct input_event inev;
8093 int count = 0;
8094 #if USE_CARBON_EVENTS
8095 EventRef eventRef;
8096 EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget ();
8097 #else
8098 EventMask event_mask;
8099 #endif
8100 EventRecord er;
8101 struct mac_display_info *dpyinfo = &one_mac_display_info;
8103 if (interrupt_input_blocked)
8105 interrupt_input_pending = 1;
8106 return -1;
8109 interrupt_input_pending = 0;
8110 BLOCK_INPUT;
8112 /* So people can tell when we have read the available input. */
8113 input_signal_count++;
8115 /* Don't poll for events to process (specifically updateEvt) if
8116 window update currently already in progress. A call to redisplay
8117 (in do_window_update) can be preempted by another call to
8118 redisplay, causing blank regions to be left on the screen and the
8119 cursor to be left at strange places. */
8120 if (handling_window_update)
8122 UNBLOCK_INPUT;
8123 return 0;
8126 if (terminate_flag)
8127 Fkill_emacs (make_number (1));
8129 #if !USE_CARBON_EVENTS
8130 event_mask = everyEvent;
8131 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8132 event_mask -= highLevelEventMask;
8134 while (WaitNextEvent (event_mask, &er, 0L, NULL))
8135 #else /* USE_CARBON_EVENTS */
8136 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8137 kEventRemoveFromQueue, &eventRef))
8138 #endif /* USE_CARBON_EVENTS */
8140 int do_help = 0;
8141 struct frame *f;
8143 /* It is necessary to set this (additional) argument slot of an
8144 event to nil because keyboard.c protects incompletely
8145 processed event from being garbage collected by placing them
8146 in the kbd_buffer_gcpro vector. */
8147 EVENT_INIT (inev);
8148 inev.kind = NO_EVENT;
8149 inev.arg = Qnil;
8151 #if USE_CARBON_EVENTS
8152 /* Handle new events */
8153 if (!mac_convert_event_ref (eventRef, &er))
8154 switch (GetEventClass (eventRef))
8156 case kEventClassWindow:
8157 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8159 WindowPtr window_ptr;
8160 GetEventParameter(eventRef, kEventParamDirectObject,
8161 typeWindowRef, NULL, sizeof(WindowPtr),
8162 NULL, &window_ptr);
8163 f = mac_window_to_frame (window_ptr);
8164 if (f && !f->async_iconified)
8165 x_real_positions (f, &f->left_pos, &f->top_pos);
8166 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8168 break;
8169 case kEventClassMouse:
8170 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8172 SInt32 delta;
8173 Point point;
8174 WindowPtr window_ptr = front_emacs_window ();
8176 if (!IsValidWindowPtr (window_ptr))
8178 SysBeep(1);
8179 break;
8182 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8183 typeSInt32, NULL, sizeof (SInt32),
8184 NULL, &delta);
8185 GetEventParameter(eventRef, kEventParamMouseLocation,
8186 typeQDPoint, NULL, sizeof (Point),
8187 NULL, &point);
8188 inev.kind = WHEEL_EVENT;
8189 inev.code = 0;
8190 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8191 | ((delta < 0) ? down_modifier
8192 : up_modifier));
8193 SetPortWindowPort (window_ptr);
8194 GlobalToLocal (&point);
8195 XSETINT (inev.x, point.h);
8196 XSETINT (inev.y, point.v);
8197 XSETFRAME (inev.frame_or_window,
8198 mac_window_to_frame (window_ptr));
8199 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8201 else
8202 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8204 break;
8205 default:
8206 /* Send the event to the appropriate receiver. */
8207 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8209 else
8210 #endif /* USE_CARBON_EVENTS */
8211 switch (er.what)
8213 case mouseDown:
8214 case mouseUp:
8216 WindowPtr window_ptr;
8217 SInt16 part_code;
8218 int tool_bar_p = 0;
8220 #if USE_CARBON_EVENTS
8221 /* This is needed to send mouse events like aqua window
8222 buttons to the correct handler. */
8223 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8224 != eventNotHandledErr)
8225 break;
8226 #endif
8228 if (dpyinfo->grabbed && last_mouse_frame
8229 && FRAME_LIVE_P (last_mouse_frame))
8231 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8232 part_code = inContent;
8234 else
8236 part_code = FindWindow (er.where, &window_ptr);
8237 if (tip_window && window_ptr == tip_window)
8239 HideWindow (tip_window);
8240 part_code = FindWindow (er.where, &window_ptr);
8244 if (er.what != mouseDown && part_code != inContent)
8245 break;
8247 switch (part_code)
8249 case inMenuBar:
8250 f = mac_window_to_frame (front_emacs_window ());
8251 saved_menu_event_location = er.where;
8252 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8253 XSETFRAME (inev.frame_or_window, f);
8254 break;
8256 case inContent:
8257 if (window_ptr != front_emacs_window ())
8258 SelectWindow (window_ptr);
8259 else
8261 SInt16 control_part_code;
8262 ControlHandle ch;
8263 Point mouse_loc = er.where;
8265 f = mac_window_to_frame (window_ptr);
8266 /* convert to local coordinates of new window */
8267 SetPortWindowPort (window_ptr);
8269 GlobalToLocal (&mouse_loc);
8270 #if TARGET_API_MAC_CARBON
8271 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8272 &control_part_code);
8273 #else
8274 control_part_code = FindControl (mouse_loc, window_ptr,
8275 &ch);
8276 #endif
8278 #if USE_CARBON_EVENTS
8279 inev.code = mac_get_mouse_btn (eventRef);
8280 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8281 #else
8282 inev.code = mac_get_emulated_btn (er.modifiers);
8283 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8284 #endif
8285 XSETINT (inev.x, mouse_loc.h);
8286 XSETINT (inev.y, mouse_loc.v);
8287 inev.timestamp = er.when * (1000 / 60);
8288 /* ticks to milliseconds */
8290 if (dpyinfo->grabbed && tracked_scroll_bar
8291 #if TARGET_API_MAC_CARBON
8292 || ch != 0
8293 #else
8294 || control_part_code != 0
8295 #endif
8298 struct scroll_bar *bar;
8300 if (dpyinfo->grabbed && tracked_scroll_bar)
8302 bar = tracked_scroll_bar;
8303 control_part_code = kControlIndicatorPart;
8305 else
8306 bar = (struct scroll_bar *) GetControlReference (ch);
8307 x_scroll_bar_handle_click (bar, control_part_code,
8308 &er, &inev);
8309 if (er.what == mouseDown
8310 && control_part_code == kControlIndicatorPart)
8311 tracked_scroll_bar = bar;
8312 else
8313 tracked_scroll_bar = NULL;
8315 else
8317 Lisp_Object window;
8318 int x = mouse_loc.h;
8319 int y = mouse_loc.v;
8321 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8322 if (EQ (window, f->tool_bar_window))
8324 if (er.what == mouseDown)
8325 handle_tool_bar_click (f, x, y, 1, 0);
8326 else
8327 handle_tool_bar_click (f, x, y, 0,
8328 inev.modifiers);
8329 tool_bar_p = 1;
8331 else
8333 XSETFRAME (inev.frame_or_window, f);
8334 inev.kind = MOUSE_CLICK_EVENT;
8338 if (er.what == mouseDown)
8340 dpyinfo->grabbed |= (1 << inev.code);
8341 last_mouse_frame = f;
8342 /* Ignore any mouse motion that happened
8343 before this event; any subsequent
8344 mouse-movement Emacs events should reflect
8345 only motion after the ButtonPress. */
8346 if (f != 0)
8347 f->mouse_moved = 0;
8349 if (!tool_bar_p)
8350 last_tool_bar_item = -1;
8352 else
8354 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8355 /* If a button is released though it was not
8356 previously pressed, that would be because
8357 of multi-button emulation. */
8358 dpyinfo->grabbed = 0;
8359 else
8360 dpyinfo->grabbed &= ~(1 << inev.code);
8363 switch (er.what)
8365 case mouseDown:
8366 inev.modifiers |= down_modifier;
8367 break;
8368 case mouseUp:
8369 inev.modifiers |= up_modifier;
8370 break;
8373 break;
8375 case inDrag:
8376 #if TARGET_API_MAC_CARBON
8377 DragWindow (window_ptr, er.where, NULL);
8378 #else /* not TARGET_API_MAC_CARBON */
8379 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8380 #endif /* not TARGET_API_MAC_CARBON */
8381 /* Update the frame parameters. */
8383 struct frame *f = mac_window_to_frame (window_ptr);
8385 if (f && !f->async_iconified)
8386 x_real_positions (f, &f->left_pos, &f->top_pos);
8388 break;
8390 case inGoAway:
8391 if (TrackGoAway (window_ptr, er.where))
8393 inev.kind = DELETE_WINDOW_EVENT;
8394 XSETFRAME (inev.frame_or_window,
8395 mac_window_to_frame (window_ptr));
8397 break;
8399 /* window resize handling added --ben */
8400 case inGrow:
8401 do_grow_window (window_ptr, &er);
8402 break;
8404 /* window zoom handling added --ben */
8405 case inZoomIn:
8406 case inZoomOut:
8407 if (TrackBox (window_ptr, er.where, part_code))
8408 do_zoom_window (window_ptr, part_code);
8409 break;
8411 default:
8412 break;
8415 break;
8417 case updateEvt:
8418 #if USE_CARBON_EVENTS
8419 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8420 != eventNotHandledErr)
8421 break;
8422 #endif
8423 do_window_update ((WindowPtr) er.message);
8424 break;
8426 case osEvt:
8427 #if USE_CARBON_EVENTS
8428 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8429 != eventNotHandledErr)
8430 break;
8431 #endif
8432 switch ((er.message >> 24) & 0x000000FF)
8434 case suspendResumeMessage:
8435 if ((er.message & resumeFlag) == 1)
8436 do_app_resume ();
8437 else
8438 do_app_suspend ();
8439 break;
8441 case mouseMovedMessage:
8442 previous_help_echo_string = help_echo_string;
8443 help_echo_string = help_echo_object = help_echo_window = Qnil;
8444 help_echo_pos = -1;
8446 do_mouse_moved (er.where, &f);
8448 /* If the contents of the global variable
8449 help_echo_string has changed, generate a
8450 HELP_EVENT. */
8451 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8452 do_help = 1;
8453 break;
8455 break;
8457 case activateEvt:
8459 WindowPtr window_ptr = (WindowPtr) er.message;
8461 #if USE_CARBON_EVENTS
8462 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8463 != eventNotHandledErr)
8464 break;
8465 #endif
8466 if (window_ptr == tip_window)
8468 HideWindow (tip_window);
8469 break;
8472 if (!is_emacs_window (window_ptr))
8473 break;
8475 f = mac_window_to_frame (window_ptr);
8477 if ((er.modifiers & activeFlag) != 0)
8479 /* A window has been activated */
8480 Point mouse_loc = er.where;
8482 x_new_focus_frame (dpyinfo, f);
8483 activate_scroll_bars (f);
8485 SetPortWindowPort (window_ptr);
8486 GlobalToLocal (&mouse_loc);
8487 /* Window-activated event counts as mouse movement,
8488 so update things that depend on mouse position. */
8489 note_mouse_movement (mac_window_to_frame (window_ptr),
8490 &mouse_loc);
8492 else
8494 /* A window has been deactivated */
8495 dpyinfo->grabbed = 0;
8497 if (f == dpyinfo->x_focus_frame)
8499 x_new_focus_frame (dpyinfo, 0);
8500 deactivate_scroll_bars (f);
8504 if (f == dpyinfo->mouse_face_mouse_frame)
8506 /* If we move outside the frame, then we're
8507 certainly no longer on any text in the
8508 frame. */
8509 clear_mouse_face (dpyinfo);
8510 dpyinfo->mouse_face_mouse_frame = 0;
8513 /* Generate a nil HELP_EVENT to cancel a help-echo.
8514 Do it only if there's something to cancel.
8515 Otherwise, the startup message is cleared when the
8516 mouse leaves the frame. */
8517 if (any_help_event_p)
8518 do_help = -1;
8521 break;
8523 case keyDown:
8524 case autoKey:
8526 int keycode = (er.message & keyCodeMask) >> 8;
8527 int xkeysym;
8529 #if USE_CARBON_EVENTS
8530 /* When using Carbon Events, we need to pass raw keyboard
8531 events to the TSM ourselves. If TSM handles it, it
8532 will pass back noErr, otherwise it will pass back
8533 "eventNotHandledErr" and we can process it
8534 normally. */
8535 if ((!NILP (Vmac_pass_command_to_system)
8536 || !(er.modifiers & cmdKey))
8537 && (!NILP (Vmac_pass_control_to_system)
8538 || !(er.modifiers & controlKey)))
8539 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8540 != eventNotHandledErr)
8541 break;
8542 #endif
8544 #if TARGET_API_MAC_CARBON
8545 if (!IsValidWindowPtr (front_emacs_window ()))
8547 SysBeep (1);
8548 break;
8550 #endif
8552 ObscureCursor ();
8554 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8556 clear_mouse_face (dpyinfo);
8557 dpyinfo->mouse_face_hidden = 1;
8560 if (keycode_to_xkeysym (keycode, &xkeysym))
8562 inev.code = 0xff00 | xkeysym;
8563 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8565 else
8567 if (er.modifiers & (controlKey |
8568 (NILP (Vmac_command_key_is_meta) ? optionKey
8569 : cmdKey)))
8571 /* This code comes from Keyboard Resource,
8572 Appendix C of IM - Text. This is necessary
8573 since shift is ignored in KCHR table
8574 translation when option or command is pressed.
8575 It also does not translate correctly
8576 control-shift chars like C-% so mask off shift
8577 here also */
8578 int new_modifiers = er.modifiers & 0xe600;
8579 /* mask off option and command */
8580 int new_keycode = keycode | new_modifiers;
8581 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8582 unsigned long some_state = 0;
8583 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8584 &some_state) & 0xff;
8585 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
8587 /* When using the option key as an emacs modifier, convert
8588 the pressed key code back to one without the Mac option
8589 modifier applied. */
8590 int new_modifiers = er.modifiers & ~optionKey;
8591 int new_keycode = keycode | new_modifiers;
8592 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8593 unsigned long some_state = 0;
8594 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8595 &some_state) & 0xff;
8597 else
8598 inev.code = er.message & charCodeMask;
8599 inev.kind = ASCII_KEYSTROKE_EVENT;
8603 /* If variable mac-convert-keyboard-input-to-latin-1 is
8604 non-nil, convert non-ASCII characters typed at the Mac
8605 keyboard (presumed to be in the Mac Roman encoding) to
8606 iso-latin-1 encoding before they are passed to Emacs.
8607 This enables the Mac keyboard to be used to enter
8608 non-ASCII iso-latin-1 characters directly. */
8609 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
8610 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
8612 static TECObjectRef converter = NULL;
8613 OSStatus the_err = noErr;
8614 OSStatus convert_status = noErr;
8616 if (converter == NULL)
8618 the_err = TECCreateConverter (&converter,
8619 kTextEncodingMacRoman,
8620 mac_keyboard_text_encoding);
8621 current_mac_keyboard_text_encoding
8622 = mac_keyboard_text_encoding;
8624 else if (mac_keyboard_text_encoding
8625 != current_mac_keyboard_text_encoding)
8627 /* Free the converter for the current encoding
8628 before creating a new one. */
8629 TECDisposeConverter (converter);
8630 the_err = TECCreateConverter (&converter,
8631 kTextEncodingMacRoman,
8632 mac_keyboard_text_encoding);
8633 current_mac_keyboard_text_encoding
8634 = mac_keyboard_text_encoding;
8637 if (the_err == noErr)
8639 unsigned char ch = inev.code;
8640 ByteCount actual_input_length, actual_output_length;
8641 unsigned char outbuf[32];
8643 convert_status = TECConvertText (converter, &ch, 1,
8644 &actual_input_length,
8645 outbuf, 1,
8646 &actual_output_length);
8647 if (convert_status == noErr
8648 && actual_input_length == 1
8649 && actual_output_length == 1)
8650 inev.code = *outbuf;
8652 /* Reset internal states of the converter object.
8653 If it fails, create another one. */
8654 convert_status = TECFlushText (converter, outbuf,
8655 sizeof (outbuf),
8656 &actual_output_length);
8657 if (convert_status != noErr)
8659 TECDisposeConverter (converter);
8660 TECCreateConverter (&converter,
8661 kTextEncodingMacRoman,
8662 mac_keyboard_text_encoding);
8667 #if USE_CARBON_EVENTS
8668 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8669 #else
8670 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8671 #endif
8672 XSETFRAME (inev.frame_or_window,
8673 mac_window_to_frame (front_emacs_window ()));
8674 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8675 break;
8677 case kHighLevelEvent:
8678 drag_and_drop_file_list = Qnil;
8680 AEProcessAppleEvent(&er);
8682 /* Build a DRAG_N_DROP_EVENT type event as is done in
8683 constuct_drag_n_drop in w32term.c. */
8684 if (!NILP (drag_and_drop_file_list))
8686 struct frame *f = NULL;
8687 WindowPtr wp;
8688 Lisp_Object frame;
8690 wp = front_emacs_window ();
8692 if (!wp)
8694 struct frame *f = XFRAME (XCAR (Vframe_list));
8695 CollapseWindow (FRAME_MAC_WINDOW (f), false);
8696 wp = front_emacs_window ();
8699 if (wp)
8700 f = mac_window_to_frame (wp);
8702 inev.kind = DRAG_N_DROP_EVENT;
8703 inev.code = 0;
8704 inev.timestamp = er.when * (1000 / 60);
8705 /* ticks to milliseconds */
8706 #if USE_CARBON_EVENTS
8707 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8708 #else
8709 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8710 #endif
8712 XSETINT (inev.x, 0);
8713 XSETINT (inev.y, 0);
8715 XSETFRAME (frame, f);
8716 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8718 /* Regardless of whether Emacs was suspended or in the
8719 foreground, ask it to redraw its entire screen.
8720 Otherwise parts of the screen can be left in an
8721 inconsistent state. */
8722 if (wp)
8723 #if TARGET_API_MAC_CARBON
8725 Rect r;
8727 GetWindowPortBounds (wp, &r);
8728 InvalWindowRect (wp, &r);
8730 #else /* not TARGET_API_MAC_CARBON */
8731 InvalRect (&(wp->portRect));
8732 #endif /* not TARGET_API_MAC_CARBON */
8734 default:
8735 break;
8737 #if USE_CARBON_EVENTS
8738 ReleaseEvent (eventRef);
8739 #endif
8741 if (inev.kind != NO_EVENT)
8743 kbd_buffer_store_event_hold (&inev, hold_quit);
8744 count++;
8747 if (do_help
8748 && !(hold_quit && hold_quit->kind != NO_EVENT))
8750 Lisp_Object frame;
8752 if (f)
8753 XSETFRAME (frame, f);
8754 else
8755 frame = Qnil;
8757 if (do_help > 0)
8759 any_help_event_p = 1;
8760 gen_help_event (help_echo_string, frame, help_echo_window,
8761 help_echo_object, help_echo_pos);
8763 else
8765 help_echo_string = Qnil;
8766 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
8768 count++;
8773 /* If the focus was just given to an autoraising frame,
8774 raise it now. */
8775 /* ??? This ought to be able to handle more than one such frame. */
8776 if (pending_autoraise_frame)
8778 x_raise_frame (pending_autoraise_frame);
8779 pending_autoraise_frame = 0;
8782 #if !TARGET_API_MAC_CARBON
8783 check_alarm (); /* simulate the handling of a SIGALRM */
8784 #endif
8786 UNBLOCK_INPUT;
8787 return count;
8791 /* Need to override CodeWarrior's input function so no conversion is
8792 done on newlines Otherwise compiled functions in .elc files will be
8793 read incorrectly. Defined in ...:MSL C:MSL
8794 Common:Source:buffer_io.c. */
8795 #ifdef __MWERKS__
8796 void
8797 __convert_to_newlines (unsigned char * p, size_t * n)
8799 #pragma unused(p,n)
8802 void
8803 __convert_from_newlines (unsigned char * p, size_t * n)
8805 #pragma unused(p,n)
8807 #endif
8810 /* Initialize the struct pointed to by MW to represent a new COLS x
8811 ROWS Macintosh window, using font with name FONTNAME and size
8812 FONTSIZE. */
8813 void
8814 make_mac_frame (FRAME_PTR fp)
8816 mac_output *mwp;
8817 #if TARGET_API_MAC_CARBON
8818 static int making_terminal_window = 0;
8819 #else
8820 static int making_terminal_window = 1;
8821 #endif
8823 mwp = fp->output_data.mac;
8825 BLOCK_INPUT;
8826 if (making_terminal_window)
8828 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
8829 (WindowPtr) -1)))
8830 abort ();
8831 making_terminal_window = 0;
8833 else
8835 #if TARGET_API_MAC_CARBON
8836 Rect r;
8838 SetRect (&r, 0, 0, 1, 1);
8839 if (CreateNewWindow (kDocumentWindowClass,
8840 kWindowStandardDocumentAttributes
8841 /* | kWindowToolbarButtonAttribute */,
8842 &r, &mwp->mWP) != noErr)
8843 #else
8844 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
8845 #endif
8846 abort ();
8849 SetWRefCon (mwp->mWP, (long) mwp);
8850 /* so that update events can find this mac_output struct */
8851 mwp->mFP = fp; /* point back to emacs frame */
8853 SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
8854 UNBLOCK_INPUT;
8858 void
8859 make_mac_terminal_frame (struct frame *f)
8861 Lisp_Object frame;
8863 XSETFRAME (frame, f);
8865 f->output_method = output_mac;
8866 f->output_data.mac = (struct mac_output *)
8867 xmalloc (sizeof (struct mac_output));
8868 bzero (f->output_data.mac, sizeof (struct mac_output));
8870 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8872 FRAME_COLS (f) = 96;
8873 FRAME_LINES (f) = 4;
8875 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8876 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8878 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8880 f->output_data.mac->cursor_pixel = 0;
8881 f->output_data.mac->border_pixel = 0x00ff00;
8882 f->output_data.mac->mouse_pixel = 0xff00ff;
8883 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
8885 FRAME_FONTSET (f) = -1;
8886 f->output_data.mac->explicit_parent = 0;
8887 f->left_pos = 4;
8888 f->top_pos = 4;
8889 f->border_width = 0;
8891 f->internal_border_width = 0;
8893 f->auto_raise = 1;
8894 f->auto_lower = 1;
8896 f->new_text_cols = 0;
8897 f->new_text_lines = 0;
8899 make_mac_frame (f);
8901 x_make_gc (f);
8903 /* Need to be initialized for unshow_buffer in window.c. */
8904 selected_window = f->selected_window;
8906 Fmodify_frame_parameters (frame,
8907 Fcons (Fcons (Qfont,
8908 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
8909 Fmodify_frame_parameters (frame,
8910 Fcons (Fcons (Qforeground_color,
8911 build_string ("black")), Qnil));
8912 Fmodify_frame_parameters (frame,
8913 Fcons (Fcons (Qbackground_color,
8914 build_string ("white")), Qnil));
8916 ShowWindow (f->output_data.mac->mWP);
8920 /***********************************************************************
8921 Initialization
8922 ***********************************************************************/
8924 int mac_initialized = 0;
8926 void
8927 mac_initialize_display_info ()
8929 struct mac_display_info *dpyinfo = &one_mac_display_info;
8930 GDHandle main_device_handle;
8932 bzero (dpyinfo, sizeof (*dpyinfo));
8934 /* Put it on x_display_name_list. */
8935 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
8936 x_display_name_list);
8937 dpyinfo->name_list_element = XCAR (x_display_name_list);
8939 #if 0
8940 dpyinfo->mac_id_name
8941 = (char *) xmalloc (SCHARS (Vinvocation_name)
8942 + SCHARS (Vsystem_name)
8943 + 2);
8944 sprintf (dpyinfo->mac_id_name, "%s@%s",
8945 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8946 #else
8947 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
8948 strcpy (dpyinfo->mac_id_name, "Mac Display");
8949 #endif
8951 main_device_handle = LMGetMainDevice();
8953 dpyinfo->reference_count = 0;
8954 dpyinfo->resx = 75.0;
8955 dpyinfo->resy = 75.0;
8956 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
8957 #ifdef MAC_OSX
8958 /* HasDepth returns true if it is possible to have a 32 bit display,
8959 but this may not be what is actually used. Mac OSX can do better.
8960 CGMainDisplayID is only available on OSX 10.2 and higher, but the
8961 header for CGGetActiveDisplayList says that the first display returned
8962 is the active one, so we use that. */
8964 CGDirectDisplayID disp_id[1];
8965 CGDisplayCount disp_count;
8966 CGDisplayErr error_code;
8968 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
8969 if (error_code != 0)
8970 error ("No display found, CGGetActiveDisplayList error %d", error_code);
8972 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
8974 #else
8975 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
8976 if (HasDepth (main_device_handle, dpyinfo->n_planes,
8977 gdDevType, dpyinfo->color_p))
8978 break;
8979 #endif
8980 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8981 dpyinfo->width = (**main_device_handle).gdRect.right;
8982 dpyinfo->grabbed = 0;
8983 dpyinfo->root_window = NULL;
8984 dpyinfo->image_cache = make_image_cache ();
8986 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8987 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8988 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8989 dpyinfo->mouse_face_window = Qnil;
8990 dpyinfo->mouse_face_overlay = Qnil;
8991 dpyinfo->mouse_face_hidden = 0;
8994 struct mac_display_info *
8995 mac_term_init (display_name, xrm_option, resource_name)
8996 Lisp_Object display_name;
8997 char *xrm_option;
8998 char *resource_name;
9000 struct mac_display_info *dpyinfo;
9001 GDHandle main_device_handle;
9003 if (!mac_initialized)
9005 mac_initialize ();
9006 mac_initialized = 1;
9009 mac_initialize_display_info (display_name);
9011 dpyinfo = &one_mac_display_info;
9013 main_device_handle = LMGetMainDevice();
9015 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9016 dpyinfo->width = (**main_device_handle).gdRect.right;
9018 return dpyinfo;
9021 #ifdef MAC_OSX
9022 void
9023 mac_check_bundle()
9025 extern int inhibit_window_system;
9026 extern int noninteractive;
9027 CFBundleRef appsBundle;
9028 pid_t child;
9030 /* No need to test if already -nw*/
9031 if (inhibit_window_system || noninteractive)
9032 return;
9034 appsBundle = CFBundleGetMainBundle();
9035 if (appsBundle != NULL)
9037 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9038 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9039 /* We found the bundle identifier, now we know we are valid. */
9040 if (res != NULL)
9042 CFRelease(res);
9043 return;
9046 /* MAC_TODO: Have this start the bundled executable */
9048 /* For now, prevent the fatal error by bringing it up in the terminal */
9049 inhibit_window_system = 1;
9052 void
9053 MakeMeTheFrontProcess ()
9055 ProcessSerialNumber psn;
9056 OSErr err;
9058 err = GetCurrentProcess (&psn);
9059 if (err == noErr)
9060 (void) SetFrontProcess (&psn);
9063 /***** Code to handle C-g testing *****/
9065 /* Contains the Mac modifier formed from quit_char */
9066 static mac_quit_char_modifiers = 0;
9067 static mac_quit_char_keycode;
9068 extern int quit_char;
9070 static void
9071 mac_determine_quit_char_modifiers()
9073 /* Todo: Determine modifiers from quit_char. */
9074 UInt32 qc_modifiers = ctrl_modifier;
9076 /* Map modifiers */
9077 mac_quit_char_modifiers = 0;
9078 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9079 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9080 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9081 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9084 static void
9085 init_quit_char_handler ()
9087 /* TODO: Let this support keys other the 'g' */
9088 mac_quit_char_keycode = 5;
9089 /* Look at <architecture/adb_kb_map.h> for details */
9090 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9092 mac_determine_quit_char_modifiers();
9095 static Boolean
9096 quit_char_comp (EventRef inEvent, void *inCompData)
9098 if (GetEventClass(inEvent) != kEventClassKeyboard)
9099 return false;
9100 if (GetEventKind(inEvent) != kEventRawKeyDown)
9101 return false;
9103 UInt32 keyCode;
9104 UInt32 keyModifiers;
9105 GetEventParameter(inEvent, kEventParamKeyCode,
9106 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9107 if (keyCode != mac_quit_char_keycode)
9108 return false;
9109 GetEventParameter(inEvent, kEventParamKeyModifiers,
9110 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9111 if (keyModifiers != mac_quit_char_modifiers)
9112 return false;
9114 return true;
9117 void
9118 mac_check_for_quit_char ()
9120 EventRef event;
9121 static EMACS_TIME last_check_time = { 0, 0 };
9122 static EMACS_TIME one_second = { 1, 0 };
9123 EMACS_TIME now, t;
9125 /* If windows are not initialized, return immediately (keep it bouncin'). */
9126 if (!mac_quit_char_modifiers)
9127 return;
9129 /* Don't check if last check is less than a second ago. */
9130 EMACS_GET_TIME (now);
9131 EMACS_SUB_TIME (t, now, last_check_time);
9132 if (EMACS_TIME_LT (t, one_second))
9133 return;
9134 last_check_time = now;
9136 /* Redetermine modifiers because they are based on lisp variables */
9137 mac_determine_quit_char_modifiers ();
9139 /* Fill the queue with events */
9140 BLOCK_INPUT;
9141 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9142 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9143 NULL);
9144 UNBLOCK_INPUT;
9145 if (event)
9147 struct input_event e;
9149 /* Use an input_event to emulate what the interrupt handler does. */
9150 EVENT_INIT (e);
9151 e.kind = ASCII_KEYSTROKE_EVENT;
9152 e.code = quit_char;
9153 e.arg = Qnil;
9154 e.modifiers = NULL;
9155 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9156 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9157 /* Remove event from queue to prevent looping. */
9158 RemoveEventFromQueue (GetMainEventQueue (), event);
9159 ReleaseEvent (event);
9160 kbd_buffer_store_event (&e);
9164 #endif /* MAC_OSX */
9166 /* Set up use of X before we make the first connection. */
9168 extern frame_parm_handler mac_frame_parm_handlers[];
9170 static struct redisplay_interface x_redisplay_interface =
9172 mac_frame_parm_handlers,
9173 x_produce_glyphs,
9174 x_write_glyphs,
9175 x_insert_glyphs,
9176 x_clear_end_of_line,
9177 x_scroll_run,
9178 x_after_update_window_line,
9179 x_update_window_begin,
9180 x_update_window_end,
9181 x_cursor_to,
9182 x_flush,
9183 0, /* flush_display_optional */
9184 x_clear_window_mouse_face,
9185 x_get_glyph_overhangs,
9186 x_fix_overlapping_area,
9187 x_draw_fringe_bitmap,
9188 0, /* define_fringe_bitmap */
9189 0, /* destroy_fringe_bitmap */
9190 mac_per_char_metric,
9191 mac_encode_char,
9192 NULL, /* mac_compute_glyph_string_overhangs */
9193 x_draw_glyph_string,
9194 mac_define_frame_cursor,
9195 mac_clear_frame_area,
9196 mac_draw_window_cursor,
9197 mac_draw_vertical_window_border,
9198 mac_shift_glyphs_for_insert
9201 void
9202 mac_initialize ()
9204 rif = &x_redisplay_interface;
9206 clear_frame_hook = x_clear_frame;
9207 ins_del_lines_hook = x_ins_del_lines;
9208 delete_glyphs_hook = x_delete_glyphs;
9209 ring_bell_hook = XTring_bell;
9210 reset_terminal_modes_hook = XTreset_terminal_modes;
9211 set_terminal_modes_hook = XTset_terminal_modes;
9212 update_begin_hook = x_update_begin;
9213 update_end_hook = x_update_end;
9214 set_terminal_window_hook = XTset_terminal_window;
9215 read_socket_hook = XTread_socket;
9216 frame_up_to_date_hook = XTframe_up_to_date;
9217 mouse_position_hook = XTmouse_position;
9218 frame_rehighlight_hook = XTframe_rehighlight;
9219 frame_raise_lower_hook = XTframe_raise_lower;
9221 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9222 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9223 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9224 judge_scroll_bars_hook = XTjudge_scroll_bars;
9226 scroll_region_ok = 1; /* we'll scroll partial frames */
9227 char_ins_del_ok = 1;
9228 line_ins_del_ok = 1; /* we'll just blt 'em */
9229 fast_clear_end_of_line = 1; /* X does this well */
9230 memory_below_frame = 0; /* we don't remember what scrolls
9231 off the bottom */
9232 baud_rate = 19200;
9234 x_noop_count = 0;
9235 last_tool_bar_item = -1;
9236 any_help_event_p = 0;
9238 /* Try to use interrupt input; if we can't, then start polling. */
9239 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9241 #ifdef USE_X_TOOLKIT
9242 XtToolkitInitialize ();
9243 Xt_app_con = XtCreateApplicationContext ();
9244 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9246 /* Install an asynchronous timer that processes Xt timeout events
9247 every 0.1s. This is necessary because some widget sets use
9248 timeouts internally, for example the LessTif menu bar, or the
9249 Xaw3d scroll bar. When Xt timouts aren't processed, these
9250 widgets don't behave normally. */
9252 EMACS_TIME interval;
9253 EMACS_SET_SECS_USECS (interval, 0, 100000);
9254 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9256 #endif
9258 #if USE_TOOLKIT_SCROLL_BARS
9259 xaw3d_arrow_scroll = False;
9260 xaw3d_pick_top = True;
9261 #endif
9263 #if 0
9264 /* Note that there is no real way portable across R3/R4 to get the
9265 original error handler. */
9266 XSetErrorHandler (x_error_handler);
9267 XSetIOErrorHandler (x_io_error_quitter);
9269 /* Disable Window Change signals; they are handled by X events. */
9270 #ifdef SIGWINCH
9271 signal (SIGWINCH, SIG_DFL);
9272 #endif /* ! defined (SIGWINCH) */
9274 signal (SIGPIPE, x_connection_signal);
9275 #endif
9277 BLOCK_INPUT;
9278 mac_initialize_display_info ();
9280 #if TARGET_API_MAC_CARBON
9281 init_required_apple_events ();
9283 init_mac_drag_n_drop ();
9285 #if USE_CARBON_EVENTS
9286 init_service_handler ();
9288 init_quit_char_handler ();
9289 #endif
9291 DisableMenuCommand (NULL, kHICommandQuit);
9293 if (!inhibit_window_system)
9294 MakeMeTheFrontProcess ();
9295 #endif
9296 UNBLOCK_INPUT;
9300 void
9301 syms_of_macterm ()
9303 #if 0
9304 staticpro (&x_error_message_string);
9305 x_error_message_string = Qnil;
9306 #endif
9308 Qmodifier_value = intern ("modifier-value");
9309 Qalt = intern ("alt");
9310 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9311 Qhyper = intern ("hyper");
9312 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9313 Qsuper = intern ("super");
9314 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9316 Fprovide (intern ("mac-carbon"), Qnil);
9318 staticpro (&Qreverse);
9319 Qreverse = intern ("reverse");
9321 staticpro (&x_display_name_list);
9322 x_display_name_list = Qnil;
9324 staticpro (&last_mouse_scroll_bar);
9325 last_mouse_scroll_bar = Qnil;
9327 staticpro (&Qvendor_specific_keysyms);
9328 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9330 staticpro (&last_mouse_press_frame);
9331 last_mouse_press_frame = Qnil;
9333 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9334 staticpro (&Qmac_ready_for_drag_n_drop);
9336 Qbig5 = intern ("big5");
9337 staticpro (&Qbig5);
9339 Qcn_gb = intern ("cn-gb");
9340 staticpro (&Qcn_gb);
9342 Qsjis = intern ("sjis");
9343 staticpro (&Qsjis);
9345 Qeuc_kr = intern ("euc-kr");
9346 staticpro (&Qeuc_kr);
9348 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9349 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9350 x_autoselect_window_p = 0;
9352 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9353 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9354 Vx_toolkit_scroll_bars = Qt;
9356 DEFVAR_BOOL ("x-use-underline-position-properties",
9357 &x_use_underline_position_properties,
9358 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9359 nil means ignore them. If you encounter fonts with bogus
9360 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9361 to 4.1, set this to nil. */);
9362 x_use_underline_position_properties = 0;
9364 staticpro (&last_mouse_motion_frame);
9365 last_mouse_motion_frame = Qnil;
9367 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9368 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9369 Otherwise the option key is used. */);
9370 Vmac_command_key_is_meta = Qt;
9372 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9373 doc: /* Modifier to use for the Mac alt/option key. The value can
9374 be alt, hyper, or super for the respective modifier. If the value is
9375 nil then the key will act as the normal Mac option modifier. */);
9376 Vmac_option_modifier = Qnil;
9378 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9379 doc: /* Non-nil means that the control and meta keys are reversed. This is
9380 useful for non-standard keyboard layouts. */);
9381 Vmac_reverse_ctrl_meta = Qnil;
9383 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9384 &Vmac_emulate_three_button_mouse,
9385 doc: /* t means that when the option-key is held down while pressing the
9386 mouse button, the click will register as mouse-2 and while the
9387 command-key is held down, the click will register as mouse-3.
9388 'reverse means that the the option-key will register for mouse-3
9389 and the command-key will register for mouse-2. nil means that
9390 not emulation should be done and the modifiers should be placed
9391 on the mouse-1 event. */);
9392 Vmac_emulate_three_button_mouse = Qnil;
9394 #if USE_CARBON_EVENTS
9395 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9396 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9397 the right click will be mouse-3.
9398 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9399 Vmac_wheel_button_is_mouse_2 = Qt;
9401 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9402 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9403 Toolbox for processing before Emacs sees it. */);
9404 Vmac_pass_command_to_system = Qt;
9406 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9407 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9408 Toolbox for processing before Emacs sees it. */);
9409 Vmac_pass_control_to_system = Qt;
9410 #endif
9412 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9413 doc: /* One of the Text Encoding Base constant values defined in the
9414 Basic Text Constants section of Inside Macintosh - Text Encoding
9415 Conversion Manager. Its value determines the encoding characters
9416 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9417 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9418 its default value, no conversion takes place. If it is set to
9419 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9420 characters typed on Mac keyboard are first converted into the
9421 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9422 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9423 command, this enables the Mac keyboard to be used to enter non-ASCII
9424 characters directly. */);
9425 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9428 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9429 (do not change this comment) */