(Variable Definitions): Replace show-paren-mode example with tooltip-mode.
[emacs.git] / src / macterm.c
blobf4f9235c8464df4688204c9821b975c5c76343b1
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; /* not used */
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 static void
647 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
648 Display *display;
649 Pixmap p;
650 GC gc;
651 int x, y;
652 unsigned int width, height;
654 CGrafPtr old_port;
655 GDHandle old_gdh;
656 Rect r;
658 GetGWorld (&old_port, &old_gdh);
659 SetGWorld (p, NULL);
660 mac_set_colors (gc);
661 SetRect (&r, x, y, x + width, y + height);
663 LockPixels (GetGWorldPixMap (p));
664 PaintRect (&r); /* using foreground color of gc */
665 UnlockPixels (GetGWorldPixMap (p));
667 SetGWorld (old_port, old_gdh);
671 /* Mac replacement for XDrawRectangle: dest is a window. */
673 static void
674 mac_draw_rectangle (display, w, gc, x, y, width, height)
675 Display *display;
676 WindowPtr w;
677 GC gc;
678 int x, y;
679 unsigned int width, height;
681 Rect r;
683 SetPortWindowPort (w);
685 mac_set_colors (gc);
686 SetRect (&r, x, y, x + width + 1, y + height + 1);
688 FrameRect (&r); /* using foreground color of gc */
692 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
694 static void
695 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
696 Display *display;
697 Pixmap p;
698 GC gc;
699 int x, y;
700 unsigned int width, height;
702 CGrafPtr old_port;
703 GDHandle old_gdh;
704 Rect r;
706 GetGWorld (&old_port, &old_gdh);
707 SetGWorld (p, NULL);
708 mac_set_colors (gc);
709 SetRect (&r, x, y, x + width + 1, y + height + 1);
711 LockPixels (GetGWorldPixMap (p));
712 FrameRect (&r); /* using foreground color of gc */
713 UnlockPixels (GetGWorldPixMap (p));
715 SetGWorld (old_port, old_gdh);
719 static void
720 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
721 bytes_per_char)
722 Display *display;
723 WindowPtr w;
724 GC gc;
725 int x, y;
726 char *buf;
727 int nchars, mode, bytes_per_char;
729 SetPortWindowPort (w);
731 mac_set_colors (gc);
733 TextFont (gc->font->mac_fontnum);
734 TextSize (gc->font->mac_fontsize);
735 TextFace (gc->font->mac_fontface);
736 TextMode (mode);
738 MoveTo (x, y);
739 DrawText (buf, 0, nchars * bytes_per_char);
743 /* Mac replacement for XDrawString. */
745 static void
746 XDrawString (display, w, gc, x, y, buf, nchars)
747 Display *display;
748 WindowPtr w;
749 GC gc;
750 int x, y;
751 char *buf;
752 int nchars;
754 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
758 /* Mac replacement for XDrawString16. */
760 static void
761 XDrawString16 (display, w, gc, x, y, buf, nchars)
762 Display *display;
763 WindowPtr w;
764 GC gc;
765 int x, y;
766 XChar2b *buf;
767 int nchars;
769 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
774 /* Mac replacement for XDrawImageString. */
776 static void
777 XDrawImageString (display, w, gc, x, y, buf, nchars)
778 Display *display;
779 WindowPtr w;
780 GC gc;
781 int x, y;
782 char *buf;
783 int nchars;
785 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
789 /* Mac replacement for XDrawString16. */
791 static void
792 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
793 Display *display;
794 WindowPtr w;
795 GC gc;
796 int x, y;
797 XChar2b *buf;
798 int nchars;
800 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
805 /* Mac replacement for XCopyArea: dest must be window. */
807 static void
808 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
809 dest_y)
810 Display *display;
811 Pixmap src;
812 WindowPtr dest;
813 GC gc;
814 int src_x, src_y;
815 unsigned int width, height;
816 int dest_x, dest_y;
818 Rect src_r, dest_r;
820 SetPortWindowPort (dest);
822 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
823 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
825 ForeColor (blackColor);
826 BackColor (whiteColor);
828 LockPixels (GetGWorldPixMap (src));
829 #if TARGET_API_MAC_CARBON
830 LockPortBits (GetWindowPort (dest));
831 CopyBits (GetPortBitMapForCopyBits (src),
832 GetPortBitMapForCopyBits (GetWindowPort (dest)),
833 &src_r, &dest_r, srcCopy, 0);
834 UnlockPortBits (GetWindowPort (dest));
835 #else /* not TARGET_API_MAC_CARBON */
836 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
837 &src_r, &dest_r, srcCopy, 0);
838 #endif /* not TARGET_API_MAC_CARBON */
839 UnlockPixels (GetGWorldPixMap (src));
843 static void
844 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
845 width, height, dest_x, dest_y)
846 Display *display;
847 Pixmap src, mask;
848 WindowPtr dest;
849 GC gc;
850 int src_x, src_y;
851 unsigned int width, height;
852 int dest_x, dest_y;
854 Rect src_r, dest_r;
856 SetPortWindowPort (dest);
858 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
859 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
861 ForeColor (blackColor);
862 BackColor (whiteColor);
864 LockPixels (GetGWorldPixMap (src));
865 LockPixels (GetGWorldPixMap (mask));
866 #if TARGET_API_MAC_CARBON
867 LockPortBits (GetWindowPort (dest));
868 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
869 GetPortBitMapForCopyBits (GetWindowPort (dest)),
870 &src_r, &src_r, &dest_r);
871 UnlockPortBits (GetWindowPort (dest));
872 #else /* not TARGET_API_MAC_CARBON */
873 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
874 &(dest->portBits), &src_r, &src_r, &dest_r);
875 #endif /* not TARGET_API_MAC_CARBON */
876 UnlockPixels (GetGWorldPixMap (mask));
877 UnlockPixels (GetGWorldPixMap (src));
881 #if 0
882 /* Convert a pair of local coordinates to global (screen) coordinates.
883 Assume graphic port has been properly set. */
884 static void
885 local_to_global_coord (short *h, short *v)
887 Point p;
889 p.h = *h;
890 p.v = *v;
892 LocalToGlobal (&p);
894 *h = p.h;
895 *v = p.v;
897 #endif
899 /* Mac replacement for XCopyArea: used only for scrolling. */
901 static void
902 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
903 Display *display;
904 WindowPtr w;
905 GC gc;
906 int src_x, src_y;
907 unsigned int width, height;
908 int dest_x, dest_y;
910 #if TARGET_API_MAC_CARBON
911 Rect gw_r, src_r, dest_r;
913 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
914 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
916 SetPortWindowPort (w);
918 ForeColor (blackColor);
919 BackColor (whiteColor);
921 LockPortBits (GetWindowPort (w));
923 const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
924 CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
926 UnlockPortBits (GetWindowPort (w));
928 mac_set_colors (gc);
929 #else /* not TARGET_API_MAC_CARBON */
930 Rect src_r, dest_r;
932 SetPort (w);
933 #if 0
934 mac_set_colors (gc);
935 #endif
937 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
938 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
940 #if 0
941 /* Need to use global coordinates and screenBits since src and dest
942 areas overlap in general. */
943 local_to_global_coord (&src_r.left, &src_r.top);
944 local_to_global_coord (&src_r.right, &src_r.bottom);
945 local_to_global_coord (&dest_r.left, &dest_r.top);
946 local_to_global_coord (&dest_r.right, &dest_r.bottom);
948 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
949 #else
950 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
951 color mapping in CopyBits. Otherwise, it will be slow. */
952 ForeColor (blackColor);
953 BackColor (whiteColor);
954 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
956 mac_set_colors (gc);
957 #endif
958 #endif /* not TARGET_API_MAC_CARBON */
962 /* Mac replacement for XCopyArea: dest must be Pixmap. */
964 static void
965 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
966 dest_x, dest_y)
967 Display *display;
968 Pixmap src, dest;
969 GC gc;
970 int src_x, src_y;
971 unsigned int width, height;
972 int dest_x, dest_y;
974 CGrafPtr old_port;
975 GDHandle old_gdh;
976 Rect src_r, dest_r;
978 GetGWorld (&old_port, &old_gdh);
979 SetGWorld (dest, NULL);
980 ForeColor (blackColor);
981 BackColor (whiteColor);
983 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
984 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
986 LockPixels (GetGWorldPixMap (src));
987 LockPixels (GetGWorldPixMap (dest));
988 #if TARGET_API_MAC_CARBON
989 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
990 &src_r, &dest_r, srcCopy, 0);
991 #else /* not TARGET_API_MAC_CARBON */
992 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
993 &src_r, &dest_r, srcCopy, 0);
994 #endif /* not TARGET_API_MAC_CARBON */
995 UnlockPixels (GetGWorldPixMap (dest));
996 UnlockPixels (GetGWorldPixMap (src));
998 SetGWorld (old_port, old_gdh);
1002 static void
1003 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
1004 width, height, dest_x, dest_y)
1005 Display *display;
1006 Pixmap src, mask, dest;
1007 GC gc;
1008 int src_x, src_y;
1009 unsigned int width, height;
1010 int dest_x, dest_y;
1012 CGrafPtr old_port;
1013 GDHandle old_gdh;
1014 Rect src_r, dest_r;
1016 GetGWorld (&old_port, &old_gdh);
1017 SetGWorld (dest, NULL);
1018 ForeColor (blackColor);
1019 BackColor (whiteColor);
1021 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1022 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1024 LockPixels (GetGWorldPixMap (src));
1025 LockPixels (GetGWorldPixMap (mask));
1026 LockPixels (GetGWorldPixMap (dest));
1027 #if TARGET_API_MAC_CARBON
1028 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1029 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1030 #else /* not TARGET_API_MAC_CARBON */
1031 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1032 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1033 #endif /* not TARGET_API_MAC_CARBON */
1034 UnlockPixels (GetGWorldPixMap (dest));
1035 UnlockPixels (GetGWorldPixMap (mask));
1036 UnlockPixels (GetGWorldPixMap (src));
1038 SetGWorld (old_port, old_gdh);
1042 /* Mac replacement for XChangeGC. */
1044 static void
1045 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1046 XGCValues *xgcv)
1048 if (mask & GCForeground)
1049 gc->foreground = xgcv->foreground;
1050 if (mask & GCBackground)
1051 gc->background = xgcv->background;
1052 if (mask & GCFont)
1053 gc->font = xgcv->font;
1057 /* Mac replacement for XCreateGC. */
1059 XGCValues *
1060 XCreateGC (void * ignore, Window window, unsigned long mask,
1061 XGCValues *xgcv)
1063 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1064 bzero (gc, sizeof (XGCValues));
1066 XChangeGC (ignore, gc, mask, xgcv);
1068 return gc;
1072 /* Used in xfaces.c. */
1074 void
1075 XFreeGC (display, gc)
1076 Display *display;
1077 GC gc;
1079 xfree (gc);
1083 /* Mac replacement for XGetGCValues. */
1085 static void
1086 XGetGCValues (void* ignore, XGCValues *gc,
1087 unsigned long mask, XGCValues *xgcv)
1089 XChangeGC (ignore, xgcv, mask, gc);
1093 /* Mac replacement for XSetForeground. */
1095 void
1096 XSetForeground (display, gc, color)
1097 Display *display;
1098 GC gc;
1099 unsigned long color;
1101 gc->foreground = color;
1105 /* Mac replacement for XSetFont. */
1107 static void
1108 XSetFont (display, gc, font)
1109 Display *display;
1110 GC gc;
1111 XFontStruct *font;
1113 gc->font = font;
1117 static void
1118 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1119 int *direction,int *font_ascent,
1120 int *font_descent, XCharStruct *cs)
1122 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1126 /* x_sync is a no-op on Mac. */
1127 void
1128 x_sync (f)
1129 void *f;
1134 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1135 Calls to XFlush should be unnecessary because the X output buffer
1136 is flushed automatically as needed by calls to XPending,
1137 XNextEvent, or XWindowEvent according to the XFlush man page.
1138 XTread_socket calls XPending. Removing XFlush improves
1139 performance. */
1141 #if TARGET_API_MAC_CARBON
1142 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1143 #else
1144 #define XFlush(DISPLAY) (void) 0
1145 #endif
1147 /* Flush display of frame F, or of all frames if F is null. */
1149 void
1150 x_flush (f)
1151 struct frame *f;
1153 #if TARGET_API_MAC_CARBON
1154 BLOCK_INPUT;
1155 if (f == NULL)
1157 Lisp_Object rest, frame;
1158 FOR_EACH_FRAME (rest, frame)
1159 x_flush (XFRAME (frame));
1161 else if (FRAME_MAC_P (f))
1162 XFlush (FRAME_MAC_DISPLAY (f));
1163 UNBLOCK_INPUT;
1164 #endif /* TARGET_API_MAC_CARBON */
1169 /* Return the struct mac_display_info corresponding to DPY. There's
1170 only one. */
1172 struct mac_display_info *
1173 mac_display_info_for_display (dpy)
1174 Display *dpy;
1176 return &one_mac_display_info;
1181 /***********************************************************************
1182 Starting and ending an update
1183 ***********************************************************************/
1185 /* Start an update of frame F. This function is installed as a hook
1186 for update_begin, i.e. it is called when update_begin is called.
1187 This function is called prior to calls to x_update_window_begin for
1188 each window being updated. */
1190 static void
1191 x_update_begin (f)
1192 struct frame *f;
1194 /* Nothing to do. */
1198 /* Start update of window W. Set the global variable updated_window
1199 to the window being updated and set output_cursor to the cursor
1200 position of W. */
1202 static void
1203 x_update_window_begin (w)
1204 struct window *w;
1206 struct frame *f = XFRAME (WINDOW_FRAME (w));
1207 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1209 updated_window = w;
1210 set_output_cursor (&w->cursor);
1212 BLOCK_INPUT;
1214 if (f == display_info->mouse_face_mouse_frame)
1216 /* Don't do highlighting for mouse motion during the update. */
1217 display_info->mouse_face_defer = 1;
1219 /* If F needs to be redrawn, simply forget about any prior mouse
1220 highlighting. */
1221 if (FRAME_GARBAGED_P (f))
1222 display_info->mouse_face_window = Qnil;
1224 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1225 their mouse_face_p flag set, which means that they are always
1226 unequal to rows in a desired matrix which never have that
1227 flag set. So, rows containing mouse-face glyphs are never
1228 scrolled, and we don't have to switch the mouse highlight off
1229 here to prevent it from being scrolled. */
1231 /* Can we tell that this update does not affect the window
1232 where the mouse highlight is? If so, no need to turn off.
1233 Likewise, don't do anything if the frame is garbaged;
1234 in that case, the frame's current matrix that we would use
1235 is all wrong, and we will redisplay that line anyway. */
1236 if (!NILP (display_info->mouse_face_window)
1237 && w == XWINDOW (display_info->mouse_face_window))
1239 int i;
1241 for (i = 0; i < w->desired_matrix->nrows; ++i)
1242 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1243 break;
1245 if (i < w->desired_matrix->nrows)
1246 clear_mouse_face (display_info);
1248 #endif /* 0 */
1251 UNBLOCK_INPUT;
1255 /* Draw a vertical window border from (x,y0) to (x,y1) */
1257 static void
1258 mac_draw_vertical_window_border (w, x, y0, y1)
1259 struct window *w;
1260 int x, y0, y1;
1262 struct frame *f = XFRAME (WINDOW_FRAME (w));
1264 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1265 f->output_data.mac->normal_gc, x, y0, x, y1);
1269 /* End update of window W (which is equal to updated_window).
1271 Draw vertical borders between horizontally adjacent windows, and
1272 display W's cursor if CURSOR_ON_P is non-zero.
1274 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1275 glyphs in mouse-face were overwritten. In that case we have to
1276 make sure that the mouse-highlight is properly redrawn.
1278 W may be a menu bar pseudo-window in case we don't have X toolkit
1279 support. Such windows don't have a cursor, so don't display it
1280 here. */
1282 static void
1283 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1284 struct window *w;
1285 int cursor_on_p, mouse_face_overwritten_p;
1287 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1289 if (!w->pseudo_window_p)
1291 BLOCK_INPUT;
1293 if (cursor_on_p)
1294 display_and_set_cursor (w, 1, output_cursor.hpos,
1295 output_cursor.vpos,
1296 output_cursor.x, output_cursor.y);
1298 if (draw_window_fringes (w, 1))
1299 x_draw_vertical_border (w);
1301 UNBLOCK_INPUT;
1304 /* If a row with mouse-face was overwritten, arrange for
1305 XTframe_up_to_date to redisplay the mouse highlight. */
1306 if (mouse_face_overwritten_p)
1308 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1309 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1310 dpyinfo->mouse_face_window = Qnil;
1313 #if 0
1314 /* Unhide the caret. This won't actually show the cursor, unless it
1315 was visible before the corresponding call to HideCaret in
1316 x_update_window_begin. */
1317 if (w32_use_visible_system_caret)
1318 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1319 #endif
1321 updated_window = NULL;
1325 /* End update of frame F. This function is installed as a hook in
1326 update_end. */
1328 static void
1329 x_update_end (f)
1330 struct frame *f;
1332 /* Mouse highlight may be displayed again. */
1333 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1335 BLOCK_INPUT;
1336 /* Reset the background color of Mac OS Window to that of the frame after
1337 update so that it is used by Mac Toolbox to clear the update region before
1338 an update event is generated. */
1339 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1341 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1343 XFlush (FRAME_MAC_DISPLAY (f));
1344 UNBLOCK_INPUT;
1348 /* This function is called from various places in xdisp.c whenever a
1349 complete update has been performed. The global variable
1350 updated_window is not available here. */
1352 static void
1353 XTframe_up_to_date (f)
1354 struct frame *f;
1356 if (FRAME_MAC_P (f))
1358 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1360 if (dpyinfo->mouse_face_deferred_gc
1361 || f == dpyinfo->mouse_face_mouse_frame)
1363 BLOCK_INPUT;
1364 if (dpyinfo->mouse_face_mouse_frame)
1365 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1366 dpyinfo->mouse_face_mouse_x,
1367 dpyinfo->mouse_face_mouse_y);
1368 dpyinfo->mouse_face_deferred_gc = 0;
1369 UNBLOCK_INPUT;
1375 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1376 arrow bitmaps, or clear the fringes if no bitmaps are required
1377 before DESIRED_ROW is made current. The window being updated is
1378 found in updated_window. This function is called from
1379 update_window_line only if it is known that there are differences
1380 between bitmaps to be drawn between current row and DESIRED_ROW. */
1382 static void
1383 x_after_update_window_line (desired_row)
1384 struct glyph_row *desired_row;
1386 struct window *w = updated_window;
1387 struct frame *f;
1388 int width, height;
1390 xassert (w);
1392 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1393 desired_row->redraw_fringe_bitmaps_p = 1;
1395 /* When a window has disappeared, make sure that no rest of
1396 full-width rows stays visible in the internal border. Could
1397 check here if updated_window is the leftmost/rightmost window,
1398 but I guess it's not worth doing since vertically split windows
1399 are almost never used, internal border is rarely set, and the
1400 overhead is very small. */
1401 if (windows_or_buffers_changed
1402 && desired_row->full_width_p
1403 && (f = XFRAME (w->frame),
1404 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1405 width != 0)
1406 && (height = desired_row->visible_height,
1407 height > 0))
1409 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1410 /* Internal border is drawn below the tool bar. */
1411 if (WINDOWP (f->tool_bar_window)
1412 && w == XWINDOW (f->tool_bar_window))
1413 y -= width;
1415 BLOCK_INPUT;
1417 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1418 0, y, width, height, 0);
1419 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1420 FRAME_PIXEL_WIDTH (f) - width, y,
1421 width, height, 0);
1423 UNBLOCK_INPUT;
1428 /* Draw the bitmap WHICH in one of the left or right fringes of
1429 window W. ROW is the glyph row for which to display the bitmap; it
1430 determines the vertical position at which the bitmap has to be
1431 drawn. */
1433 static void
1434 x_draw_fringe_bitmap (w, row, p)
1435 struct window *w;
1436 struct glyph_row *row;
1437 struct draw_fringe_bitmap_params *p;
1439 struct frame *f = XFRAME (WINDOW_FRAME (w));
1440 Display *display = FRAME_MAC_DISPLAY (f);
1441 WindowPtr window = FRAME_MAC_WINDOW (f);
1442 XGCValues gcv;
1443 GC gc = f->output_data.mac->normal_gc;
1444 struct face *face = p->face;
1445 int rowY;
1447 /* Must clip because of partially visible lines. */
1448 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1449 if (p->y < rowY)
1451 /* Adjust position of "bottom aligned" bitmap on partially
1452 visible last row. */
1453 int oldY = row->y;
1454 int oldVH = row->visible_height;
1455 row->visible_height = p->h;
1456 row->y -= rowY - p->y;
1457 x_clip_to_row (w, row, -1, gc);
1458 row->y = oldY;
1459 row->visible_height = oldVH;
1461 else
1462 x_clip_to_row (w, row, -1, gc);
1464 if (p->bx >= 0 && !p->overlay_p)
1466 XGCValues gcv;
1467 gcv.foreground = face->background;
1469 #if 0 /* MAC_TODO: stipple */
1470 /* In case the same realized face is used for fringes and
1471 for something displayed in the text (e.g. face `region' on
1472 mono-displays, the fill style may have been changed to
1473 FillSolid in x_draw_glyph_string_background. */
1474 if (face->stipple)
1475 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1476 else
1477 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1478 #endif
1480 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1481 &gcv,
1482 p->bx, p->by, p->nx, p->ny);
1484 #if 0 /* MAC_TODO: stipple */
1485 if (!face->stipple)
1486 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1487 #endif
1490 if (p->which)
1492 unsigned short *bits = p->bits + p->dh;
1494 gcv.foreground = (p->cursor_p
1495 ? (p->overlay_p ? face->background
1496 : f->output_data.mac->cursor_pixel)
1497 : face->foreground);
1498 gcv.background = face->background;
1500 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1501 p->wd, p->h, bits, p->overlay_p);
1504 mac_reset_clipping (display, window);
1508 /* This is called when starting Emacs and when restarting after
1509 suspend. When starting Emacs, no window is mapped. And nothing
1510 must be done to Emacs's own window if it is suspended (though that
1511 rarely happens). */
1513 static void
1514 XTset_terminal_modes ()
1518 /* This is called when exiting or suspending Emacs. Exiting will make
1519 the windows go away, and suspending requires no action. */
1521 static void
1522 XTreset_terminal_modes ()
1527 /***********************************************************************
1528 Display Iterator
1529 ***********************************************************************/
1531 /* Function prototypes of this page. */
1533 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1534 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1537 /* Return a pointer to per-char metric information in FONT of a
1538 character pointed by B which is a pointer to an XChar2b. */
1540 #define PER_CHAR_METRIC(font, b) \
1541 ((font)->per_char \
1542 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1543 + (((font)->min_byte1 || (font)->max_byte1) \
1544 ? (((b)->byte1 - (font)->min_byte1) \
1545 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1546 : 0)) \
1547 : &((font)->max_bounds))
1550 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1551 is not contained in the font. */
1553 static INLINE XCharStruct *
1554 x_per_char_metric (font, char2b)
1555 XFontStruct *font;
1556 XChar2b *char2b;
1558 /* The result metric information. */
1559 XCharStruct *pcm = NULL;
1561 xassert (font && char2b);
1563 if (font->per_char != NULL)
1565 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1567 /* min_char_or_byte2 specifies the linear character index
1568 corresponding to the first element of the per_char array,
1569 max_char_or_byte2 is the index of the last character. A
1570 character with non-zero CHAR2B->byte1 is not in the font.
1571 A character with byte2 less than min_char_or_byte2 or
1572 greater max_char_or_byte2 is not in the font. */
1573 if (char2b->byte1 == 0
1574 && char2b->byte2 >= font->min_char_or_byte2
1575 && char2b->byte2 <= font->max_char_or_byte2)
1576 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1578 else
1580 /* If either min_byte1 or max_byte1 are nonzero, both
1581 min_char_or_byte2 and max_char_or_byte2 are less than
1582 256, and the 2-byte character index values corresponding
1583 to the per_char array element N (counting from 0) are:
1585 byte1 = N/D + min_byte1
1586 byte2 = N\D + min_char_or_byte2
1588 where:
1590 D = max_char_or_byte2 - min_char_or_byte2 + 1
1591 / = integer division
1592 \ = integer modulus */
1593 if (char2b->byte1 >= font->min_byte1
1594 && char2b->byte1 <= font->max_byte1
1595 && char2b->byte2 >= font->min_char_or_byte2
1596 && char2b->byte2 <= font->max_char_or_byte2)
1598 pcm = (font->per_char
1599 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1600 * (char2b->byte1 - font->min_byte1))
1601 + (char2b->byte2 - font->min_char_or_byte2));
1605 else
1607 /* If the per_char pointer is null, all glyphs between the first
1608 and last character indexes inclusive have the same
1609 information, as given by both min_bounds and max_bounds. */
1610 if (char2b->byte2 >= font->min_char_or_byte2
1611 && char2b->byte2 <= font->max_char_or_byte2)
1612 pcm = &font->max_bounds;
1615 return ((pcm == NULL
1616 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1617 ? NULL : pcm);
1620 /* RIF:
1623 static XCharStruct *
1624 mac_per_char_metric (font, char2b, font_type)
1625 XFontStruct *font;
1626 XChar2b *char2b;
1627 int font_type;
1629 return x_per_char_metric (font, char2b);
1632 /* RIF:
1633 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1634 the two-byte form of C. Encoding is returned in *CHAR2B. */
1636 static int
1637 mac_encode_char (c, char2b, font_info, two_byte_p)
1638 int c;
1639 XChar2b *char2b;
1640 struct font_info *font_info;
1641 int *two_byte_p;
1643 int charset = CHAR_CHARSET (c);
1644 XFontStruct *font = font_info->font;
1646 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1647 This may be either a program in a special encoder language or a
1648 fixed encoding. */
1649 if (font_info->font_encoder)
1651 /* It's a program. */
1652 struct ccl_program *ccl = font_info->font_encoder;
1654 if (CHARSET_DIMENSION (charset) == 1)
1656 ccl->reg[0] = charset;
1657 ccl->reg[1] = char2b->byte2;
1659 else
1661 ccl->reg[0] = charset;
1662 ccl->reg[1] = char2b->byte1;
1663 ccl->reg[2] = char2b->byte2;
1666 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1668 /* We assume that MSBs are appropriately set/reset by CCL
1669 program. */
1670 if (font->max_byte1 == 0) /* 1-byte font */
1671 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1672 else
1673 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1675 else if (font_info->encoding[charset])
1677 /* Fixed encoding scheme. See fontset.h for the meaning of the
1678 encoding numbers. */
1679 int enc = font_info->encoding[charset];
1681 if ((enc == 1 || enc == 2)
1682 && CHARSET_DIMENSION (charset) == 2)
1683 char2b->byte1 |= 0x80;
1685 if (enc == 1 || enc == 3)
1686 char2b->byte2 |= 0x80;
1688 if (enc == 4)
1690 int sjis1, sjis2;
1692 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1693 char2b->byte1 = sjis1;
1694 char2b->byte2 = sjis2;
1698 if (two_byte_p)
1699 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1701 return FONT_TYPE_UNKNOWN;
1706 /***********************************************************************
1707 Glyph display
1708 ***********************************************************************/
1711 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1712 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1713 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1714 int));
1715 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1716 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1717 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1718 static void x_draw_glyph_string P_ ((struct glyph_string *));
1719 static void x_set_cursor_gc P_ ((struct glyph_string *));
1720 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1721 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1722 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1723 unsigned long *, double, int));*/
1724 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1725 double, int, unsigned long));
1726 static void x_setup_relief_colors P_ ((struct glyph_string *));
1727 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1728 static void x_draw_image_relief P_ ((struct glyph_string *));
1729 static void x_draw_image_foreground P_ ((struct glyph_string *));
1730 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1731 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1732 int, int, int));
1733 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1734 int, int, int, int, int, int,
1735 Rect *));
1736 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1737 int, int, int, Rect *));
1739 #if GLYPH_DEBUG
1740 static void x_check_font P_ ((struct frame *, XFontStruct *));
1741 #endif
1744 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1745 face. */
1747 static void
1748 x_set_cursor_gc (s)
1749 struct glyph_string *s;
1751 if (s->font == FRAME_FONT (s->f)
1752 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1753 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1754 && !s->cmp)
1755 s->gc = s->f->output_data.mac->cursor_gc;
1756 else
1758 /* Cursor on non-default face: must merge. */
1759 XGCValues xgcv;
1760 unsigned long mask;
1762 xgcv.background = s->f->output_data.mac->cursor_pixel;
1763 xgcv.foreground = s->face->background;
1765 /* If the glyph would be invisible, try a different foreground. */
1766 if (xgcv.foreground == xgcv.background)
1767 xgcv.foreground = s->face->foreground;
1768 if (xgcv.foreground == xgcv.background)
1769 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1770 if (xgcv.foreground == xgcv.background)
1771 xgcv.foreground = s->face->foreground;
1773 /* Make sure the cursor is distinct from text in this face. */
1774 if (xgcv.background == s->face->background
1775 && xgcv.foreground == s->face->foreground)
1777 xgcv.background = s->face->foreground;
1778 xgcv.foreground = s->face->background;
1781 IF_DEBUG (x_check_font (s->f, s->font));
1782 xgcv.font = s->font;
1783 mask = GCForeground | GCBackground | GCFont;
1785 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1786 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1787 mask, &xgcv);
1788 else
1789 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1790 = XCreateGC (s->display, s->window, mask, &xgcv);
1792 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1797 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1799 static void
1800 x_set_mouse_face_gc (s)
1801 struct glyph_string *s;
1803 int face_id;
1804 struct face *face;
1806 /* What face has to be used last for the mouse face? */
1807 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1808 face = FACE_FROM_ID (s->f, face_id);
1809 if (face == NULL)
1810 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1812 if (s->first_glyph->type == CHAR_GLYPH)
1813 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1814 else
1815 face_id = FACE_FOR_CHAR (s->f, face, 0);
1816 s->face = FACE_FROM_ID (s->f, face_id);
1817 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1819 /* If font in this face is same as S->font, use it. */
1820 if (s->font == s->face->font)
1821 s->gc = s->face->gc;
1822 else
1824 /* Otherwise construct scratch_cursor_gc with values from FACE
1825 but font FONT. */
1826 XGCValues xgcv;
1827 unsigned long mask;
1829 xgcv.background = s->face->background;
1830 xgcv.foreground = s->face->foreground;
1831 IF_DEBUG (x_check_font (s->f, s->font));
1832 xgcv.font = s->font;
1833 mask = GCForeground | GCBackground | GCFont;
1835 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1836 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1837 mask, &xgcv);
1838 else
1839 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1840 = XCreateGC (s->display, s->window, mask, &xgcv);
1842 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1845 xassert (s->gc != 0);
1849 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1850 Faces to use in the mode line have already been computed when the
1851 matrix was built, so there isn't much to do, here. */
1853 static INLINE void
1854 x_set_mode_line_face_gc (s)
1855 struct glyph_string *s;
1857 s->gc = s->face->gc;
1861 /* Set S->gc of glyph string S for drawing that glyph string. Set
1862 S->stippled_p to a non-zero value if the face of S has a stipple
1863 pattern. */
1865 static INLINE void
1866 x_set_glyph_string_gc (s)
1867 struct glyph_string *s;
1869 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1871 if (s->hl == DRAW_NORMAL_TEXT)
1873 s->gc = s->face->gc;
1874 s->stippled_p = s->face->stipple != 0;
1876 else if (s->hl == DRAW_INVERSE_VIDEO)
1878 x_set_mode_line_face_gc (s);
1879 s->stippled_p = s->face->stipple != 0;
1881 else if (s->hl == DRAW_CURSOR)
1883 x_set_cursor_gc (s);
1884 s->stippled_p = 0;
1886 else if (s->hl == DRAW_MOUSE_FACE)
1888 x_set_mouse_face_gc (s);
1889 s->stippled_p = s->face->stipple != 0;
1891 else if (s->hl == DRAW_IMAGE_RAISED
1892 || s->hl == DRAW_IMAGE_SUNKEN)
1894 s->gc = s->face->gc;
1895 s->stippled_p = s->face->stipple != 0;
1897 else
1899 s->gc = s->face->gc;
1900 s->stippled_p = s->face->stipple != 0;
1903 /* GC must have been set. */
1904 xassert (s->gc != 0);
1908 /* Set clipping for output of glyph string S. S may be part of a mode
1909 line or menu if we don't have X toolkit support. */
1911 static INLINE void
1912 x_set_glyph_string_clipping (s)
1913 struct glyph_string *s;
1915 Rect r;
1916 get_glyph_string_clip_rect (s, &r);
1917 mac_set_clip_rectangle (s->display, s->window, &r);
1921 /* RIF:
1922 Compute left and right overhang of glyph string S. If S is a glyph
1923 string for a composition, assume overhangs don't exist. */
1925 static void
1926 mac_compute_glyph_string_overhangs (s)
1927 struct glyph_string *s;
1929 #if 0
1930 /* MAC_TODO: XTextExtents16 does nothing yet... */
1932 if (s->cmp == NULL
1933 && s->first_glyph->type == CHAR_GLYPH)
1935 XCharStruct cs;
1936 int direction, font_ascent, font_descent;
1937 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
1938 &font_ascent, &font_descent, &cs);
1939 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
1940 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
1942 #endif
1946 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1948 static INLINE void
1949 x_clear_glyph_string_rect (s, x, y, w, h)
1950 struct glyph_string *s;
1951 int x, y, w, h;
1953 XGCValues xgcv;
1955 xgcv.foreground = s->gc->background;
1956 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
1960 /* Draw the background of glyph_string S. If S->background_filled_p
1961 is non-zero don't draw it. FORCE_P non-zero means draw the
1962 background even if it wouldn't be drawn normally. This is used
1963 when a string preceding S draws into the background of S, or S
1964 contains the first component of a composition. */
1966 static void
1967 x_draw_glyph_string_background (s, force_p)
1968 struct glyph_string *s;
1969 int force_p;
1971 /* Nothing to do if background has already been drawn or if it
1972 shouldn't be drawn in the first place. */
1973 if (!s->background_filled_p)
1975 int box_line_width = max (s->face->box_line_width, 0);
1977 #if 0 /* MAC_TODO: stipple */
1978 if (s->stippled_p)
1980 /* Fill background with a stipple pattern. */
1981 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1982 XFillRectangle (s->display, s->window, s->gc, s->x,
1983 s->y + box_line_width,
1984 s->background_width,
1985 s->height - 2 * box_line_width);
1986 XSetFillStyle (s->display, s->gc, FillSolid);
1987 s->background_filled_p = 1;
1989 else
1990 #endif
1991 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1992 || s->font_not_found_p
1993 || s->extends_to_end_of_line_p
1994 || force_p)
1996 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1997 s->background_width,
1998 s->height - 2 * box_line_width);
1999 s->background_filled_p = 1;
2005 /* Draw the foreground of glyph string S. */
2007 static void
2008 x_draw_glyph_string_foreground (s)
2009 struct glyph_string *s;
2011 int i, x;
2013 /* If first glyph of S has a left box line, start drawing the text
2014 of S to the right of that box line. */
2015 if (s->face->box != FACE_NO_BOX
2016 && s->first_glyph->left_box_line_p)
2017 x = s->x + abs (s->face->box_line_width);
2018 else
2019 x = s->x;
2021 /* Draw characters of S as rectangles if S's font could not be
2022 loaded. */
2023 if (s->font_not_found_p)
2025 for (i = 0; i < s->nchars; ++i)
2027 struct glyph *g = s->first_glyph + i;
2028 mac_draw_rectangle (s->display, s->window,
2029 s->gc, x, s->y, g->pixel_width - 1,
2030 s->height - 1);
2031 x += g->pixel_width;
2034 else
2036 char *char1b = (char *) s->char2b;
2037 int boff = s->font_info->baseline_offset;
2039 if (s->font_info->vertical_centering)
2040 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2042 /* If we can use 8-bit functions, condense S->char2b. */
2043 if (!s->two_byte_p)
2044 for (i = 0; i < s->nchars; ++i)
2045 char1b[i] = s->char2b[i].byte2;
2047 /* Draw text with XDrawString if background has already been
2048 filled. Otherwise, use XDrawImageString. (Note that
2049 XDrawImageString is usually faster than XDrawString.) Always
2050 use XDrawImageString when drawing the cursor so that there is
2051 no chance that characters under a box cursor are invisible. */
2052 if (s->for_overlaps_p
2053 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2055 /* Draw characters with 16-bit or 8-bit functions. */
2056 if (s->two_byte_p)
2057 XDrawString16 (s->display, s->window, s->gc, x,
2058 s->ybase - boff, s->char2b, s->nchars);
2059 else
2060 XDrawString (s->display, s->window, s->gc, x,
2061 s->ybase - boff, char1b, s->nchars);
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);
2075 /* Draw the foreground of composite glyph string S. */
2077 static void
2078 x_draw_composite_glyph_string_foreground (s)
2079 struct glyph_string *s;
2081 int i, x;
2083 /* If first glyph of S has a left box line, start drawing the text
2084 of S to the right of that box line. */
2085 if (s->face->box != FACE_NO_BOX
2086 && s->first_glyph->left_box_line_p)
2087 x = s->x + abs (s->face->box_line_width);
2088 else
2089 x = s->x;
2091 /* S is a glyph string for a composition. S->gidx is the index of
2092 the first character drawn for glyphs of this composition.
2093 S->gidx == 0 means we are drawing the very first character of
2094 this composition. */
2096 /* Draw a rectangle for the composition if the font for the very
2097 first character of the composition could not be loaded. */
2098 if (s->font_not_found_p)
2100 if (s->gidx == 0)
2101 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2102 s->width - 1, s->height - 1);
2104 else
2106 for (i = 0; i < s->nchars; i++, ++s->gidx)
2107 XDrawString16 (s->display, s->window, s->gc,
2108 x + s->cmp->offsets[s->gidx * 2],
2109 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2110 s->char2b + i, 1);
2115 #ifdef USE_X_TOOLKIT
2117 static struct frame *x_frame_of_widget P_ ((Widget));
2120 /* Return the frame on which widget WIDGET is used.. Abort if frame
2121 cannot be determined. */
2123 static struct frame *
2124 x_frame_of_widget (widget)
2125 Widget widget;
2127 struct x_display_info *dpyinfo;
2128 Lisp_Object tail;
2129 struct frame *f;
2131 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2133 /* Find the top-level shell of the widget. Note that this function
2134 can be called when the widget is not yet realized, so XtWindow
2135 (widget) == 0. That's the reason we can't simply use
2136 x_any_window_to_frame. */
2137 while (!XtIsTopLevelShell (widget))
2138 widget = XtParent (widget);
2140 /* Look for a frame with that top-level widget. Allocate the color
2141 on that frame to get the right gamma correction value. */
2142 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2143 if (GC_FRAMEP (XCAR (tail))
2144 && (f = XFRAME (XCAR (tail)),
2145 (f->output_data.nothing != 1
2146 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2147 && f->output_data.x->widget == widget)
2148 return f;
2150 abort ();
2154 /* Allocate the color COLOR->pixel on the screen and display of
2155 widget WIDGET in colormap CMAP. If an exact match cannot be
2156 allocated, try the nearest color available. Value is non-zero
2157 if successful. This is called from lwlib. */
2160 x_alloc_nearest_color_for_widget (widget, cmap, color)
2161 Widget widget;
2162 Colormap cmap;
2163 XColor *color;
2165 struct frame *f = x_frame_of_widget (widget);
2166 return x_alloc_nearest_color (f, cmap, color);
2170 #endif /* USE_X_TOOLKIT */
2172 #if 0 /* MAC_TODO */
2174 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2175 CMAP. If an exact match can't be allocated, try the nearest color
2176 available. Value is non-zero if successful. Set *COLOR to the
2177 color allocated. */
2180 x_alloc_nearest_color (f, cmap, color)
2181 struct frame *f;
2182 Colormap cmap;
2183 XColor *color;
2185 Display *display = FRAME_X_DISPLAY (f);
2186 Screen *screen = FRAME_X_SCREEN (f);
2187 int rc;
2189 gamma_correct (f, color);
2190 rc = XAllocColor (display, cmap, color);
2191 if (rc == 0)
2193 /* If we got to this point, the colormap is full, so we're going
2194 to try to get the next closest color. The algorithm used is
2195 a least-squares matching, which is what X uses for closest
2196 color matching with StaticColor visuals. */
2197 int nearest, i;
2198 unsigned long nearest_delta = ~0;
2199 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2200 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2202 for (i = 0; i < ncells; ++i)
2203 cells[i].pixel = i;
2204 XQueryColors (display, cmap, cells, ncells);
2206 for (nearest = i = 0; i < ncells; ++i)
2208 long dred = (color->red >> 8) - (cells[i].red >> 8);
2209 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2210 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2211 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2213 if (delta < nearest_delta)
2215 nearest = i;
2216 nearest_delta = delta;
2220 color->red = cells[nearest].red;
2221 color->green = cells[nearest].green;
2222 color->blue = cells[nearest].blue;
2223 rc = XAllocColor (display, cmap, color);
2226 #ifdef DEBUG_X_COLORS
2227 if (rc)
2228 register_color (color->pixel);
2229 #endif /* DEBUG_X_COLORS */
2231 return rc;
2235 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2236 It's necessary to do this instead of just using PIXEL directly to
2237 get color reference counts right. */
2239 unsigned long
2240 x_copy_color (f, pixel)
2241 struct frame *f;
2242 unsigned long pixel;
2244 XColor color;
2246 color.pixel = pixel;
2247 BLOCK_INPUT;
2248 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2249 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2250 UNBLOCK_INPUT;
2251 #ifdef DEBUG_X_COLORS
2252 register_color (pixel);
2253 #endif
2254 return color.pixel;
2258 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2259 It's necessary to do this instead of just using PIXEL directly to
2260 get color reference counts right. */
2262 unsigned long
2263 x_copy_dpy_color (dpy, cmap, pixel)
2264 Display *dpy;
2265 Colormap cmap;
2266 unsigned long pixel;
2268 XColor color;
2270 color.pixel = pixel;
2271 BLOCK_INPUT;
2272 XQueryColor (dpy, cmap, &color);
2273 XAllocColor (dpy, cmap, &color);
2274 UNBLOCK_INPUT;
2275 #ifdef DEBUG_X_COLORS
2276 register_color (pixel);
2277 #endif
2278 return color.pixel;
2281 #endif /* MAC_TODO */
2284 /* Brightness beyond which a color won't have its highlight brightness
2285 boosted.
2287 Nominally, highlight colors for `3d' faces are calculated by
2288 brightening an object's color by a constant scale factor, but this
2289 doesn't yield good results for dark colors, so for colors who's
2290 brightness is less than this value (on a scale of 0-255) have to
2291 use an additional additive factor.
2293 The value here is set so that the default menu-bar/mode-line color
2294 (grey75) will not have its highlights changed at all. */
2295 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2298 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2299 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2300 If this produces the same color as COLOR, try a color where all RGB
2301 values have DELTA added. Return the allocated color in *COLOR.
2302 DISPLAY is the X display, CMAP is the colormap to operate on.
2303 Value is non-zero if successful. */
2305 static int
2306 mac_alloc_lighter_color (f, color, factor, delta)
2307 struct frame *f;
2308 unsigned long *color;
2309 double factor;
2310 int delta;
2312 unsigned long new;
2313 long bright;
2315 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2316 delta /= 256;
2318 /* Change RGB values by specified FACTOR. Avoid overflow! */
2319 xassert (factor >= 0);
2320 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2321 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2322 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2324 /* Calculate brightness of COLOR. */
2325 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2326 + BLUE_FROM_ULONG (*color)) / 6;
2328 /* We only boost colors that are darker than
2329 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2330 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2331 /* Make an additive adjustment to NEW, because it's dark enough so
2332 that scaling by FACTOR alone isn't enough. */
2334 /* How far below the limit this color is (0 - 1, 1 being darker). */
2335 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2336 /* The additive adjustment. */
2337 int min_delta = delta * dimness * factor / 2;
2339 if (factor < 1)
2340 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2341 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2342 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2343 else
2344 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2345 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2346 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2349 if (new == *color)
2350 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2351 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2352 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2354 /* MAC_TODO: Map to palette and retry with delta if same? */
2355 /* MAC_TODO: Free colors (if using palette)? */
2357 if (new == *color)
2358 return 0;
2360 *color = new;
2362 return 1;
2366 /* Set up the foreground color for drawing relief lines of glyph
2367 string S. RELIEF is a pointer to a struct relief containing the GC
2368 with which lines will be drawn. Use a color that is FACTOR or
2369 DELTA lighter or darker than the relief's background which is found
2370 in S->f->output_data.x->relief_background. If such a color cannot
2371 be allocated, use DEFAULT_PIXEL, instead. */
2373 static void
2374 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2375 struct frame *f;
2376 struct relief *relief;
2377 double factor;
2378 int delta;
2379 unsigned long default_pixel;
2381 XGCValues xgcv;
2382 struct mac_output *di = f->output_data.mac;
2383 unsigned long mask = GCForeground;
2384 unsigned long pixel;
2385 unsigned long background = di->relief_background;
2386 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2388 /* MAC_TODO: Free colors (if using palette)? */
2390 /* Allocate new color. */
2391 xgcv.foreground = default_pixel;
2392 pixel = background;
2393 if (dpyinfo->n_planes != 1
2394 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2396 relief->allocated_p = 1;
2397 xgcv.foreground = relief->pixel = pixel;
2400 if (relief->gc == 0)
2402 #if 0 /* MAC_TODO: stipple */
2403 xgcv.stipple = dpyinfo->gray;
2404 mask |= GCStipple;
2405 #endif
2406 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2408 else
2409 XChangeGC (NULL, relief->gc, mask, &xgcv);
2413 /* Set up colors for the relief lines around glyph string S. */
2415 static void
2416 x_setup_relief_colors (s)
2417 struct glyph_string *s;
2419 struct mac_output *di = s->f->output_data.mac;
2420 unsigned long color;
2422 if (s->face->use_box_color_for_shadows_p)
2423 color = s->face->box_color;
2424 else if (s->first_glyph->type == IMAGE_GLYPH
2425 && s->img->pixmap
2426 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2427 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2428 else
2430 XGCValues xgcv;
2432 /* Get the background color of the face. */
2433 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2434 color = xgcv.background;
2437 if (di->white_relief.gc == 0
2438 || color != di->relief_background)
2440 di->relief_background = color;
2441 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2442 WHITE_PIX_DEFAULT (s->f));
2443 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2444 BLACK_PIX_DEFAULT (s->f));
2449 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2450 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2451 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2452 relief. LEFT_P non-zero means draw a relief on the left side of
2453 the rectangle. RIGHT_P non-zero means draw a relief on the right
2454 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2455 when drawing. */
2457 static void
2458 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2459 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2460 struct frame *f;
2461 int left_x, top_y, right_x, bottom_y, width;
2462 int top_p, bot_p, left_p, right_p, raised_p;
2463 Rect *clip_rect;
2465 Display *dpy = FRAME_MAC_DISPLAY (f);
2466 Window window = FRAME_MAC_WINDOW (f);
2467 int i;
2468 GC gc;
2470 if (raised_p)
2471 gc = f->output_data.mac->white_relief.gc;
2472 else
2473 gc = f->output_data.mac->black_relief.gc;
2474 mac_set_clip_rectangle (dpy, window, clip_rect);
2476 /* Top. */
2477 if (top_p)
2478 for (i = 0; i < width; ++i)
2479 XDrawLine (dpy, window, gc,
2480 left_x + i * left_p, top_y + i,
2481 right_x - i * right_p, top_y + i);
2483 /* Left. */
2484 if (left_p)
2485 for (i = 0; i < width; ++i)
2486 XDrawLine (dpy, window, gc,
2487 left_x + i, top_y + i, left_x + i, bottom_y - i);
2489 mac_reset_clipping (dpy, window);
2490 if (raised_p)
2491 gc = f->output_data.mac->black_relief.gc;
2492 else
2493 gc = f->output_data.mac->white_relief.gc;
2494 mac_set_clip_rectangle (dpy, window,
2495 clip_rect);
2497 /* Bottom. */
2498 if (bot_p)
2499 for (i = 0; i < width; ++i)
2500 XDrawLine (dpy, window, gc,
2501 left_x + i * left_p, bottom_y - i,
2502 right_x - i * right_p, bottom_y - i);
2504 /* Right. */
2505 if (right_p)
2506 for (i = 0; i < width; ++i)
2507 XDrawLine (dpy, window, gc,
2508 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2510 mac_reset_clipping (dpy, window);
2514 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2515 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2516 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2517 left side of the rectangle. RIGHT_P non-zero means draw a line
2518 on the right side of the rectangle. CLIP_RECT is the clipping
2519 rectangle to use when drawing. */
2521 static void
2522 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2523 left_p, right_p, clip_rect)
2524 struct glyph_string *s;
2525 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2526 Rect *clip_rect;
2528 XGCValues xgcv;
2530 xgcv.foreground = s->face->box_color;
2531 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2533 /* Top. */
2534 XFillRectangle (s->display, s->window, &xgcv,
2535 left_x, top_y, right_x - left_x + 1, width);
2537 /* Left. */
2538 if (left_p)
2539 XFillRectangle (s->display, s->window, &xgcv,
2540 left_x, top_y, width, bottom_y - top_y + 1);
2542 /* Bottom. */
2543 XFillRectangle (s->display, s->window, &xgcv,
2544 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2546 /* Right. */
2547 if (right_p)
2548 XFillRectangle (s->display, s->window, &xgcv,
2549 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2551 mac_reset_clipping (s->display, s->window);
2555 /* Draw a box around glyph string S. */
2557 static void
2558 x_draw_glyph_string_box (s)
2559 struct glyph_string *s;
2561 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2562 int left_p, right_p;
2563 struct glyph *last_glyph;
2564 Rect clip_rect;
2566 last_x = window_box_right (s->w, s->area);
2567 if (s->row->full_width_p
2568 && !s->w->pseudo_window_p)
2570 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2571 if (s->area != RIGHT_MARGIN_AREA
2572 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2573 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2576 /* The glyph that may have a right box line. */
2577 last_glyph = (s->cmp || s->img
2578 ? s->first_glyph
2579 : s->first_glyph + s->nchars - 1);
2581 width = abs (s->face->box_line_width);
2582 raised_p = s->face->box == FACE_RAISED_BOX;
2583 left_x = s->x;
2584 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2585 ? last_x - 1
2586 : min (last_x, s->x + s->background_width) - 1);
2587 top_y = s->y;
2588 bottom_y = top_y + s->height - 1;
2590 left_p = (s->first_glyph->left_box_line_p
2591 || (s->hl == DRAW_MOUSE_FACE
2592 && (s->prev == NULL
2593 || s->prev->hl != s->hl)));
2594 right_p = (last_glyph->right_box_line_p
2595 || (s->hl == DRAW_MOUSE_FACE
2596 && (s->next == NULL
2597 || s->next->hl != s->hl)));
2599 get_glyph_string_clip_rect (s, &clip_rect);
2601 if (s->face->box == FACE_SIMPLE_BOX)
2602 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2603 left_p, right_p, &clip_rect);
2604 else
2606 x_setup_relief_colors (s);
2607 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2608 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2613 /* Draw foreground of image glyph string S. */
2615 static void
2616 x_draw_image_foreground (s)
2617 struct glyph_string *s;
2619 int x = s->x;
2620 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2622 /* If first glyph of S has a left box line, start drawing it to the
2623 right of that line. */
2624 if (s->face->box != FACE_NO_BOX
2625 && s->first_glyph->left_box_line_p
2626 && s->slice.x == 0)
2627 x += abs (s->face->box_line_width);
2629 /* If there is a margin around the image, adjust x- and y-position
2630 by that margin. */
2631 if (s->slice.x == 0)
2632 x += s->img->hmargin;
2633 if (s->slice.y == 0)
2634 y += s->img->vmargin;
2636 if (s->img->pixmap)
2638 if (s->img->mask)
2640 Rect nr;
2641 XRectangle clip_rect, image_rect, r;
2643 get_glyph_string_clip_rect (s, &nr);
2644 CONVERT_TO_XRECT (clip_rect, nr);
2645 image_rect.x = x;
2646 image_rect.y = y;
2647 image_rect.width = s->slice.width;
2648 image_rect.height = s->slice.height;
2649 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2650 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2651 s->window, s->gc,
2652 s->slice.x + r.x - x, s->slice.y + r.y - y,
2653 r.width, r.height, r.x, r.y);
2655 else
2657 Rect nr;
2658 XRectangle clip_rect, image_rect, r;
2660 get_glyph_string_clip_rect (s, &nr);
2661 CONVERT_TO_XRECT (clip_rect, nr);
2662 image_rect.x = x;
2663 image_rect.y = y;
2664 image_rect.width = s->slice.width;
2665 image_rect.height = s->slice.height;
2666 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2667 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
2668 s->slice.x + r.x - x, s->slice.y + r.y - y,
2669 r.width, r.height, r.x, r.y);
2671 /* When the image has a mask, we can expect that at
2672 least part of a mouse highlight or a block cursor will
2673 be visible. If the image doesn't have a mask, make
2674 a block cursor visible by drawing a rectangle around
2675 the image. I believe it's looking better if we do
2676 nothing here for mouse-face. */
2677 if (s->hl == DRAW_CURSOR)
2679 int r = s->img->relief;
2680 if (r < 0) r = -r;
2681 mac_draw_rectangle (s->display, s->window, s->gc,
2682 x - r, y - r,
2683 s->slice.width + r*2 - 1,
2684 s->slice.height + r*2 - 1);
2688 else
2689 /* Draw a rectangle if image could not be loaded. */
2690 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2691 s->slice.width - 1, s->slice.height - 1);
2695 /* Draw a relief around the image glyph string S. */
2697 static void
2698 x_draw_image_relief (s)
2699 struct glyph_string *s;
2701 int x0, y0, x1, y1, thick, raised_p;
2702 Rect r;
2703 int x = s->x;
2704 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2706 /* If first glyph of S has a left box line, start drawing it to the
2707 right of that line. */
2708 if (s->face->box != FACE_NO_BOX
2709 && s->first_glyph->left_box_line_p
2710 && s->slice.x == 0)
2711 x += abs (s->face->box_line_width);
2713 /* If there is a margin around the image, adjust x- and y-position
2714 by that margin. */
2715 if (s->slice.x == 0)
2716 x += s->img->hmargin;
2717 if (s->slice.y == 0)
2718 y += s->img->vmargin;
2720 if (s->hl == DRAW_IMAGE_SUNKEN
2721 || s->hl == DRAW_IMAGE_RAISED)
2723 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2724 raised_p = s->hl == DRAW_IMAGE_RAISED;
2726 else
2728 thick = abs (s->img->relief);
2729 raised_p = s->img->relief > 0;
2732 x0 = x - thick;
2733 y0 = y - thick;
2734 x1 = x + s->slice.width + thick - 1;
2735 y1 = y + s->slice.height + thick - 1;
2737 x_setup_relief_colors (s);
2738 get_glyph_string_clip_rect (s, &r);
2739 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2740 s->slice.y == 0,
2741 s->slice.y + s->slice.height == s->img->height,
2742 s->slice.x == 0,
2743 s->slice.x + s->slice.width == s->img->width,
2744 &r);
2748 /* Draw the foreground of image glyph string S to PIXMAP. */
2750 static void
2751 x_draw_image_foreground_1 (s, pixmap)
2752 struct glyph_string *s;
2753 Pixmap pixmap;
2755 int x = 0;
2756 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2758 /* If first glyph of S has a left box line, start drawing it to the
2759 right of that line. */
2760 if (s->face->box != FACE_NO_BOX
2761 && s->first_glyph->left_box_line_p
2762 && s->slice.x == 0)
2763 x += abs (s->face->box_line_width);
2765 /* If there is a margin around the image, adjust x- and y-position
2766 by that margin. */
2767 if (s->slice.x == 0)
2768 x += s->img->hmargin;
2769 if (s->slice.y == 0)
2770 y += s->img->vmargin;
2772 if (s->img->pixmap)
2774 if (s->img->mask)
2775 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2776 s->img->mask, pixmap, s->gc,
2777 s->slice.x, s->slice.y,
2778 s->slice.width, s->slice.height,
2779 x, y);
2780 else
2782 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2783 s->slice.x, s->slice.y,
2784 s->slice.width, s->slice.height,
2785 x, y);
2787 /* When the image has a mask, we can expect that at
2788 least part of a mouse highlight or a block cursor will
2789 be visible. If the image doesn't have a mask, make
2790 a block cursor visible by drawing a rectangle around
2791 the image. I believe it's looking better if we do
2792 nothing here for mouse-face. */
2793 if (s->hl == DRAW_CURSOR)
2795 int r = s->img->relief;
2796 if (r < 0) r = -r;
2797 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2798 s->slice.width + r*2 - 1,
2799 s->slice.height + r*2 - 1);
2803 else
2804 /* Draw a rectangle if image could not be loaded. */
2805 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2806 s->slice.width - 1, s->slice.height - 1);
2810 /* Draw part of the background of glyph string S. X, Y, W, and H
2811 give the rectangle to draw. */
2813 static void
2814 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2815 struct glyph_string *s;
2816 int x, y, w, h;
2818 #if 0 /* MAC_TODO: stipple */
2819 if (s->stippled_p)
2821 /* Fill background with a stipple pattern. */
2822 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2823 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2824 XSetFillStyle (s->display, s->gc, FillSolid);
2826 else
2827 #endif /* MAC_TODO */
2828 x_clear_glyph_string_rect (s, x, y, w, h);
2832 /* Draw image glyph string S.
2834 s->y
2835 s->x +-------------------------
2836 | s->face->box
2838 | +-------------------------
2839 | | s->img->margin
2841 | | +-------------------
2842 | | | the image
2846 static void
2847 x_draw_image_glyph_string (s)
2848 struct glyph_string *s;
2850 int x, y;
2851 int box_line_hwidth = abs (s->face->box_line_width);
2852 int box_line_vwidth = max (s->face->box_line_width, 0);
2853 int height;
2854 Pixmap pixmap = 0;
2856 height = s->height - 2 * box_line_vwidth;
2859 /* Fill background with face under the image. Do it only if row is
2860 taller than image or if image has a clip mask to reduce
2861 flickering. */
2862 s->stippled_p = s->face->stipple != 0;
2863 if (height > s->slice.height
2864 || s->img->hmargin
2865 || s->img->vmargin
2866 || s->img->mask
2867 || s->img->pixmap == 0
2868 || s->width != s->background_width)
2870 x = s->x;
2871 if (s->first_glyph->left_box_line_p
2872 && s->slice.x == 0)
2873 x += box_line_hwidth;
2875 y = s->y;
2876 if (s->slice.y == 0)
2877 y += box_line_vwidth;
2879 if (s->img->mask)
2881 /* Create a pixmap as large as the glyph string. Fill it
2882 with the background color. Copy the image to it, using
2883 its mask. Copy the temporary pixmap to the display. */
2884 int depth = one_mac_display_info.n_planes;
2886 /* Create a pixmap as large as the glyph string. */
2887 pixmap = XCreatePixmap (s->display, s->window,
2888 s->background_width,
2889 s->height, depth);
2891 /* Fill the pixmap with the background color/stipple. */
2892 #if 0 /* TODO: stipple */
2893 if (s->stippled_p)
2895 /* Fill background with a stipple pattern. */
2896 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2897 XFillRectangle (s->display, pixmap, s->gc,
2898 0, 0, s->background_width, s->height);
2899 XSetFillStyle (s->display, s->gc, FillSolid);
2901 else
2902 #endif
2904 XGCValues xgcv;
2905 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2906 &xgcv);
2907 XSetForeground (s->display, s->gc, xgcv.background);
2908 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2909 0, 0, s->background_width,
2910 s->height);
2911 XSetForeground (s->display, s->gc, xgcv.foreground);
2914 else
2915 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2917 s->background_filled_p = 1;
2920 /* Draw the foreground. */
2921 if (pixmap != 0)
2923 x_draw_image_foreground_1 (s, pixmap);
2924 x_set_glyph_string_clipping (s);
2925 mac_copy_area (s->display, pixmap, s->window, s->gc,
2926 0, 0, s->background_width, s->height, s->x, s->y);
2927 mac_reset_clipping (s->display, s->window);
2928 XFreePixmap (s->display, pixmap);
2930 else
2931 x_draw_image_foreground (s);
2933 /* If we must draw a relief around the image, do it. */
2934 if (s->img->relief
2935 || s->hl == DRAW_IMAGE_RAISED
2936 || s->hl == DRAW_IMAGE_SUNKEN)
2937 x_draw_image_relief (s);
2941 /* Draw stretch glyph string S. */
2943 static void
2944 x_draw_stretch_glyph_string (s)
2945 struct glyph_string *s;
2947 xassert (s->first_glyph->type == STRETCH_GLYPH);
2948 s->stippled_p = s->face->stipple != 0;
2950 if (s->hl == DRAW_CURSOR
2951 && !x_stretch_cursor_p)
2953 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2954 as wide as the stretch glyph. */
2955 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2957 /* Draw cursor. */
2958 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2960 /* Clear rest using the GC of the original non-cursor face. */
2961 if (width < s->background_width)
2963 int x = s->x + width, y = s->y;
2964 int w = s->background_width - width, h = s->height;
2965 Rect r;
2966 GC gc;
2968 if (s->row->mouse_face_p
2969 && cursor_in_mouse_face_p (s->w))
2971 x_set_mouse_face_gc (s);
2972 gc = s->gc;
2974 else
2975 gc = s->face->gc;
2977 get_glyph_string_clip_rect (s, &r);
2978 mac_set_clip_rectangle (s->display, s->window, &r);
2980 #if 0 /* MAC_TODO: stipple */
2981 if (s->face->stipple)
2983 /* Fill background with a stipple pattern. */
2984 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2985 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2986 XSetFillStyle (s->display, gc, FillSolid);
2988 else
2989 #endif /* MAC_TODO */
2991 XGCValues xgcv;
2992 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2993 XSetForeground (s->display, gc, xgcv.background);
2994 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2995 XSetForeground (s->display, gc, xgcv.foreground);
2998 mac_reset_clipping (s->display, s->window);
3001 else if (!s->background_filled_p)
3002 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3003 s->height);
3005 s->background_filled_p = 1;
3009 /* Draw glyph string S. */
3011 static void
3012 x_draw_glyph_string (s)
3013 struct glyph_string *s;
3015 int relief_drawn_p = 0;
3017 /* If S draws into the background of its successor, draw the
3018 background of the successor first so that S can draw into it.
3019 This makes S->next use XDrawString instead of XDrawImageString. */
3020 if (s->next && s->right_overhang && !s->for_overlaps_p)
3022 xassert (s->next->img == NULL);
3023 x_set_glyph_string_gc (s->next);
3024 x_set_glyph_string_clipping (s->next);
3025 x_draw_glyph_string_background (s->next, 1);
3028 /* Set up S->gc, set clipping and draw S. */
3029 x_set_glyph_string_gc (s);
3031 /* Draw relief (if any) in advance for char/composition so that the
3032 glyph string can be drawn over it. */
3033 if (!s->for_overlaps_p
3034 && s->face->box != FACE_NO_BOX
3035 && (s->first_glyph->type == CHAR_GLYPH
3036 || s->first_glyph->type == COMPOSITE_GLYPH))
3039 x_set_glyph_string_clipping (s);
3040 x_draw_glyph_string_background (s, 1);
3041 x_draw_glyph_string_box (s);
3042 x_set_glyph_string_clipping (s);
3043 relief_drawn_p = 1;
3045 else
3046 x_set_glyph_string_clipping (s);
3048 switch (s->first_glyph->type)
3050 case IMAGE_GLYPH:
3051 x_draw_image_glyph_string (s);
3052 break;
3054 case STRETCH_GLYPH:
3055 x_draw_stretch_glyph_string (s);
3056 break;
3058 case CHAR_GLYPH:
3059 if (s->for_overlaps_p)
3060 s->background_filled_p = 1;
3061 else
3062 x_draw_glyph_string_background (s, 0);
3063 x_draw_glyph_string_foreground (s);
3064 break;
3066 case COMPOSITE_GLYPH:
3067 if (s->for_overlaps_p || s->gidx > 0)
3068 s->background_filled_p = 1;
3069 else
3070 x_draw_glyph_string_background (s, 1);
3071 x_draw_composite_glyph_string_foreground (s);
3072 break;
3074 default:
3075 abort ();
3078 if (!s->for_overlaps_p)
3080 /* Draw underline. */
3081 if (s->face->underline_p)
3083 unsigned long h = 1;
3084 unsigned long dy = s->height - h;
3086 if (s->face->underline_defaulted_p)
3087 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3088 s->width, h);
3089 else
3091 XGCValues xgcv;
3092 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3093 XSetForeground (s->display, s->gc, s->face->underline_color);
3094 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3095 s->width, h);
3096 XSetForeground (s->display, s->gc, xgcv.foreground);
3100 /* Draw overline. */
3101 if (s->face->overline_p)
3103 unsigned long dy = 0, h = 1;
3105 if (s->face->overline_color_defaulted_p)
3106 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3107 s->width, h);
3108 else
3110 XGCValues xgcv;
3111 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3112 XSetForeground (s->display, s->gc, s->face->overline_color);
3113 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3114 s->width, h);
3115 XSetForeground (s->display, s->gc, xgcv.foreground);
3119 /* Draw strike-through. */
3120 if (s->face->strike_through_p)
3122 unsigned long h = 1;
3123 unsigned long dy = (s->height - h) / 2;
3125 if (s->face->strike_through_color_defaulted_p)
3126 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3127 s->width, h);
3128 else
3130 XGCValues xgcv;
3131 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3132 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3133 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3134 s->width, h);
3135 XSetForeground (s->display, s->gc, xgcv.foreground);
3139 /* Draw relief if not yet drawn. */
3140 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3141 x_draw_glyph_string_box (s);
3144 /* Reset clipping. */
3145 mac_reset_clipping (s->display, s->window);
3148 /* Shift display to make room for inserted glyphs. */
3150 void
3151 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3152 struct frame *f;
3153 int x, y, width, height, shift_by;
3155 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3156 f->output_data.mac->normal_gc,
3157 x, y, width, height,
3158 x + shift_by, y);
3161 /* Delete N glyphs at the nominal cursor position. Not implemented
3162 for X frames. */
3164 static void
3165 x_delete_glyphs (n)
3166 register int n;
3168 abort ();
3172 /* Clear entire frame. If updating_frame is non-null, clear that
3173 frame. Otherwise clear the selected frame. */
3175 static void
3176 x_clear_frame ()
3178 struct frame *f;
3180 if (updating_frame)
3181 f = updating_frame;
3182 else
3183 f = SELECTED_FRAME ();
3185 /* Clearing the frame will erase any cursor, so mark them all as no
3186 longer visible. */
3187 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3188 output_cursor.hpos = output_cursor.vpos = 0;
3189 output_cursor.x = -1;
3191 /* We don't set the output cursor here because there will always
3192 follow an explicit cursor_to. */
3193 BLOCK_INPUT;
3194 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3196 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3197 /* We have to clear the scroll bars, too. If we have changed
3198 colors or something like that, then they should be notified. */
3199 x_scroll_bar_clear (f);
3200 #endif
3202 XFlush (FRAME_MAC_DISPLAY (f));
3203 UNBLOCK_INPUT;
3208 /* Invert the middle quarter of the frame for .15 sec. */
3210 /* We use the select system call to do the waiting, so we have to make
3211 sure it's available. If it isn't, we just won't do visual bells. */
3213 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3216 /* Subtract the `struct timeval' values X and Y, storing the result in
3217 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3219 static int
3220 timeval_subtract (result, x, y)
3221 struct timeval *result, x, y;
3223 /* Perform the carry for the later subtraction by updating y. This
3224 is safer because on some systems the tv_sec member is unsigned. */
3225 if (x.tv_usec < y.tv_usec)
3227 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3228 y.tv_usec -= 1000000 * nsec;
3229 y.tv_sec += nsec;
3232 if (x.tv_usec - y.tv_usec > 1000000)
3234 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3235 y.tv_usec += 1000000 * nsec;
3236 y.tv_sec -= nsec;
3239 /* Compute the time remaining to wait. tv_usec is certainly
3240 positive. */
3241 result->tv_sec = x.tv_sec - y.tv_sec;
3242 result->tv_usec = x.tv_usec - y.tv_usec;
3244 /* Return indication of whether the result should be considered
3245 negative. */
3246 return x.tv_sec < y.tv_sec;
3249 void
3250 XTflash (f)
3251 struct frame *f;
3253 BLOCK_INPUT;
3255 FlashMenuBar (0);
3258 struct timeval wakeup;
3260 EMACS_GET_TIME (wakeup);
3262 /* Compute time to wait until, propagating carry from usecs. */
3263 wakeup.tv_usec += 150000;
3264 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3265 wakeup.tv_usec %= 1000000;
3267 /* Keep waiting until past the time wakeup. */
3268 while (1)
3270 struct timeval timeout;
3272 EMACS_GET_TIME (timeout);
3274 /* In effect, timeout = wakeup - timeout.
3275 Break if result would be negative. */
3276 if (timeval_subtract (&timeout, wakeup, timeout))
3277 break;
3279 /* Try to wait that long--but we might wake up sooner. */
3280 select (0, NULL, NULL, NULL, &timeout);
3284 FlashMenuBar (0);
3286 UNBLOCK_INPUT;
3289 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3292 /* Make audible bell. */
3294 void
3295 XTring_bell ()
3297 struct frame *f = SELECTED_FRAME ();
3299 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3300 if (visible_bell)
3301 XTflash (f);
3302 else
3303 #endif
3305 BLOCK_INPUT;
3306 SysBeep (1);
3307 XFlush (FRAME_MAC_DISPLAY (f));
3308 UNBLOCK_INPUT;
3314 /* Specify how many text lines, from the top of the window,
3315 should be affected by insert-lines and delete-lines operations.
3316 This, and those operations, are used only within an update
3317 that is bounded by calls to x_update_begin and x_update_end. */
3319 static void
3320 XTset_terminal_window (n)
3321 register int n;
3323 /* This function intentionally left blank. */
3328 /***********************************************************************
3329 Line Dance
3330 ***********************************************************************/
3332 /* Perform an insert-lines or delete-lines operation, inserting N
3333 lines or deleting -N lines at vertical position VPOS. */
3335 static void
3336 x_ins_del_lines (vpos, n)
3337 int vpos, n;
3339 abort ();
3343 /* Scroll part of the display as described by RUN. */
3345 static void
3346 x_scroll_run (w, run)
3347 struct window *w;
3348 struct run *run;
3350 struct frame *f = XFRAME (w->frame);
3351 int x, y, width, height, from_y, to_y, bottom_y;
3353 /* Get frame-relative bounding box of the text display area of W,
3354 without mode lines. Include in this box the left and right
3355 fringe of W. */
3356 window_box (w, -1, &x, &y, &width, &height);
3358 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3359 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3360 bottom_y = y + height;
3362 if (to_y < from_y)
3364 /* Scrolling up. Make sure we don't copy part of the mode
3365 line at the bottom. */
3366 if (from_y + run->height > bottom_y)
3367 height = bottom_y - from_y;
3368 else
3369 height = run->height;
3371 else
3373 /* Scolling down. Make sure we don't copy over the mode line.
3374 at the bottom. */
3375 if (to_y + run->height > bottom_y)
3376 height = bottom_y - to_y;
3377 else
3378 height = run->height;
3381 BLOCK_INPUT;
3383 /* Cursor off. Will be switched on again in x_update_window_end. */
3384 updated_window = w;
3385 x_clear_cursor (w);
3387 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3388 f->output_data.mac->normal_gc,
3389 x, from_y,
3390 width, height,
3391 x, to_y);
3393 UNBLOCK_INPUT;
3398 /***********************************************************************
3399 Exposure Events
3400 ***********************************************************************/
3403 static void
3404 frame_highlight (f)
3405 struct frame *f;
3407 x_update_cursor (f, 1);
3410 static void
3411 frame_unhighlight (f)
3412 struct frame *f;
3414 x_update_cursor (f, 1);
3417 /* The focus has changed. Update the frames as necessary to reflect
3418 the new situation. Note that we can't change the selected frame
3419 here, because the Lisp code we are interrupting might become confused.
3420 Each event gets marked with the frame in which it occurred, so the
3421 Lisp code can tell when the switch took place by examining the events. */
3423 static void
3424 x_new_focus_frame (dpyinfo, frame)
3425 struct x_display_info *dpyinfo;
3426 struct frame *frame;
3428 struct frame *old_focus = dpyinfo->x_focus_frame;
3430 if (frame != dpyinfo->x_focus_frame)
3432 /* Set this before calling other routines, so that they see
3433 the correct value of x_focus_frame. */
3434 dpyinfo->x_focus_frame = frame;
3436 if (old_focus && old_focus->auto_lower)
3437 x_lower_frame (old_focus);
3439 #if 0
3440 selected_frame = frame;
3441 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3442 selected_frame);
3443 Fselect_window (selected_frame->selected_window, Qnil);
3444 choose_minibuf_frame ();
3445 #endif /* ! 0 */
3447 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3448 pending_autoraise_frame = dpyinfo->x_focus_frame;
3449 else
3450 pending_autoraise_frame = 0;
3453 x_frame_rehighlight (dpyinfo);
3456 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3458 void
3459 x_mouse_leave (dpyinfo)
3460 struct x_display_info *dpyinfo;
3462 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3465 /* The focus has changed, or we have redirected a frame's focus to
3466 another frame (this happens when a frame uses a surrogate
3467 mini-buffer frame). Shift the highlight as appropriate.
3469 The FRAME argument doesn't necessarily have anything to do with which
3470 frame is being highlighted or un-highlighted; we only use it to find
3471 the appropriate X display info. */
3473 static void
3474 XTframe_rehighlight (frame)
3475 struct frame *frame;
3477 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3480 static void
3481 x_frame_rehighlight (dpyinfo)
3482 struct x_display_info *dpyinfo;
3484 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3486 if (dpyinfo->x_focus_frame)
3488 dpyinfo->x_highlight_frame
3489 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3490 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3491 : dpyinfo->x_focus_frame);
3492 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3494 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3495 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3498 else
3499 dpyinfo->x_highlight_frame = 0;
3501 if (dpyinfo->x_highlight_frame != old_highlight)
3503 if (old_highlight)
3504 frame_unhighlight (old_highlight);
3505 if (dpyinfo->x_highlight_frame)
3506 frame_highlight (dpyinfo->x_highlight_frame);
3512 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3514 #if 0 /* MAC_TODO */
3515 /* Initialize mode_switch_bit and modifier_meaning. */
3516 static void
3517 x_find_modifier_meanings (dpyinfo)
3518 struct x_display_info *dpyinfo;
3520 int min_code, max_code;
3521 KeySym *syms;
3522 int syms_per_code;
3523 XModifierKeymap *mods;
3525 dpyinfo->meta_mod_mask = 0;
3526 dpyinfo->shift_lock_mask = 0;
3527 dpyinfo->alt_mod_mask = 0;
3528 dpyinfo->super_mod_mask = 0;
3529 dpyinfo->hyper_mod_mask = 0;
3531 #ifdef HAVE_X11R4
3532 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3533 #else
3534 min_code = dpyinfo->display->min_keycode;
3535 max_code = dpyinfo->display->max_keycode;
3536 #endif
3538 syms = XGetKeyboardMapping (dpyinfo->display,
3539 min_code, max_code - min_code + 1,
3540 &syms_per_code);
3541 mods = XGetModifierMapping (dpyinfo->display);
3543 /* Scan the modifier table to see which modifier bits the Meta and
3544 Alt keysyms are on. */
3546 int row, col; /* The row and column in the modifier table. */
3548 for (row = 3; row < 8; row++)
3549 for (col = 0; col < mods->max_keypermod; col++)
3551 KeyCode code
3552 = mods->modifiermap[(row * mods->max_keypermod) + col];
3554 /* Zeroes are used for filler. Skip them. */
3555 if (code == 0)
3556 continue;
3558 /* Are any of this keycode's keysyms a meta key? */
3560 int code_col;
3562 for (code_col = 0; code_col < syms_per_code; code_col++)
3564 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3566 switch (sym)
3568 case XK_Meta_L:
3569 case XK_Meta_R:
3570 dpyinfo->meta_mod_mask |= (1 << row);
3571 break;
3573 case XK_Alt_L:
3574 case XK_Alt_R:
3575 dpyinfo->alt_mod_mask |= (1 << row);
3576 break;
3578 case XK_Hyper_L:
3579 case XK_Hyper_R:
3580 dpyinfo->hyper_mod_mask |= (1 << row);
3581 break;
3583 case XK_Super_L:
3584 case XK_Super_R:
3585 dpyinfo->super_mod_mask |= (1 << row);
3586 break;
3588 case XK_Shift_Lock:
3589 /* Ignore this if it's not on the lock modifier. */
3590 if ((1 << row) == LockMask)
3591 dpyinfo->shift_lock_mask = LockMask;
3592 break;
3599 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3600 if (! dpyinfo->meta_mod_mask)
3602 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3603 dpyinfo->alt_mod_mask = 0;
3606 /* If some keys are both alt and meta,
3607 make them just meta, not alt. */
3608 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3610 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3613 XFree ((char *) syms);
3614 XFreeModifiermap (mods);
3617 #endif /* MAC_TODO */
3619 /* Convert between the modifier bits X uses and the modifier bits
3620 Emacs uses. */
3622 static unsigned int
3623 x_mac_to_emacs_modifiers (dpyinfo, state)
3624 struct x_display_info *dpyinfo;
3625 unsigned short state;
3627 return (((state & shiftKey) ? shift_modifier : 0)
3628 | ((state & controlKey) ? ctrl_modifier : 0)
3629 | ((state & cmdKey) ? meta_modifier : 0)
3630 | ((state & optionKey) ? alt_modifier : 0));
3633 #if 0 /* MAC_TODO */
3634 static unsigned short
3635 x_emacs_to_x_modifiers (dpyinfo, state)
3636 struct x_display_info *dpyinfo;
3637 unsigned int state;
3639 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3640 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3641 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3642 | ((state & shift_modifier) ? ShiftMask : 0)
3643 | ((state & ctrl_modifier) ? ControlMask : 0)
3644 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3646 #endif /* MAC_TODO */
3648 /* Convert a keysym to its name. */
3650 char *
3651 x_get_keysym_name (keysym)
3652 int keysym;
3654 char *value;
3656 BLOCK_INPUT;
3657 #if 0
3658 value = XKeysymToString (keysym);
3659 #else
3660 value = 0;
3661 #endif
3662 UNBLOCK_INPUT;
3664 return value;
3669 /* Mouse clicks and mouse movement. Rah. */
3671 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3673 If the event is a button press, then note that we have grabbed
3674 the mouse. */
3676 static Lisp_Object
3677 construct_mouse_click (result, event, f)
3678 struct input_event *result;
3679 EventRecord *event;
3680 struct frame *f;
3682 Point mouseLoc;
3684 result->kind = MOUSE_CLICK_EVENT;
3685 result->code = 0; /* only one mouse button */
3686 result->timestamp = event->when;
3687 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3689 mouseLoc = event->where;
3691 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3693 GlobalToLocal (&mouseLoc);
3694 XSETINT (result->x, mouseLoc.h);
3695 XSETINT (result->y, mouseLoc.v);
3697 XSETFRAME (result->frame_or_window, f);
3699 result->arg = Qnil;
3700 return Qnil;
3704 /* Function to report a mouse movement to the mainstream Emacs code.
3705 The input handler calls this.
3707 We have received a mouse movement event, which is given in *event.
3708 If the mouse is over a different glyph than it was last time, tell
3709 the mainstream emacs code by setting mouse_moved. If not, ask for
3710 another motion event, so we can check again the next time it moves. */
3712 static Point last_mouse_motion_position;
3713 static Lisp_Object last_mouse_motion_frame;
3715 static void
3716 note_mouse_movement (frame, pos)
3717 FRAME_PTR frame;
3718 Point *pos;
3720 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3721 #if TARGET_API_MAC_CARBON
3722 Rect r;
3723 #endif
3725 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3726 last_mouse_motion_position = *pos;
3727 XSETFRAME (last_mouse_motion_frame, frame);
3729 #if TARGET_API_MAC_CARBON
3730 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3731 #else
3732 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3733 #endif
3735 if (frame == dpyinfo->mouse_face_mouse_frame)
3736 /* This case corresponds to LeaveNotify in X11. */
3738 /* If we move outside the frame, then we're certainly no
3739 longer on any text in the frame. */
3740 clear_mouse_face (dpyinfo);
3741 dpyinfo->mouse_face_mouse_frame = 0;
3742 if (!dpyinfo->grabbed)
3743 rif->define_frame_cursor (frame,
3744 frame->output_data.mac->nontext_cursor);
3747 /* Has the mouse moved off the glyph it was on at the last sighting? */
3748 else if (pos->h < last_mouse_glyph.left
3749 || pos->h >= last_mouse_glyph.right
3750 || pos->v < last_mouse_glyph.top
3751 || pos->v >= last_mouse_glyph.bottom)
3753 frame->mouse_moved = 1;
3754 last_mouse_scroll_bar = Qnil;
3755 note_mouse_highlight (frame, pos->h, pos->v);
3759 /* This is used for debugging, to turn off note_mouse_highlight. */
3761 int disable_mouse_highlight;
3765 /************************************************************************
3766 Mouse Face
3767 ************************************************************************/
3769 static struct scroll_bar *x_window_to_scroll_bar ();
3770 static void x_scroll_bar_report_motion ();
3771 static void x_check_fullscreen P_ ((struct frame *));
3772 static void x_check_fullscreen_move P_ ((struct frame *));
3773 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3776 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3778 static void
3779 redo_mouse_highlight ()
3781 if (!NILP (last_mouse_motion_frame)
3782 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3783 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3784 last_mouse_motion_position.h,
3785 last_mouse_motion_position.v);
3789 /* Try to determine frame pixel position and size of the glyph under
3790 frame pixel coordinates X/Y on frame F . Return the position and
3791 size in *RECT. Value is non-zero if we could compute these
3792 values. */
3794 static int
3795 glyph_rect (f, x, y, rect)
3796 struct frame *f;
3797 int x, y;
3798 Rect *rect;
3800 Lisp_Object window;
3802 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3804 if (!NILP (window))
3806 struct window *w = XWINDOW (window);
3807 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3808 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3810 for (; r < end && r->enabled_p; ++r)
3811 if (r->y <= y && r->y + r->height > y)
3813 /* Found the row at y. */
3814 struct glyph *g = r->glyphs[TEXT_AREA];
3815 struct glyph *end = g + r->used[TEXT_AREA];
3816 int gx;
3818 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3819 rect->bottom = rect->top + r->height;
3821 if (x < r->x)
3823 /* x is to the left of the first glyph in the row. */
3824 /* Shouldn't this be a pixel value?
3825 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3826 ++KFS */
3827 rect->left = WINDOW_LEFT_EDGE_COL (w);
3828 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3829 return 1;
3832 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3833 if (gx <= x && gx + g->pixel_width > x)
3835 /* x is on a glyph. */
3836 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3837 rect->right = rect->left + g->pixel_width;
3838 return 1;
3841 /* x is to the right of the last glyph in the row. */
3842 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3843 /* Shouldn't this be a pixel value?
3844 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3845 ++KFS */
3846 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3847 return 1;
3851 /* The y is not on any row. */
3852 return 0;
3855 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3857 /* Record the position of the mouse in last_mouse_glyph. */
3858 static void
3859 remember_mouse_glyph (f1, gx, gy)
3860 struct frame * f1;
3861 int gx, gy;
3863 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3865 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3866 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3868 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3869 round down even for negative values. */
3870 if (gx < 0)
3871 gx -= width - 1;
3872 if (gy < 0)
3873 gy -= height - 1;
3874 #if 0
3875 /* This was the original code from XTmouse_position, but it seems
3876 to give the position of the glyph diagonally next to the one
3877 the mouse is over. */
3878 gx = (gx + width - 1) / width * width;
3879 gy = (gy + height - 1) / height * height;
3880 #else
3881 gx = gx / width * width;
3882 gy = gy / height * height;
3883 #endif
3885 last_mouse_glyph.left = gx;
3886 last_mouse_glyph.top = gy;
3887 last_mouse_glyph.right = gx + width;
3888 last_mouse_glyph.bottom = gy + height;
3893 static WindowPtr
3894 front_emacs_window ()
3896 #if TARGET_API_MAC_CARBON
3897 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3899 while (wp && !is_emacs_window (wp))
3900 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3901 #else
3902 WindowPtr wp = FrontWindow ();
3904 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3905 wp = GetNextWindow (wp);
3906 #endif
3908 return wp;
3911 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3913 /* Return the current position of the mouse.
3914 *fp should be a frame which indicates which display to ask about.
3916 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3917 and *part to the frame, window, and scroll bar part that the mouse
3918 is over. Set *x and *y to the portion and whole of the mouse's
3919 position on the scroll bar.
3921 If the mouse movement started elsewhere, set *fp to the frame the
3922 mouse is on, *bar_window to nil, and *x and *y to the character cell
3923 the mouse is over.
3925 Set *time to the server time-stamp for the time at which the mouse
3926 was at this position.
3928 Don't store anything if we don't have a valid set of values to report.
3930 This clears the mouse_moved flag, so we can wait for the next mouse
3931 movement. */
3933 static void
3934 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3935 FRAME_PTR *fp;
3936 int insist;
3937 Lisp_Object *bar_window;
3938 enum scroll_bar_part *part;
3939 Lisp_Object *x, *y;
3940 unsigned long *time;
3942 Point mouse_pos;
3943 int ignore1, ignore2;
3944 WindowPtr wp = front_emacs_window ();
3945 struct frame *f;
3946 Lisp_Object frame, tail;
3948 if (is_emacs_window(wp))
3949 f = mac_window_to_frame (wp);
3951 BLOCK_INPUT;
3953 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3954 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3955 else
3957 /* Clear the mouse-moved flag for every frame on this display. */
3958 FOR_EACH_FRAME (tail, frame)
3959 XFRAME (frame)->mouse_moved = 0;
3961 last_mouse_scroll_bar = Qnil;
3963 SetPortWindowPort (wp);
3965 GetMouse (&mouse_pos);
3967 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3968 &last_mouse_glyph, insist);
3970 *bar_window = Qnil;
3971 *part = scroll_bar_handle;
3972 *fp = f;
3973 XSETINT (*x, mouse_pos.h);
3974 XSETINT (*y, mouse_pos.v);
3975 *time = last_mouse_movement_time;
3978 UNBLOCK_INPUT;
3982 /***********************************************************************
3983 Tool-bars
3984 ***********************************************************************/
3986 /* Handle mouse button event on the tool-bar of frame F, at
3987 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3988 or ButtonRelase. */
3990 static void
3991 mac_handle_tool_bar_click (f, button_event)
3992 struct frame *f;
3993 EventRecord *button_event;
3995 int x = button_event->where.h;
3996 int y = button_event->where.v;
3998 if (button_event->what == mouseDown)
3999 handle_tool_bar_click (f, x, y, 1, 0);
4000 else
4001 handle_tool_bar_click (f, x, y, 0,
4002 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
4003 button_event->modifiers));
4007 /************************************************************************
4008 Scroll bars, general
4009 ************************************************************************/
4011 /* Create a scroll bar and return the scroll bar vector for it. W is
4012 the Emacs window on which to create the scroll bar. TOP, LEFT,
4013 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4014 scroll bar. */
4016 static struct scroll_bar *
4017 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4018 struct window *w;
4019 int top, left, width, height, disp_top, disp_height;
4021 struct frame *f = XFRAME (w->frame);
4022 struct scroll_bar *bar
4023 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4024 Rect r;
4025 ControlHandle ch;
4027 BLOCK_INPUT;
4029 r.left = left;
4030 r.top = disp_top;
4031 r.right = left + width;
4032 r.bottom = disp_top + disp_height;
4034 #ifdef TARGET_API_MAC_CARBON
4035 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4036 kControlScrollBarProc, 0L);
4037 #else
4038 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4039 0L);
4040 #endif
4041 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4042 SetControlReference (ch, (long) bar);
4044 XSETWINDOW (bar->window, w);
4045 XSETINT (bar->top, top);
4046 XSETINT (bar->left, left);
4047 XSETINT (bar->width, width);
4048 XSETINT (bar->height, height);
4049 XSETINT (bar->start, 0);
4050 XSETINT (bar->end, 0);
4051 bar->dragging = Qnil;
4053 /* Add bar to its frame's list of scroll bars. */
4054 bar->next = FRAME_SCROLL_BARS (f);
4055 bar->prev = Qnil;
4056 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4057 if (!NILP (bar->next))
4058 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4060 UNBLOCK_INPUT;
4061 return bar;
4065 /* Draw BAR's handle in the proper position.
4067 If the handle is already drawn from START to END, don't bother
4068 redrawing it, unless REBUILD is non-zero; in that case, always
4069 redraw it. (REBUILD is handy for drawing the handle after expose
4070 events.)
4072 Normally, we want to constrain the start and end of the handle to
4073 fit inside its rectangle, but if the user is dragging the scroll
4074 bar handle, we want to let them drag it down all the way, so that
4075 the bar's top is as far down as it goes; otherwise, there's no way
4076 to move to the very end of the buffer. */
4078 static void
4079 x_scroll_bar_set_handle (bar, start, end, rebuild)
4080 struct scroll_bar *bar;
4081 int start, end;
4082 int rebuild;
4084 int dragging = ! NILP (bar->dragging);
4085 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4086 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4087 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4088 int length = end - start;
4090 /* If the display is already accurate, do nothing. */
4091 if (! rebuild
4092 && start == XINT (bar->start)
4093 && end == XINT (bar->end))
4094 return;
4096 BLOCK_INPUT;
4098 /* Make sure the values are reasonable, and try to preserve the
4099 distance between start and end. */
4100 if (start < 0)
4101 start = 0;
4102 else if (start > top_range)
4103 start = top_range;
4104 end = start + length;
4106 if (end < start)
4107 end = start;
4108 else if (end > top_range && ! dragging)
4109 end = top_range;
4111 /* Store the adjusted setting in the scroll bar. */
4112 XSETINT (bar->start, start);
4113 XSETINT (bar->end, end);
4115 /* Clip the end position, just for display. */
4116 if (end > top_range)
4117 end = top_range;
4119 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4120 top positions, to make sure the handle is always at least that
4121 many pixels tall. */
4122 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4124 SetControlMinimum (ch, 0);
4125 /* Don't inadvertently activate deactivated scroll bars */
4126 if (GetControlMaximum (ch) != -1)
4127 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4128 - (end - start));
4129 SetControlValue (ch, start);
4130 #if TARGET_API_MAC_CARBON
4131 SetControlViewSize (ch, end - start);
4132 #endif
4134 UNBLOCK_INPUT;
4138 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4139 nil. */
4141 static void
4142 x_scroll_bar_remove (bar)
4143 struct scroll_bar *bar;
4145 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4147 BLOCK_INPUT;
4149 /* Destroy the Mac scroll bar control */
4150 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4152 /* Disassociate this scroll bar from its window. */
4153 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4155 UNBLOCK_INPUT;
4158 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4159 that we are displaying PORTION characters out of a total of WHOLE
4160 characters, starting at POSITION. If WINDOW has no scroll bar,
4161 create one. */
4162 static void
4163 XTset_vertical_scroll_bar (w, portion, whole, position)
4164 struct window *w;
4165 int portion, whole, position;
4167 struct frame *f = XFRAME (w->frame);
4168 struct scroll_bar *bar;
4169 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4170 int window_y, window_height;
4172 /* Get window dimensions. */
4173 window_box (w, -1, 0, &window_y, 0, &window_height);
4174 top = window_y;
4175 #ifdef MAC_OSX
4176 width = 16;
4177 #else
4178 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4179 #endif
4180 height = window_height;
4182 /* Compute the left edge of the scroll bar area. */
4183 left = WINDOW_SCROLL_BAR_AREA_X (w);
4185 /* Compute the width of the scroll bar which might be less than
4186 the width of the area reserved for the scroll bar. */
4187 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4188 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4189 else
4190 sb_width = width;
4192 /* Compute the left edge of the scroll bar. */
4193 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4194 sb_left = left + width - sb_width - (width - sb_width) / 2;
4195 else
4196 sb_left = left + (width - sb_width) / 2;
4198 /* Adjustments according to Inside Macintosh to make it look nice */
4199 disp_top = top;
4200 disp_height = height;
4201 if (disp_top == 0)
4203 disp_top = -1;
4204 disp_height++;
4206 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4208 disp_top++;
4209 disp_height--;
4212 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4213 sb_left++;
4215 /* Does the scroll bar exist yet? */
4216 if (NILP (w->vertical_scroll_bar))
4218 BLOCK_INPUT;
4219 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4220 left, top, width, height, 0);
4221 UNBLOCK_INPUT;
4222 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4223 disp_height);
4224 XSETVECTOR (w->vertical_scroll_bar, bar);
4226 else
4228 /* It may just need to be moved and resized. */
4229 ControlHandle ch;
4231 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4232 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4234 BLOCK_INPUT;
4236 /* If already correctly positioned, do nothing. */
4237 if (XINT (bar->left) == sb_left
4238 && XINT (bar->top) == top
4239 && XINT (bar->width) == sb_width
4240 && XINT (bar->height) == height)
4241 Draw1Control (ch);
4242 else
4244 /* Clear areas not covered by the scroll bar because it's not as
4245 wide as the area reserved for it . This makes sure a
4246 previous mode line display is cleared after C-x 2 C-x 1, for
4247 example. */
4248 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4249 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4250 left, top, area_width, height, 0);
4252 #if 0
4253 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4254 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4255 sb_left - 1, top, 1, height, 0);
4256 #endif
4258 HideControl (ch);
4259 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4260 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4261 disp_height);
4262 ShowControl (ch);
4264 /* Remember new settings. */
4265 XSETINT (bar->left, sb_left);
4266 XSETINT (bar->top, top);
4267 XSETINT (bar->width, sb_width);
4268 XSETINT (bar->height, height);
4271 UNBLOCK_INPUT;
4274 /* Set the scroll bar's current state, unless we're currently being
4275 dragged. */
4276 if (NILP (bar->dragging))
4278 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4280 if (whole == 0)
4281 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4282 else
4284 int start = ((double) position * top_range) / whole;
4285 int end = ((double) (position + portion) * top_range) / whole;
4286 x_scroll_bar_set_handle (bar, start, end, 0);
4292 /* The following three hooks are used when we're doing a thorough
4293 redisplay of the frame. We don't explicitly know which scroll bars
4294 are going to be deleted, because keeping track of when windows go
4295 away is a real pain - "Can you say set-window-configuration, boys
4296 and girls?" Instead, we just assert at the beginning of redisplay
4297 that *all* scroll bars are to be removed, and then save a scroll bar
4298 from the fiery pit when we actually redisplay its window. */
4300 /* Arrange for all scroll bars on FRAME to be removed at the next call
4301 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4302 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4304 static void
4305 XTcondemn_scroll_bars (frame)
4306 FRAME_PTR frame;
4308 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4309 while (! NILP (FRAME_SCROLL_BARS (frame)))
4311 Lisp_Object bar;
4312 bar = FRAME_SCROLL_BARS (frame);
4313 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4314 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4315 XSCROLL_BAR (bar)->prev = Qnil;
4316 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4317 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4318 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4323 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4324 Note that WINDOW isn't necessarily condemned at all. */
4326 static void
4327 XTredeem_scroll_bar (window)
4328 struct window *window;
4330 struct scroll_bar *bar;
4332 /* We can't redeem this window's scroll bar if it doesn't have one. */
4333 if (NILP (window->vertical_scroll_bar))
4334 abort ();
4336 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4338 /* Unlink it from the condemned list. */
4340 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4342 if (NILP (bar->prev))
4344 /* If the prev pointer is nil, it must be the first in one of
4345 the lists. */
4346 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4347 /* It's not condemned. Everything's fine. */
4348 return;
4349 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4350 window->vertical_scroll_bar))
4351 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4352 else
4353 /* If its prev pointer is nil, it must be at the front of
4354 one or the other! */
4355 abort ();
4357 else
4358 XSCROLL_BAR (bar->prev)->next = bar->next;
4360 if (! NILP (bar->next))
4361 XSCROLL_BAR (bar->next)->prev = bar->prev;
4363 bar->next = FRAME_SCROLL_BARS (f);
4364 bar->prev = Qnil;
4365 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4366 if (! NILP (bar->next))
4367 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4371 /* Remove all scroll bars on FRAME that haven't been saved since the
4372 last call to `*condemn_scroll_bars_hook'. */
4374 static void
4375 XTjudge_scroll_bars (f)
4376 FRAME_PTR f;
4378 Lisp_Object bar, next;
4380 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4382 /* Clear out the condemned list now so we won't try to process any
4383 more events on the hapless scroll bars. */
4384 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4386 for (; ! NILP (bar); bar = next)
4388 struct scroll_bar *b = XSCROLL_BAR (bar);
4390 x_scroll_bar_remove (b);
4392 next = b->next;
4393 b->next = b->prev = Qnil;
4396 /* Now there should be no references to the condemned scroll bars,
4397 and they should get garbage-collected. */
4401 void
4402 activate_scroll_bars (frame)
4403 FRAME_PTR frame;
4405 Lisp_Object bar;
4406 ControlHandle ch;
4408 bar = FRAME_SCROLL_BARS (frame);
4409 while (! NILP (bar))
4411 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4412 #ifdef TARGET_API_MAC_CARBON
4413 ActivateControl (ch);
4414 #else
4415 SetControlMaximum (ch,
4416 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4417 XINT (XSCROLL_BAR (bar)
4418 ->height)) - 1);
4419 #endif
4420 bar = XSCROLL_BAR (bar)->next;
4425 void
4426 deactivate_scroll_bars (frame)
4427 FRAME_PTR frame;
4429 Lisp_Object bar;
4430 ControlHandle ch;
4432 bar = FRAME_SCROLL_BARS (frame);
4433 while (! NILP (bar))
4435 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4436 #ifdef TARGET_API_MAC_CARBON
4437 DeactivateControl (ch);
4438 #else
4439 SetControlMaximum (ch, XINT (-1));
4440 #endif
4441 bar = XSCROLL_BAR (bar)->next;
4445 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4446 is set to something other than NO_EVENT, it is enqueued.
4448 This may be called from a signal handler, so we have to ignore GC
4449 mark bits. */
4451 static void
4452 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4453 struct scroll_bar *bar;
4454 int part_code;
4455 EventRecord *er;
4456 struct input_event *bufp;
4458 int win_y, top_range;
4460 if (! GC_WINDOWP (bar->window))
4461 abort ();
4463 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4464 bufp->frame_or_window = bar->window;
4465 bufp->arg = Qnil;
4467 bar->dragging = Qnil;
4469 switch (part_code)
4471 case kControlUpButtonPart:
4472 bufp->part = scroll_bar_up_arrow;
4473 break;
4474 case kControlDownButtonPart:
4475 bufp->part = scroll_bar_down_arrow;
4476 break;
4477 case kControlPageUpPart:
4478 bufp->part = scroll_bar_above_handle;
4479 break;
4480 case kControlPageDownPart:
4481 bufp->part = scroll_bar_below_handle;
4482 break;
4483 #ifdef TARGET_API_MAC_CARBON
4484 default:
4485 #else
4486 case kControlIndicatorPart:
4487 #endif
4488 if (er->what == mouseDown)
4489 bar->dragging = make_number (0);
4490 XSETVECTOR (last_mouse_scroll_bar, bar);
4491 bufp->part = scroll_bar_handle;
4492 break;
4495 win_y = XINT (bufp->y) - XINT (bar->top);
4496 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4498 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4500 win_y -= 24;
4502 if (! NILP (bar->dragging))
4503 win_y -= XINT (bar->dragging);
4505 if (win_y < 0)
4506 win_y = 0;
4507 if (win_y > top_range)
4508 win_y = top_range;
4510 XSETINT (bufp->x, win_y);
4511 XSETINT (bufp->y, top_range);
4515 /* Handle some mouse motion while someone is dragging the scroll bar.
4517 This may be called from a signal handler, so we have to ignore GC
4518 mark bits. */
4520 static void
4521 x_scroll_bar_note_movement (bar, y_pos, t)
4522 struct scroll_bar *bar;
4523 int y_pos;
4524 Time t;
4526 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4528 last_mouse_movement_time = t;
4530 f->mouse_moved = 1;
4531 XSETVECTOR (last_mouse_scroll_bar, bar);
4533 /* If we're dragging the bar, display it. */
4534 if (! GC_NILP (bar->dragging))
4536 /* Where should the handle be now? */
4537 int new_start = y_pos - 24;
4539 if (new_start != XINT (bar->start))
4541 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4543 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4549 /* Return information to the user about the current position of the
4550 mouse on the scroll bar. */
4552 static void
4553 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4554 FRAME_PTR *fp;
4555 Lisp_Object *bar_window;
4556 enum scroll_bar_part *part;
4557 Lisp_Object *x, *y;
4558 unsigned long *time;
4560 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4561 WindowPtr wp = front_emacs_window ();
4562 Point mouse_pos;
4563 struct frame *f = mac_window_to_frame (wp);
4564 int win_y, top_range;
4566 SetPortWindowPort (wp);
4568 GetMouse (&mouse_pos);
4570 win_y = mouse_pos.v - XINT (bar->top);
4571 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4573 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4575 win_y -= 24;
4577 if (! NILP (bar->dragging))
4578 win_y -= XINT (bar->dragging);
4580 if (win_y < 0)
4581 win_y = 0;
4582 if (win_y > top_range)
4583 win_y = top_range;
4585 *fp = f;
4586 *bar_window = bar->window;
4588 if (! NILP (bar->dragging))
4589 *part = scroll_bar_handle;
4590 else if (win_y < XINT (bar->start))
4591 *part = scroll_bar_above_handle;
4592 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4593 *part = scroll_bar_handle;
4594 else
4595 *part = scroll_bar_below_handle;
4597 XSETINT (*x, win_y);
4598 XSETINT (*y, top_range);
4600 f->mouse_moved = 0;
4601 last_mouse_scroll_bar = Qnil;
4603 *time = last_mouse_movement_time;
4606 /***********************************************************************
4607 Text Cursor
4608 ***********************************************************************/
4610 /* Set clipping for output in glyph row ROW. W is the window in which
4611 we operate. GC is the graphics context to set clipping in.
4613 ROW may be a text row or, e.g., a mode line. Text rows must be
4614 clipped to the interior of the window dedicated to text display,
4615 mode lines must be clipped to the whole window. */
4617 static void
4618 x_clip_to_row (w, row, area, gc)
4619 struct window *w;
4620 struct glyph_row *row;
4621 int area;
4622 GC gc;
4624 struct frame *f = XFRAME (WINDOW_FRAME (w));
4625 Rect clip_rect;
4626 int window_x, window_y, window_width;
4628 window_box (w, area, &window_x, &window_y, &window_width, 0);
4630 clip_rect.left = window_x;
4631 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4632 clip_rect.top = max (clip_rect.top, window_y);
4633 clip_rect.right = clip_rect.left + window_width;
4634 clip_rect.bottom = clip_rect.top + row->visible_height;
4636 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4640 /* Draw a hollow box cursor on window W in glyph row ROW. */
4642 static void
4643 x_draw_hollow_cursor (w, row)
4644 struct window *w;
4645 struct glyph_row *row;
4647 struct frame *f = XFRAME (WINDOW_FRAME (w));
4648 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4649 Display *dpy = FRAME_MAC_DISPLAY (f);
4650 int x, y, wd, h;
4651 XGCValues xgcv;
4652 struct glyph *cursor_glyph;
4653 GC gc;
4655 /* Get the glyph the cursor is on. If we can't tell because
4656 the current matrix is invalid or such, give up. */
4657 cursor_glyph = get_phys_cursor_glyph (w);
4658 if (cursor_glyph == NULL)
4659 return;
4661 /* Compute the width of the rectangle to draw. If on a stretch
4662 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4663 rectangle as wide as the glyph, but use a canonical character
4664 width instead. */
4665 wd = cursor_glyph->pixel_width - 1;
4666 if (cursor_glyph->type == STRETCH_GLYPH
4667 && !x_stretch_cursor_p)
4668 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4669 w->phys_cursor_width = wd;
4671 /* Compute frame-relative coordinates from window-relative
4672 coordinates. */
4673 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4674 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4676 /* Compute the proper height and ascent of the rectangle, based
4677 on the actual glyph. Using the full height of the row looks
4678 bad when there are tall images on that row. */
4679 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4680 cursor_glyph->ascent + cursor_glyph->descent);
4681 if (h < row->height)
4682 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4683 h--;
4685 /* The foreground of cursor_gc is typically the same as the normal
4686 background color, which can cause the cursor box to be invisible. */
4687 xgcv.foreground = f->output_data.mac->cursor_pixel;
4688 if (dpyinfo->scratch_cursor_gc)
4689 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4690 else
4691 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4692 GCForeground, &xgcv);
4693 gc = dpyinfo->scratch_cursor_gc;
4695 /* Set clipping, draw the rectangle, and reset clipping again. */
4696 x_clip_to_row (w, row, TEXT_AREA, gc);
4697 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4698 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4702 /* Draw a bar cursor on window W in glyph row ROW.
4704 Implementation note: One would like to draw a bar cursor with an
4705 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4706 Unfortunately, I didn't find a font yet that has this property set.
4707 --gerd. */
4709 static void
4710 x_draw_bar_cursor (w, row, width, kind)
4711 struct window *w;
4712 struct glyph_row *row;
4713 int width;
4714 enum text_cursor_kinds kind;
4716 struct frame *f = XFRAME (w->frame);
4717 struct glyph *cursor_glyph;
4719 /* If cursor is out of bounds, don't draw garbage. This can happen
4720 in mini-buffer windows when switching between echo area glyphs
4721 and mini-buffer. */
4722 cursor_glyph = get_phys_cursor_glyph (w);
4723 if (cursor_glyph == NULL)
4724 return;
4726 /* If on an image, draw like a normal cursor. That's usually better
4727 visible than drawing a bar, esp. if the image is large so that
4728 the bar might not be in the window. */
4729 if (cursor_glyph->type == IMAGE_GLYPH)
4731 struct glyph_row *row;
4732 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4733 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4735 else
4737 Display *dpy = FRAME_MAC_DISPLAY (f);
4738 Window window = FRAME_MAC_WINDOW (f);
4739 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4740 unsigned long mask = GCForeground | GCBackground;
4741 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4742 XGCValues xgcv;
4744 /* If the glyph's background equals the color we normally draw
4745 the bar cursor in, the bar cursor in its normal color is
4746 invisible. Use the glyph's foreground color instead in this
4747 case, on the assumption that the glyph's colors are chosen so
4748 that the glyph is legible. */
4749 if (face->background == f->output_data.mac->cursor_pixel)
4750 xgcv.background = xgcv.foreground = face->foreground;
4751 else
4752 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4754 if (gc)
4755 XChangeGC (dpy, gc, mask, &xgcv);
4756 else
4758 gc = XCreateGC (dpy, window, mask, &xgcv);
4759 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4762 if (width < 0)
4763 width = FRAME_CURSOR_WIDTH (f);
4764 width = min (cursor_glyph->pixel_width, width);
4766 w->phys_cursor_width = width;
4767 x_clip_to_row (w, row, TEXT_AREA, gc);
4769 if (kind == BAR_CURSOR)
4770 XFillRectangle (dpy, window, gc,
4771 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4772 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4773 width, row->height);
4774 else
4775 XFillRectangle (dpy, window, gc,
4776 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4777 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4778 row->height - width),
4779 cursor_glyph->pixel_width,
4780 width);
4782 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4787 /* RIF: Define cursor CURSOR on frame F. */
4789 static void
4790 mac_define_frame_cursor (f, cursor)
4791 struct frame *f;
4792 Cursor cursor;
4794 #if TARGET_API_MAC_CARBON
4795 SetThemeCursor (cursor);
4796 #else
4797 SetCursor (*cursor);
4798 #endif
4802 /* RIF: Clear area on frame F. */
4804 static void
4805 mac_clear_frame_area (f, x, y, width, height)
4806 struct frame *f;
4807 int x, y, width, height;
4809 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4810 x, y, width, height, 0);
4814 /* RIF: Draw cursor on window W. */
4816 static void
4817 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4818 struct window *w;
4819 struct glyph_row *glyph_row;
4820 int x, y;
4821 int cursor_type, cursor_width;
4822 int on_p, active_p;
4824 if (on_p)
4826 w->phys_cursor_type = cursor_type;
4827 w->phys_cursor_on_p = 1;
4829 if (glyph_row->exact_window_width_line_p
4830 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4832 glyph_row->cursor_in_fringe_p = 1;
4833 draw_fringe_bitmap (w, glyph_row, 0);
4835 else
4836 switch (cursor_type)
4838 case HOLLOW_BOX_CURSOR:
4839 x_draw_hollow_cursor (w, glyph_row);
4840 break;
4842 case FILLED_BOX_CURSOR:
4843 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4844 break;
4846 case BAR_CURSOR:
4847 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4848 break;
4850 case HBAR_CURSOR:
4851 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4852 break;
4854 case NO_CURSOR:
4855 w->phys_cursor_width = 0;
4856 break;
4858 default:
4859 abort ();
4865 /* Icons. */
4867 #if 0 /* MAC_TODO: no icon support yet. */
4869 x_bitmap_icon (f, icon)
4870 struct frame *f;
4871 Lisp_Object icon;
4873 HANDLE hicon;
4875 if (FRAME_W32_WINDOW (f) == 0)
4876 return 1;
4878 if (NILP (icon))
4879 hicon = LoadIcon (hinst, EMACS_CLASS);
4880 else if (STRINGP (icon))
4881 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4882 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4883 else if (SYMBOLP (icon))
4885 LPCTSTR name;
4887 if (EQ (icon, intern ("application")))
4888 name = (LPCTSTR) IDI_APPLICATION;
4889 else if (EQ (icon, intern ("hand")))
4890 name = (LPCTSTR) IDI_HAND;
4891 else if (EQ (icon, intern ("question")))
4892 name = (LPCTSTR) IDI_QUESTION;
4893 else if (EQ (icon, intern ("exclamation")))
4894 name = (LPCTSTR) IDI_EXCLAMATION;
4895 else if (EQ (icon, intern ("asterisk")))
4896 name = (LPCTSTR) IDI_ASTERISK;
4897 else if (EQ (icon, intern ("winlogo")))
4898 name = (LPCTSTR) IDI_WINLOGO;
4899 else
4900 return 1;
4902 hicon = LoadIcon (NULL, name);
4904 else
4905 return 1;
4907 if (hicon == NULL)
4908 return 1;
4910 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4911 (LPARAM) hicon);
4913 return 0;
4915 #endif /* MAC_TODO */
4917 /************************************************************************
4918 Handling X errors
4919 ************************************************************************/
4921 /* Display Error Handling functions not used on W32. Listing them here
4922 helps diff stay in step when comparing w32term.c with xterm.c.
4924 x_error_catcher (display, error)
4925 x_catch_errors (dpy)
4926 x_catch_errors_unwind (old_val)
4927 x_check_errors (dpy, format)
4928 x_had_errors_p (dpy)
4929 x_clear_errors (dpy)
4930 x_uncatch_errors (dpy, count)
4931 x_trace_wire ()
4932 x_connection_signal (signalnum)
4933 x_connection_closed (dpy, error_message)
4934 x_error_quitter (display, error)
4935 x_error_handler (display, error)
4936 x_io_error_quitter (display)
4941 /* Changing the font of the frame. */
4943 /* Give frame F the font named FONTNAME as its default font, and
4944 return the full name of that font. FONTNAME may be a wildcard
4945 pattern; in that case, we choose some font that fits the pattern.
4946 The return value shows which font we chose. */
4948 Lisp_Object
4949 x_new_font (f, fontname)
4950 struct frame *f;
4951 register char *fontname;
4953 struct font_info *fontp
4954 = FS_LOAD_FONT (f, 0, fontname, -1);
4956 if (!fontp)
4957 return Qnil;
4959 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4960 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4961 FRAME_FONTSET (f) = -1;
4963 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4964 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4966 compute_fringe_widths (f, 1);
4968 /* Compute the scroll bar width in character columns. */
4969 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4971 int wid = FRAME_COLUMN_WIDTH (f);
4972 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4973 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4975 else
4977 int wid = FRAME_COLUMN_WIDTH (f);
4978 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4981 /* Now make the frame display the given font. */
4982 if (FRAME_MAC_WINDOW (f) != 0)
4984 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4985 FRAME_FONT (f));
4986 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4987 FRAME_FONT (f));
4988 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4989 FRAME_FONT (f));
4991 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4992 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4995 return build_string (fontp->full_name);
4998 /* Give frame F the fontset named FONTSETNAME as its default font, and
4999 return the full name of that fontset. FONTSETNAME may be a wildcard
5000 pattern; in that case, we choose some fontset that fits the pattern.
5001 The return value shows which fontset we chose. */
5003 Lisp_Object
5004 x_new_fontset (f, fontsetname)
5005 struct frame *f;
5006 char *fontsetname;
5008 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5009 Lisp_Object result;
5011 if (fontset < 0)
5012 return Qnil;
5014 if (FRAME_FONTSET (f) == fontset)
5015 /* This fontset is already set in frame F. There's nothing more
5016 to do. */
5017 return fontset_name (fontset);
5019 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5021 if (!STRINGP (result))
5022 /* Can't load ASCII font. */
5023 return Qnil;
5025 /* Since x_new_font doesn't update any fontset information, do it now. */
5026 FRAME_FONTSET(f) = fontset;
5028 return build_string (fontsetname);
5032 /***********************************************************************
5033 TODO: W32 Input Methods
5034 ***********************************************************************/
5035 /* Listing missing functions from xterm.c helps diff stay in step.
5037 xim_destroy_callback (xim, client_data, call_data)
5038 xim_open_dpy (dpyinfo, resource_name)
5039 struct xim_inst_t
5040 xim_instantiate_callback (display, client_data, call_data)
5041 xim_initialize (dpyinfo, resource_name)
5042 xim_close_dpy (dpyinfo)
5047 void
5048 mac_get_window_bounds (f, inner, outer)
5049 struct frame *f;
5050 Rect *inner, *outer;
5052 #if TARGET_API_MAC_CARBON
5053 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5054 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5055 #else /* not TARGET_API_MAC_CARBON */
5056 RgnHandle region = NewRgn ();
5058 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5059 *inner = (*region)->rgnBBox;
5060 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5061 *outer = (*region)->rgnBBox;
5062 DisposeRgn (region);
5063 #endif /* not TARGET_API_MAC_CARBON */
5067 /* Calculate the absolute position in frame F
5068 from its current recorded position values and gravity. */
5070 void
5071 x_calc_absolute_position (f)
5072 struct frame *f;
5074 int width_diff = 0, height_diff = 0;
5075 int flags = f->size_hint_flags;
5076 Rect inner, outer;
5078 /* We have nothing to do if the current position
5079 is already for the top-left corner. */
5080 if (! ((flags & XNegative) || (flags & YNegative)))
5081 return;
5083 /* Find the offsets of the outside upper-left corner of
5084 the inner window, with respect to the outer window. */
5085 mac_get_window_bounds (f, &inner, &outer);
5087 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5088 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5090 /* Treat negative positions as relative to the leftmost bottommost
5091 position that fits on the screen. */
5092 if (flags & XNegative)
5093 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5094 - width_diff
5095 - FRAME_PIXEL_WIDTH (f)
5096 + f->left_pos);
5098 if (flags & YNegative)
5099 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5100 - height_diff
5101 - FRAME_PIXEL_HEIGHT (f)
5102 + f->top_pos);
5104 /* The left_pos and top_pos
5105 are now relative to the top and left screen edges,
5106 so the flags should correspond. */
5107 f->size_hint_flags &= ~ (XNegative | YNegative);
5110 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5111 to really change the position, and 0 when calling from
5112 x_make_frame_visible (in that case, XOFF and YOFF are the current
5113 position values). It is -1 when calling from x_set_frame_parameters,
5114 which means, do adjust for borders but don't change the gravity. */
5116 void
5117 x_set_offset (f, xoff, yoff, change_gravity)
5118 struct frame *f;
5119 register int xoff, yoff;
5120 int change_gravity;
5122 if (change_gravity > 0)
5124 f->top_pos = yoff;
5125 f->left_pos = xoff;
5126 f->size_hint_flags &= ~ (XNegative | YNegative);
5127 if (xoff < 0)
5128 f->size_hint_flags |= XNegative;
5129 if (yoff < 0)
5130 f->size_hint_flags |= YNegative;
5131 f->win_gravity = NorthWestGravity;
5133 x_calc_absolute_position (f);
5135 BLOCK_INPUT;
5136 x_wm_set_size_hint (f, (long) 0, 0);
5138 #if TARGET_API_MAC_CARBON
5139 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5140 /* If the title bar is completely outside the screen, adjust the
5141 position. */
5142 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5143 kWindowConstrainMoveRegardlessOfFit
5144 | kWindowConstrainAllowPartial, NULL, NULL);
5145 x_real_positions (f, &f->left_pos, &f->top_pos);
5146 #else
5148 Rect inner, outer, screen_rect, dummy;
5149 RgnHandle region = NewRgn ();
5151 mac_get_window_bounds (f, &inner, &outer);
5152 f->x_pixels_diff = inner.left - outer.left;
5153 f->y_pixels_diff = inner.top - outer.top;
5154 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5155 f->top_pos + f->y_pixels_diff, false);
5157 /* If the title bar is completely outside the screen, adjust the
5158 position. The variable `outer' holds the title bar rectangle.
5159 The variable `inner' holds slightly smaller one than `outer',
5160 so that the calculation of overlapping may not become too
5161 strict. */
5162 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5163 outer = (*region)->rgnBBox;
5164 DisposeRgn (region);
5165 inner = outer;
5166 InsetRect (&inner, 8, 8);
5167 screen_rect = qd.screenBits.bounds;
5168 screen_rect.top += GetMBarHeight ();
5170 if (!SectRect (&inner, &screen_rect, &dummy))
5172 if (inner.right <= screen_rect.left)
5173 f->left_pos = screen_rect.left;
5174 else if (inner.left >= screen_rect.right)
5175 f->left_pos = screen_rect.right - (outer.right - outer.left);
5177 if (inner.bottom <= screen_rect.top)
5178 f->top_pos = screen_rect.top;
5179 else if (inner.top >= screen_rect.bottom)
5180 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5182 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5183 f->top_pos + f->y_pixels_diff, false);
5186 #endif
5188 UNBLOCK_INPUT;
5191 /* Call this to change the size of frame F's x-window.
5192 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5193 for this size change and subsequent size changes.
5194 Otherwise we leave the window gravity unchanged. */
5196 void
5197 x_set_window_size (f, change_gravity, cols, rows)
5198 struct frame *f;
5199 int change_gravity;
5200 int cols, rows;
5202 int pixelwidth, pixelheight;
5204 BLOCK_INPUT;
5206 check_frame_size (f, &rows, &cols);
5207 f->scroll_bar_actual_width
5208 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5210 compute_fringe_widths (f, 0);
5212 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5213 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5215 f->win_gravity = NorthWestGravity;
5216 x_wm_set_size_hint (f, (long) 0, 0);
5218 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5220 /* Now, strictly speaking, we can't be sure that this is accurate,
5221 but the window manager will get around to dealing with the size
5222 change request eventually, and we'll hear how it went when the
5223 ConfigureNotify event gets here.
5225 We could just not bother storing any of this information here,
5226 and let the ConfigureNotify event set everything up, but that
5227 might be kind of confusing to the Lisp code, since size changes
5228 wouldn't be reported in the frame parameters until some random
5229 point in the future when the ConfigureNotify event arrives.
5231 We pass 1 for DELAY since we can't run Lisp code inside of
5232 a BLOCK_INPUT. */
5233 change_frame_size (f, rows, cols, 0, 1, 0);
5234 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5235 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5237 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5238 receive in the ConfigureNotify event; if we get what we asked
5239 for, then the event won't cause the screen to become garbaged, so
5240 we have to make sure to do it here. */
5241 SET_FRAME_GARBAGED (f);
5243 XFlush (FRAME_X_DISPLAY (f));
5245 /* If cursor was outside the new size, mark it as off. */
5246 mark_window_cursors_off (XWINDOW (f->root_window));
5248 /* Clear out any recollection of where the mouse highlighting was,
5249 since it might be in a place that's outside the new frame size.
5250 Actually checking whether it is outside is a pain in the neck,
5251 so don't try--just let the highlighting be done afresh with new size. */
5252 cancel_mouse_face (f);
5254 UNBLOCK_INPUT;
5257 /* Mouse warping. */
5259 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5261 void
5262 x_set_mouse_position (f, x, y)
5263 struct frame *f;
5264 int x, y;
5266 int pix_x, pix_y;
5268 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5269 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5271 if (pix_x < 0) pix_x = 0;
5272 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5274 if (pix_y < 0) pix_y = 0;
5275 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5277 x_set_mouse_pixel_position (f, pix_x, pix_y);
5280 void
5281 x_set_mouse_pixel_position (f, pix_x, pix_y)
5282 struct frame *f;
5283 int pix_x, pix_y;
5285 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5286 BLOCK_INPUT;
5288 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5289 0, 0, 0, 0, pix_x, pix_y);
5290 UNBLOCK_INPUT;
5291 #endif
5295 /* focus shifting, raising and lowering. */
5297 void
5298 x_focus_on_frame (f)
5299 struct frame *f;
5301 #if 0 /* This proves to be unpleasant. */
5302 x_raise_frame (f);
5303 #endif
5304 #if 0
5305 /* I don't think that the ICCCM allows programs to do things like this
5306 without the interaction of the window manager. Whatever you end up
5307 doing with this code, do it to x_unfocus_frame too. */
5308 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5309 RevertToPointerRoot, CurrentTime);
5310 #endif /* ! 0 */
5313 void
5314 x_unfocus_frame (f)
5315 struct frame *f;
5319 /* Raise frame F. */
5320 void
5321 x_raise_frame (f)
5322 struct frame *f;
5324 if (f->async_visible)
5326 BLOCK_INPUT;
5327 SelectWindow (FRAME_MAC_WINDOW (f));
5328 UNBLOCK_INPUT;
5332 /* Lower frame F. */
5333 void
5334 x_lower_frame (f)
5335 struct frame *f;
5337 if (f->async_visible)
5339 BLOCK_INPUT;
5340 SendBehind (FRAME_MAC_WINDOW (f), nil);
5341 UNBLOCK_INPUT;
5345 static void
5346 XTframe_raise_lower (f, raise_flag)
5347 FRAME_PTR f;
5348 int raise_flag;
5350 if (raise_flag)
5351 x_raise_frame (f);
5352 else
5353 x_lower_frame (f);
5356 /* Change of visibility. */
5358 /* This tries to wait until the frame is really visible.
5359 However, if the window manager asks the user where to position
5360 the frame, this will return before the user finishes doing that.
5361 The frame will not actually be visible at that time,
5362 but it will become visible later when the window manager
5363 finishes with it. */
5365 void
5366 x_make_frame_visible (f)
5367 struct frame *f;
5369 Lisp_Object type;
5370 int original_top, original_left;
5372 BLOCK_INPUT;
5374 if (! FRAME_VISIBLE_P (f))
5376 /* We test FRAME_GARBAGED_P here to make sure we don't
5377 call x_set_offset a second time
5378 if we get to x_make_frame_visible a second time
5379 before the window gets really visible. */
5380 if (! FRAME_ICONIFIED_P (f)
5381 && ! f->output_data.mac->asked_for_visible)
5382 x_set_offset (f, f->left_pos, f->top_pos, 0);
5384 f->output_data.mac->asked_for_visible = 1;
5386 ShowWindow (FRAME_MAC_WINDOW (f));
5389 XFlush (FRAME_MAC_DISPLAY (f));
5391 /* Synchronize to ensure Emacs knows the frame is visible
5392 before we do anything else. We do this loop with input not blocked
5393 so that incoming events are handled. */
5395 Lisp_Object frame;
5396 int count;
5398 /* This must come after we set COUNT. */
5399 UNBLOCK_INPUT;
5401 XSETFRAME (frame, f);
5403 /* Wait until the frame is visible. Process X events until a
5404 MapNotify event has been seen, or until we think we won't get a
5405 MapNotify at all.. */
5406 for (count = input_signal_count + 10;
5407 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5409 /* Force processing of queued events. */
5410 x_sync (f);
5412 /* Machines that do polling rather than SIGIO have been
5413 observed to go into a busy-wait here. So we'll fake an
5414 alarm signal to let the handler know that there's something
5415 to be read. We used to raise a real alarm, but it seems
5416 that the handler isn't always enabled here. This is
5417 probably a bug. */
5418 if (input_polling_used ())
5420 /* It could be confusing if a real alarm arrives while
5421 processing the fake one. Turn it off and let the
5422 handler reset it. */
5423 extern void poll_for_input_1 P_ ((void));
5424 int old_poll_suppress_count = poll_suppress_count;
5425 poll_suppress_count = 1;
5426 poll_for_input_1 ();
5427 poll_suppress_count = old_poll_suppress_count;
5430 /* See if a MapNotify event has been processed. */
5431 FRAME_SAMPLE_VISIBILITY (f);
5436 /* Change from mapped state to withdrawn state. */
5438 /* Make the frame visible (mapped and not iconified). */
5440 void
5441 x_make_frame_invisible (f)
5442 struct frame *f;
5444 /* Don't keep the highlight on an invisible frame. */
5445 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5446 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5448 BLOCK_INPUT;
5450 HideWindow (FRAME_MAC_WINDOW (f));
5452 /* We can't distinguish this from iconification
5453 just by the event that we get from the server.
5454 So we can't win using the usual strategy of letting
5455 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5456 and synchronize with the server to make sure we agree. */
5457 f->visible = 0;
5458 FRAME_ICONIFIED_P (f) = 0;
5459 f->async_visible = 0;
5460 f->async_iconified = 0;
5462 UNBLOCK_INPUT;
5465 /* Change window state from mapped to iconified. */
5467 void
5468 x_iconify_frame (f)
5469 struct frame *f;
5471 /* Don't keep the highlight on an invisible frame. */
5472 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5473 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5475 #if 0
5476 /* Review: Since window is still visible in dock, still allow updates? */
5477 if (f->async_iconified)
5478 return;
5479 #endif
5481 BLOCK_INPUT;
5483 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5485 UNBLOCK_INPUT;
5489 /* Free X resources of frame F. */
5491 void
5492 x_free_frame_resources (f)
5493 struct frame *f;
5495 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5496 WindowPtr wp = FRAME_MAC_WINDOW (f);
5498 BLOCK_INPUT;
5500 DisposeWindow (wp);
5501 if (wp == tip_window)
5502 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5503 closed' event. So we reset tip_window here. */
5504 tip_window = NULL;
5506 free_frame_menubar (f);
5508 if (FRAME_FACE_CACHE (f))
5509 free_frame_faces (f);
5511 x_free_gcs (f);
5513 xfree (f->output_data.mac);
5514 f->output_data.mac = NULL;
5516 if (f == dpyinfo->x_focus_frame)
5517 dpyinfo->x_focus_frame = 0;
5518 if (f == dpyinfo->x_focus_event_frame)
5519 dpyinfo->x_focus_event_frame = 0;
5520 if (f == dpyinfo->x_highlight_frame)
5521 dpyinfo->x_highlight_frame = 0;
5523 if (f == dpyinfo->mouse_face_mouse_frame)
5525 dpyinfo->mouse_face_beg_row
5526 = dpyinfo->mouse_face_beg_col = -1;
5527 dpyinfo->mouse_face_end_row
5528 = dpyinfo->mouse_face_end_col = -1;
5529 dpyinfo->mouse_face_window = Qnil;
5530 dpyinfo->mouse_face_deferred_gc = 0;
5531 dpyinfo->mouse_face_mouse_frame = 0;
5534 UNBLOCK_INPUT;
5538 /* Destroy the X window of frame F. */
5540 void
5541 x_destroy_window (f)
5542 struct frame *f;
5544 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5546 x_free_frame_resources (f);
5548 dpyinfo->reference_count--;
5552 /* Setting window manager hints. */
5554 /* Set the normal size hints for the window manager, for frame F.
5555 FLAGS is the flags word to use--or 0 meaning preserve the flags
5556 that the window now has.
5557 If USER_POSITION is nonzero, we set the USPosition
5558 flag (this is useful when FLAGS is 0). */
5559 void
5560 x_wm_set_size_hint (f, flags, user_position)
5561 struct frame *f;
5562 long flags;
5563 int user_position;
5565 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5566 XSizeHints size_hints;
5568 #ifdef USE_X_TOOLKIT
5569 Arg al[2];
5570 int ac = 0;
5571 Dimension widget_width, widget_height;
5572 Window window = XtWindow (f->output_data.x->widget);
5573 #else /* not USE_X_TOOLKIT */
5574 Window window = FRAME_X_WINDOW (f);
5575 #endif /* not USE_X_TOOLKIT */
5577 /* Setting PMaxSize caused various problems. */
5578 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5580 size_hints.x = f->left_pos;
5581 size_hints.y = f->top_pos;
5583 #ifdef USE_X_TOOLKIT
5584 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5585 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5586 XtGetValues (f->output_data.x->widget, al, ac);
5587 size_hints.height = widget_height;
5588 size_hints.width = widget_width;
5589 #else /* not USE_X_TOOLKIT */
5590 size_hints.height = FRAME_PIXEL_HEIGHT (f);
5591 size_hints.width = FRAME_PIXEL_WIDTH (f);
5592 #endif /* not USE_X_TOOLKIT */
5594 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
5595 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
5596 size_hints.max_width
5597 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5598 size_hints.max_height
5599 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5601 /* Calculate the base and minimum sizes.
5603 (When we use the X toolkit, we don't do it here.
5604 Instead we copy the values that the widgets are using, below.) */
5605 #ifndef USE_X_TOOLKIT
5607 int base_width, base_height;
5608 int min_rows = 0, min_cols = 0;
5610 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5611 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5613 check_frame_size (f, &min_rows, &min_cols);
5615 /* The window manager uses the base width hints to calculate the
5616 current number of rows and columns in the frame while
5617 resizing; min_width and min_height aren't useful for this
5618 purpose, since they might not give the dimensions for a
5619 zero-row, zero-column frame.
5621 We use the base_width and base_height members if we have
5622 them; otherwise, we set the min_width and min_height members
5623 to the size for a zero x zero frame. */
5625 #ifdef HAVE_X11R4
5626 size_hints.flags |= PBaseSize;
5627 size_hints.base_width = base_width;
5628 size_hints.base_height = base_height;
5629 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5630 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5631 #else
5632 size_hints.min_width = base_width;
5633 size_hints.min_height = base_height;
5634 #endif
5637 /* If we don't need the old flags, we don't need the old hint at all. */
5638 if (flags)
5640 size_hints.flags |= flags;
5641 goto no_read;
5643 #endif /* not USE_X_TOOLKIT */
5646 XSizeHints hints; /* Sometimes I hate X Windows... */
5647 long supplied_return;
5648 int value;
5650 #ifdef HAVE_X11R4
5651 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5652 &supplied_return);
5653 #else
5654 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5655 #endif
5657 #ifdef USE_X_TOOLKIT
5658 size_hints.base_height = hints.base_height;
5659 size_hints.base_width = hints.base_width;
5660 size_hints.min_height = hints.min_height;
5661 size_hints.min_width = hints.min_width;
5662 #endif
5664 if (flags)
5665 size_hints.flags |= flags;
5666 else
5668 if (value == 0)
5669 hints.flags = 0;
5670 if (hints.flags & PSize)
5671 size_hints.flags |= PSize;
5672 if (hints.flags & PPosition)
5673 size_hints.flags |= PPosition;
5674 if (hints.flags & USPosition)
5675 size_hints.flags |= USPosition;
5676 if (hints.flags & USSize)
5677 size_hints.flags |= USSize;
5681 #ifndef USE_X_TOOLKIT
5682 no_read:
5683 #endif
5685 #ifdef PWinGravity
5686 size_hints.win_gravity = f->win_gravity;
5687 size_hints.flags |= PWinGravity;
5689 if (user_position)
5691 size_hints.flags &= ~ PPosition;
5692 size_hints.flags |= USPosition;
5694 #endif /* PWinGravity */
5696 #ifdef HAVE_X11R4
5697 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5698 #else
5699 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5700 #endif
5701 #endif /* MAC_TODO */
5704 #if 0 /* MAC_TODO: hide application instead of iconify? */
5705 /* Used for IconicState or NormalState */
5707 void
5708 x_wm_set_window_state (f, state)
5709 struct frame *f;
5710 int state;
5712 #ifdef USE_X_TOOLKIT
5713 Arg al[1];
5715 XtSetArg (al[0], XtNinitialState, state);
5716 XtSetValues (f->output_data.x->widget, al, 1);
5717 #else /* not USE_X_TOOLKIT */
5718 Window window = FRAME_X_WINDOW (f);
5720 f->output_data.x->wm_hints.flags |= StateHint;
5721 f->output_data.x->wm_hints.initial_state = state;
5723 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5724 #endif /* not USE_X_TOOLKIT */
5727 void
5728 x_wm_set_icon_pixmap (f, pixmap_id)
5729 struct frame *f;
5730 int pixmap_id;
5732 Pixmap icon_pixmap;
5734 #ifndef USE_X_TOOLKIT
5735 Window window = FRAME_X_WINDOW (f);
5736 #endif
5738 if (pixmap_id > 0)
5740 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5741 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5743 else
5745 /* It seems there is no way to turn off use of an icon pixmap.
5746 The following line does it, only if no icon has yet been created,
5747 for some window managers. But with mwm it crashes.
5748 Some people say it should clear the IconPixmapHint bit in this case,
5749 but that doesn't work, and the X consortium said it isn't the
5750 right thing at all. Since there is no way to win,
5751 best to explicitly give up. */
5752 #if 0
5753 f->output_data.x->wm_hints.icon_pixmap = None;
5754 #else
5755 return;
5756 #endif
5759 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5762 Arg al[1];
5763 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5764 XtSetValues (f->output_data.x->widget, al, 1);
5767 #else /* not USE_X_TOOLKIT */
5769 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5770 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5772 #endif /* not USE_X_TOOLKIT */
5775 #endif /* MAC_TODO */
5777 void
5778 x_wm_set_icon_position (f, icon_x, icon_y)
5779 struct frame *f;
5780 int icon_x, icon_y;
5782 #if 0 /* MAC_TODO: no icons on Mac */
5783 #ifdef USE_X_TOOLKIT
5784 Window window = XtWindow (f->output_data.x->widget);
5785 #else
5786 Window window = FRAME_X_WINDOW (f);
5787 #endif
5789 f->output_data.x->wm_hints.flags |= IconPositionHint;
5790 f->output_data.x->wm_hints.icon_x = icon_x;
5791 f->output_data.x->wm_hints.icon_y = icon_y;
5793 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5794 #endif /* MAC_TODO */
5798 /***********************************************************************
5799 Fonts
5800 ***********************************************************************/
5802 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5804 struct font_info *
5805 x_get_font_info (f, font_idx)
5806 FRAME_PTR f;
5807 int font_idx;
5809 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5812 /* the global font name table */
5813 char **font_name_table = NULL;
5814 int font_name_table_size = 0;
5815 int font_name_count = 0;
5817 #if 0
5818 /* compare two strings ignoring case */
5819 static int
5820 stricmp (const char *s, const char *t)
5822 for ( ; tolower (*s) == tolower (*t); s++, t++)
5823 if (*s == '\0')
5824 return 0;
5825 return tolower (*s) - tolower (*t);
5828 /* compare two strings ignoring case and handling wildcard */
5829 static int
5830 wildstrieq (char *s1, char *s2)
5832 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5833 return true;
5835 return stricmp (s1, s2) == 0;
5838 /* Assume parameter 1 is fully qualified, no wildcards. */
5839 static int
5840 mac_font_pattern_match (fontname, pattern)
5841 char * fontname;
5842 char * pattern;
5844 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5845 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5846 char *ptr;
5848 /* Copy fontname so we can modify it during comparison. */
5849 strcpy (font_name_copy, fontname);
5851 ptr = regex;
5852 *ptr++ = '^';
5854 /* Turn pattern into a regexp and do a regexp match. */
5855 for (; *pattern; pattern++)
5857 if (*pattern == '?')
5858 *ptr++ = '.';
5859 else if (*pattern == '*')
5861 *ptr++ = '.';
5862 *ptr++ = '*';
5864 else
5865 *ptr++ = *pattern;
5867 *ptr = '$';
5868 *(ptr + 1) = '\0';
5870 return (fast_c_string_match_ignore_case (build_string (regex),
5871 font_name_copy) >= 0);
5874 /* Two font specs are considered to match if their foundry, family,
5875 weight, slant, and charset match. */
5876 static int
5877 mac_font_match (char *mf, char *xf)
5879 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5880 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5882 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5883 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5884 return mac_font_pattern_match (mf, xf);
5886 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5887 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5888 return mac_font_pattern_match (mf, xf);
5890 return (wildstrieq (m_foundry, x_foundry)
5891 && wildstrieq (m_family, x_family)
5892 && wildstrieq (m_weight, x_weight)
5893 && wildstrieq (m_slant, x_slant)
5894 && wildstrieq (m_charset, x_charset))
5895 || mac_font_pattern_match (mf, xf);
5897 #endif
5899 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5901 static void
5902 decode_mac_font_name (char *name, int size, short scriptcode)
5904 Lisp_Object coding_system;
5905 struct coding_system coding;
5906 char *buf;
5908 switch (scriptcode)
5910 case smTradChinese:
5911 coding_system = Qbig5;
5912 break;
5913 case smSimpChinese:
5914 coding_system = Qcn_gb;
5915 break;
5916 case smJapanese:
5917 coding_system = Qsjis;
5918 break;
5919 case smKorean:
5920 coding_system = Qeuc_kr;
5921 break;
5922 default:
5923 return;
5926 setup_coding_system (coding_system, &coding);
5927 coding.src_multibyte = 0;
5928 coding.dst_multibyte = 1;
5929 coding.mode |= CODING_MODE_LAST_BLOCK;
5930 coding.composing = COMPOSITION_DISABLED;
5931 buf = (char *) alloca (size);
5933 decode_coding (&coding, name, buf, strlen (name), size - 1);
5934 bcopy (buf, name, coding.produced);
5935 name[coding.produced] = '\0';
5939 static char *
5940 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
5942 char foundry[32], family[32], cs[32];
5943 char xf[256], *result, *p;
5945 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5947 strcpy(foundry, "Apple");
5948 strcpy(family, name);
5950 switch (scriptcode)
5952 case smTradChinese:
5953 strcpy(cs, "big5-0");
5954 break;
5955 case smSimpChinese:
5956 strcpy(cs, "gb2312.1980-0");
5957 break;
5958 case smJapanese:
5959 strcpy(cs, "jisx0208.1983-sjis");
5960 break;
5961 case -smJapanese:
5962 /* Each Apple Japanese font is entered into the font table
5963 twice: once as a jisx0208.1983-sjis font and once as a
5964 jisx0201.1976-0 font. The latter can be used to display
5965 the ascii charset and katakana-jisx0201 charset. A
5966 negative script code signals that the name of this latter
5967 font is being built. */
5968 strcpy(cs, "jisx0201.1976-0");
5969 break;
5970 case smKorean:
5971 strcpy(cs, "ksc5601.1989-0");
5972 break;
5973 default:
5974 strcpy(cs, "mac-roman");
5975 break;
5979 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5980 foundry, family, style & bold ? "bold" : "medium",
5981 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5983 result = (char *) xmalloc (strlen (xf) + 1);
5984 strcpy (result, xf);
5985 for (p = result; *p; p++)
5986 *p = tolower(*p);
5987 return result;
5991 /* Convert an X font spec to the corresponding mac font name, which
5992 can then be passed to GetFNum after conversion to a Pascal string.
5993 For ordinary Mac fonts, this should just be their names, like
5994 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5995 collection contain their charset designation in their names, like
5996 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5997 names are handled accordingly. */
5998 static void
5999 x_font_name_to_mac_font_name (char *xf, char *mf)
6001 char foundry[32], family[32], weight[20], slant[2], cs[32];
6002 Lisp_Object coding_system = Qnil;
6003 struct coding_system coding;
6005 strcpy (mf, "");
6007 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6008 foundry, family, weight, slant, cs) != 5 &&
6009 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6010 foundry, family, weight, slant, cs) != 5)
6011 return;
6013 if (strcmp (cs, "big5-0") == 0)
6014 coding_system = Qbig5;
6015 else if (strcmp (cs, "gb2312.1980-0") == 0)
6016 coding_system = Qcn_gb;
6017 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
6018 || strcmp (cs, "jisx0201.1976-0") == 0)
6019 coding_system = Qsjis;
6020 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6021 coding_system = Qeuc_kr;
6022 else if (strcmp (cs, "mac-roman") == 0)
6023 strcpy (mf, family);
6024 else
6025 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6027 if (!NILP (coding_system))
6029 setup_coding_system (coding_system, &coding);
6030 coding.src_multibyte = 1;
6031 coding.dst_multibyte = 1;
6032 coding.mode |= CODING_MODE_LAST_BLOCK;
6033 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6034 mf[coding.produced] = '\0';
6039 static void
6040 add_font_name_table_entry (char *font_name)
6042 if (font_name_table_size == 0)
6044 font_name_table_size = 16;
6045 font_name_table = (char **)
6046 xmalloc (font_name_table_size * sizeof (char *));
6048 else if (font_name_count + 1 >= font_name_table_size)
6050 font_name_table_size += 16;
6051 font_name_table = (char **)
6052 xrealloc (font_name_table,
6053 font_name_table_size * sizeof (char *));
6056 font_name_table[font_name_count++] = font_name;
6059 /* Sets up the table font_name_table to contain the list of all fonts
6060 in the system the first time the table is used so that the Resource
6061 Manager need not be accessed every time this information is
6062 needed. */
6064 static void
6065 init_font_name_table ()
6067 #if TARGET_API_MAC_CARBON
6068 SInt32 sv;
6070 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6072 FMFontFamilyIterator ffi;
6073 FMFontFamilyInstanceIterator ffii;
6074 FMFontFamily ff;
6076 /* Create a dummy instance iterator here to avoid creating and
6077 destroying it in the loop. */
6078 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6079 return;
6080 /* Create an iterator to enumerate the font families. */
6081 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6082 != noErr)
6084 FMDisposeFontFamilyInstanceIterator (&ffii);
6085 return;
6088 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6090 Str255 name;
6091 FMFont font;
6092 FMFontStyle style;
6093 FMFontSize size;
6094 SInt16 sc;
6096 if (FMGetFontFamilyName (ff, name) != noErr)
6097 break;
6098 p2cstr (name);
6099 if (*name == '.')
6100 continue;
6102 sc = FontToScript (ff);
6103 decode_mac_font_name (name, sizeof (name), sc);
6105 /* Point the instance iterator at the current font family. */
6106 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6107 break;
6109 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6110 == noErr)
6112 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6113 contained in Apple Japanese (SJIS) font. */
6114 again:
6115 if (size == 0)
6117 add_font_name_table_entry (mac_to_x_fontname (name, size,
6118 style, sc));
6119 add_font_name_table_entry (mac_to_x_fontname (name, size,
6120 italic, sc));
6121 add_font_name_table_entry (mac_to_x_fontname (name, size,
6122 bold, sc));
6123 add_font_name_table_entry (mac_to_x_fontname (name, size,
6124 italic | bold,
6125 sc));
6127 else
6128 add_font_name_table_entry (mac_to_x_fontname (name, size,
6129 style, sc));
6130 if (sc == smJapanese)
6132 sc = -smJapanese;
6133 goto again;
6135 else if (sc == -smJapanese)
6136 sc = smJapanese;
6140 /* Dispose of the iterators. */
6141 FMDisposeFontFamilyIterator (&ffi);
6142 FMDisposeFontFamilyInstanceIterator (&ffii);
6144 else
6146 #endif /* TARGET_API_MAC_CARBON */
6147 GrafPtr port;
6148 SInt16 fontnum, old_fontnum;
6149 int num_mac_fonts = CountResources('FOND');
6150 int i, j;
6151 Handle font_handle, font_handle_2;
6152 short id, scriptcode;
6153 ResType type;
6154 Str32 name;
6155 struct FontAssoc *fat;
6156 struct AsscEntry *assc_entry;
6158 GetPort (&port); /* save the current font number used */
6159 #if TARGET_API_MAC_CARBON
6160 old_fontnum = GetPortTextFont (port);
6161 #else
6162 old_fontnum = port->txFont;
6163 #endif
6165 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6167 font_handle = GetIndResource ('FOND', i);
6168 if (!font_handle)
6169 continue;
6171 GetResInfo (font_handle, &id, &type, name);
6172 GetFNum (name, &fontnum);
6173 p2cstr (name);
6174 if (fontnum == 0)
6175 continue;
6177 TextFont (fontnum);
6178 scriptcode = FontToScript (fontnum);
6179 decode_mac_font_name (name, sizeof (name), scriptcode);
6182 HLock (font_handle);
6184 if (GetResourceSizeOnDisk (font_handle)
6185 >= sizeof (struct FamRec))
6187 fat = (struct FontAssoc *) (*font_handle
6188 + sizeof (struct FamRec));
6189 assc_entry
6190 = (struct AsscEntry *) (*font_handle
6191 + sizeof (struct FamRec)
6192 + sizeof (struct FontAssoc));
6194 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6196 if (font_name_table_size == 0)
6198 font_name_table_size = 16;
6199 font_name_table = (char **)
6200 xmalloc (font_name_table_size * sizeof (char *));
6202 else if (font_name_count >= font_name_table_size)
6204 font_name_table_size += 16;
6205 font_name_table = (char **)
6206 xrealloc (font_name_table,
6207 font_name_table_size * sizeof (char *));
6209 font_name_table[font_name_count++]
6210 = mac_to_x_fontname (name,
6211 assc_entry->fontSize,
6212 assc_entry->fontStyle,
6213 scriptcode);
6214 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6215 parts are contained in Apple Japanese (SJIS)
6216 font. */
6217 if (smJapanese == scriptcode)
6219 font_name_table[font_name_count++]
6220 = mac_to_x_fontname (name,
6221 assc_entry->fontSize,
6222 assc_entry->fontStyle,
6223 -smJapanese);
6228 HUnlock (font_handle);
6229 font_handle_2 = GetNextFOND (font_handle);
6230 ReleaseResource (font_handle);
6231 font_handle = font_handle_2;
6233 while (ResError () == noErr && font_handle);
6236 TextFont (old_fontnum);
6237 #if TARGET_API_MAC_CARBON
6239 #endif /* TARGET_API_MAC_CARBON */
6243 enum xlfd_scalable_field_index
6245 XLFD_SCL_PIXEL_SIZE,
6246 XLFD_SCL_POINT_SIZE,
6247 XLFD_SCL_AVGWIDTH,
6248 XLFD_SCL_LAST
6251 static int xlfd_scalable_fields[] =
6253 6, /* PIXEL_SIZE */
6254 7, /* POINT_SIZE */
6255 11, /* AVGWIDTH */
6259 static Lisp_Object
6260 mac_do_list_fonts (pattern, maxnames)
6261 char *pattern;
6262 int maxnames;
6264 int i, n_fonts = 0;
6265 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6266 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6267 char scaled[256];
6268 char *ptr;
6269 int scl_val[XLFD_SCL_LAST], *field, *val;
6271 for (i = 0; i < XLFD_SCL_LAST; i++)
6272 scl_val[i] = -1;
6274 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6275 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6276 fonts are scaled according to the specified size. */
6277 ptr = pattern;
6278 i = 0;
6279 field = xlfd_scalable_fields;
6280 val = scl_val;
6281 if (*ptr == '-')
6284 ptr++;
6285 if (i == *field)
6287 if ('1' <= *ptr && *ptr <= '9')
6289 *val = *ptr++ - '0';
6290 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6291 *val = *val * 10 + *ptr++ - '0';
6292 if (*ptr != '-')
6293 *val = -1;
6295 field++;
6296 val++;
6298 ptr = strchr (ptr, '-');
6299 i++;
6301 while (ptr && i < 14);
6303 if (i == 14 && ptr == NULL)
6305 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6307 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6308 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6310 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6312 scl_val[XLFD_SCL_POINT_SIZE] =
6313 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6315 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6317 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6318 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6321 else
6322 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6324 ptr = regex;
6325 *ptr++ = '^';
6327 /* Turn pattern into a regexp and do a regexp match. */
6328 for (; *pattern; pattern++)
6330 if (*pattern == '?')
6331 *ptr++ = '.';
6332 else if (*pattern == '*')
6334 *ptr++ = '.';
6335 *ptr++ = '*';
6337 else
6338 *ptr++ = tolower (*pattern);
6340 *ptr = '$';
6341 *(ptr + 1) = '\0';
6343 pattern_regex = build_string (regex);
6345 for (i = 0; i < font_name_count; i++)
6347 fontname = build_string (font_name_table[i]);
6348 if (fast_string_match (pattern_regex, fontname) >= 0)
6350 font_list = Fcons (fontname, font_list);
6352 n_fonts++;
6353 if (maxnames > 0 && n_fonts >= maxnames)
6354 break;
6356 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6357 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6359 int former_len = ptr - font_name_table[i];
6361 memcpy (scaled, font_name_table[i], former_len);
6362 sprintf (scaled + former_len,
6363 "-%d-%d-75-75-m-%d-%s",
6364 scl_val[XLFD_SCL_PIXEL_SIZE],
6365 scl_val[XLFD_SCL_POINT_SIZE],
6366 scl_val[XLFD_SCL_AVGWIDTH],
6367 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6368 fontname = build_string (scaled);
6369 if (fast_string_match (pattern_regex, fontname) >= 0)
6371 font_list = Fcons (fontname, font_list);
6373 n_fonts++;
6374 if (maxnames > 0 && n_fonts >= maxnames)
6375 break;
6379 return font_list;
6382 /* Return a list of at most MAXNAMES font specs matching the one in
6383 PATTERN. Cache matching fonts for patterns in
6384 dpyinfo->name_list_element to avoid looking them up again by
6385 calling mac_font_pattern_match (slow). Return as many matching
6386 fonts as possible if MAXNAMES = -1. */
6388 Lisp_Object
6389 x_list_fonts (struct frame *f,
6390 Lisp_Object pattern,
6391 int size,
6392 int maxnames)
6394 Lisp_Object newlist = Qnil, tem, key;
6395 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6397 if (font_name_table == NULL) /* Initialize when first used. */
6398 init_font_name_table ();
6400 if (dpyinfo)
6402 tem = XCDR (dpyinfo->name_list_element);
6403 key = Fcons (pattern, make_number (maxnames));
6405 newlist = Fassoc (key, tem);
6406 if (!NILP (newlist))
6408 newlist = Fcdr_safe (newlist);
6409 goto label_cached;
6413 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6415 /* MAC_TODO: add code for matching outline fonts here */
6417 if (dpyinfo)
6419 XSETCDR (dpyinfo->name_list_element,
6420 Fcons (Fcons (key, newlist),
6421 XCDR (dpyinfo->name_list_element)));
6423 label_cached:
6425 return newlist;
6429 #if GLYPH_DEBUG
6431 /* Check that FONT is valid on frame F. It is if it can be found in F's
6432 font table. */
6434 static void
6435 x_check_font (f, font)
6436 struct frame *f;
6437 XFontStruct *font;
6439 int i;
6440 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6442 xassert (font != NULL);
6444 for (i = 0; i < dpyinfo->n_fonts; i++)
6445 if (dpyinfo->font_table[i].name
6446 && font == dpyinfo->font_table[i].font)
6447 break;
6449 xassert (i < dpyinfo->n_fonts);
6452 #endif /* GLYPH_DEBUG != 0 */
6454 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6455 Note: There are (broken) X fonts out there with invalid XFontStruct
6456 min_bounds contents. For example, handa@etl.go.jp reports that
6457 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6458 have font->min_bounds.width == 0. */
6460 static INLINE void
6461 x_font_min_bounds (font, w, h)
6462 MacFontStruct *font;
6463 int *w, *h;
6466 * TODO: Windows does not appear to offer min bound, only
6467 * average and maximum width, and maximum height.
6469 *h = FONT_HEIGHT (font);
6470 *w = FONT_WIDTH (font);
6474 /* Compute the smallest character width and smallest font height over
6475 all fonts available on frame F. Set the members smallest_char_width
6476 and smallest_font_height in F's x_display_info structure to
6477 the values computed. Value is non-zero if smallest_font_height or
6478 smallest_char_width become smaller than they were before. */
6481 x_compute_min_glyph_bounds (f)
6482 struct frame *f;
6484 int i;
6485 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6486 MacFontStruct *font;
6487 int old_width = dpyinfo->smallest_char_width;
6488 int old_height = dpyinfo->smallest_font_height;
6490 dpyinfo->smallest_font_height = 100000;
6491 dpyinfo->smallest_char_width = 100000;
6493 for (i = 0; i < dpyinfo->n_fonts; ++i)
6494 if (dpyinfo->font_table[i].name)
6496 struct font_info *fontp = dpyinfo->font_table + i;
6497 int w, h;
6499 font = (MacFontStruct *) fontp->font;
6500 xassert (font != (MacFontStruct *) ~0);
6501 x_font_min_bounds (font, &w, &h);
6503 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6504 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6507 xassert (dpyinfo->smallest_char_width > 0
6508 && dpyinfo->smallest_font_height > 0);
6510 return (dpyinfo->n_fonts == 1
6511 || dpyinfo->smallest_char_width < old_width
6512 || dpyinfo->smallest_font_height < old_height);
6516 /* Determine whether given string is a fully-specified XLFD: all 14
6517 fields are present, none is '*'. */
6519 static int
6520 is_fully_specified_xlfd (char *p)
6522 int i;
6523 char *q;
6525 if (*p != '-')
6526 return 0;
6528 for (i = 0; i < 13; i++)
6530 q = strchr (p + 1, '-');
6531 if (q == NULL)
6532 return 0;
6533 if (q - p == 2 && *(p + 1) == '*')
6534 return 0;
6535 p = q;
6538 if (strchr (p + 1, '-') != NULL)
6539 return 0;
6541 if (*(p + 1) == '*' && *(p + 2) == '\0')
6542 return 0;
6544 return 1;
6548 const int kDefaultFontSize = 9;
6551 /* XLoadQueryFont creates and returns an internal representation for a
6552 font in a MacFontStruct struct. There is really no concept
6553 corresponding to "loading" a font on the Mac. But we check its
6554 existence and find the font number and all other information for it
6555 and store them in the returned MacFontStruct. */
6557 static MacFontStruct *
6558 XLoadQueryFont (Display *dpy, char *fontname)
6560 int i, size, is_two_byte_font, char_width;
6561 char *name;
6562 GrafPtr port;
6563 SInt16 old_fontnum, old_fontsize;
6564 Style old_fontface;
6565 Str32 mfontname;
6566 SInt16 fontnum;
6567 Style fontface = normal;
6568 MacFontStruct *font;
6569 FontInfo the_fontinfo;
6570 char s_weight[7], c_slant;
6572 if (is_fully_specified_xlfd (fontname))
6573 name = fontname;
6574 else
6576 Lisp_Object matched_fonts;
6578 matched_fonts = mac_do_list_fonts (fontname, 1);
6579 if (NILP (matched_fonts))
6580 return NULL;
6581 name = SDATA (XCAR (matched_fonts));
6584 GetPort (&port); /* save the current font number used */
6585 #if TARGET_API_MAC_CARBON
6586 old_fontnum = GetPortTextFont (port);
6587 old_fontsize = GetPortTextSize (port);
6588 old_fontface = GetPortTextFace (port);
6589 #else
6590 old_fontnum = port->txFont;
6591 old_fontsize = port->txSize;
6592 old_fontface = port->txFace;
6593 #endif
6595 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6596 size = kDefaultFontSize;
6598 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6599 if (strcmp (s_weight, "bold") == 0)
6600 fontface |= bold;
6602 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6603 if (c_slant == 'i')
6604 fontface |= italic;
6606 x_font_name_to_mac_font_name (name, mfontname);
6607 c2pstr (mfontname);
6608 GetFNum (mfontname, &fontnum);
6609 if (fontnum == 0)
6610 return NULL;
6612 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6614 font->fontname = (char *) xmalloc (strlen (name) + 1);
6615 bcopy (name, font->fontname, strlen (name) + 1);
6617 font->mac_fontnum = fontnum;
6618 font->mac_fontsize = size;
6619 font->mac_fontface = fontface;
6620 font->mac_scriptcode = FontToScript (fontnum);
6622 /* Apple Japanese (SJIS) font is listed as both
6623 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6624 (Roman script) in init_font_name_table (). The latter should be
6625 treated as a one-byte font. */
6627 char cs[32];
6629 if (sscanf (name,
6630 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6631 cs) == 1
6632 && 0 == strcmp (cs, "jisx0201.1976-0"))
6633 font->mac_scriptcode = smRoman;
6636 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6637 font->mac_scriptcode == smTradChinese ||
6638 font->mac_scriptcode == smSimpChinese ||
6639 font->mac_scriptcode == smKorean;
6641 TextFont (fontnum);
6642 TextSize (size);
6643 TextFace (fontface);
6645 GetFontInfo (&the_fontinfo);
6647 font->ascent = the_fontinfo.ascent;
6648 font->descent = the_fontinfo.descent;
6650 font->min_byte1 = 0;
6651 if (is_two_byte_font)
6652 font->max_byte1 = 1;
6653 else
6654 font->max_byte1 = 0;
6655 font->min_char_or_byte2 = 0x20;
6656 font->max_char_or_byte2 = 0xff;
6658 if (is_two_byte_font)
6660 /* Use the width of an "ideographic space" of that font because
6661 the_fontinfo.widMax returns the wrong width for some fonts. */
6662 switch (font->mac_scriptcode)
6664 case smJapanese:
6665 char_width = StringWidth("\p\x81\x40");
6666 break;
6667 case smTradChinese:
6668 char_width = StringWidth("\p\xa1\x40");
6669 break;
6670 case smSimpChinese:
6671 char_width = StringWidth("\p\xa1\xa1");
6672 break;
6673 case smKorean:
6674 char_width = StringWidth("\p\xa1\xa1");
6675 break;
6678 else
6679 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6680 returns 15 for 12-point Monaco! */
6681 char_width = CharWidth ('m');
6683 font->max_bounds.rbearing = char_width;
6684 font->max_bounds.lbearing = 0;
6685 font->max_bounds.width = char_width;
6686 font->max_bounds.ascent = the_fontinfo.ascent;
6687 font->max_bounds.descent = the_fontinfo.descent;
6689 font->min_bounds = font->max_bounds;
6691 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6692 font->per_char = NULL;
6693 else
6695 font->per_char = (XCharStruct *)
6696 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6698 int c;
6700 for (c = 0x20; c <= 0xff; c++)
6702 font->per_char[c - 0x20] = font->max_bounds;
6703 font->per_char[c - 0x20].width =
6704 font->per_char[c - 0x20].rbearing = CharWidth (c);
6709 TextFont (old_fontnum); /* restore previous font number, size and face */
6710 TextSize (old_fontsize);
6711 TextFace (old_fontface);
6713 return font;
6717 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6718 pointer to the structure font_info while allocating it dynamically.
6719 If SIZE is 0, load any size of font.
6720 If loading is failed, return NULL. */
6722 struct font_info *
6723 x_load_font (f, fontname, size)
6724 struct frame *f;
6725 register char *fontname;
6726 int size;
6728 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6729 Lisp_Object font_names;
6731 /* Get a list of all the fonts that match this name. Once we
6732 have a list of matching fonts, we compare them against the fonts
6733 we already have by comparing names. */
6734 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6736 if (!NILP (font_names))
6738 Lisp_Object tail;
6739 int i;
6741 for (i = 0; i < dpyinfo->n_fonts; i++)
6742 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6743 if (dpyinfo->font_table[i].name
6744 && (!strcmp (dpyinfo->font_table[i].name,
6745 SDATA (XCAR (tail)))
6746 || !strcmp (dpyinfo->font_table[i].full_name,
6747 SDATA (XCAR (tail)))))
6748 return (dpyinfo->font_table + i);
6751 /* Load the font and add it to the table. */
6753 char *full_name;
6754 struct MacFontStruct *font;
6755 struct font_info *fontp;
6756 unsigned long value;
6757 int i;
6759 /* If we have found fonts by x_list_font, load one of them. If
6760 not, we still try to load a font by the name given as FONTNAME
6761 because XListFonts (called in x_list_font) of some X server has
6762 a bug of not finding a font even if the font surely exists and
6763 is loadable by XLoadQueryFont. */
6764 if (size > 0 && !NILP (font_names))
6765 fontname = (char *) SDATA (XCAR (font_names));
6767 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6768 if (!font)
6769 return NULL;
6771 /* Find a free slot in the font table. */
6772 for (i = 0; i < dpyinfo->n_fonts; ++i)
6773 if (dpyinfo->font_table[i].name == NULL)
6774 break;
6776 /* If no free slot found, maybe enlarge the font table. */
6777 if (i == dpyinfo->n_fonts
6778 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6780 int sz;
6781 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6782 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6783 dpyinfo->font_table
6784 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6787 fontp = dpyinfo->font_table + i;
6788 if (i == dpyinfo->n_fonts)
6789 ++dpyinfo->n_fonts;
6791 /* Now fill in the slots of *FONTP. */
6792 BLOCK_INPUT;
6793 bzero (fontp, sizeof (*fontp));
6794 fontp->font = font;
6795 fontp->font_idx = i;
6796 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6797 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6799 fontp->full_name = fontp->name;
6801 fontp->size = font->max_bounds.width;
6802 fontp->height = FONT_HEIGHT (font);
6804 /* For some font, ascent and descent in max_bounds field is
6805 larger than the above value. */
6806 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6807 if (max_height > fontp->height)
6808 fontp->height = max_height;
6811 /* The slot `encoding' specifies how to map a character
6812 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6813 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6814 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6815 2:0xA020..0xFF7F). For the moment, we don't know which charset
6816 uses this font. So, we set information in fontp->encoding[1]
6817 which is never used by any charset. If mapping can't be
6818 decided, set FONT_ENCODING_NOT_DECIDED. */
6819 if (font->mac_scriptcode == smJapanese)
6820 fontp->encoding[1] = 4;
6821 else
6823 fontp->encoding[1]
6824 = (font->max_byte1 == 0
6825 /* 1-byte font */
6826 ? (font->min_char_or_byte2 < 0x80
6827 ? (font->max_char_or_byte2 < 0x80
6828 ? 0 /* 0x20..0x7F */
6829 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6830 : 1) /* 0xA0..0xFF */
6831 /* 2-byte font */
6832 : (font->min_byte1 < 0x80
6833 ? (font->max_byte1 < 0x80
6834 ? (font->min_char_or_byte2 < 0x80
6835 ? (font->max_char_or_byte2 < 0x80
6836 ? 0 /* 0x2020..0x7F7F */
6837 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6838 : 3) /* 0x20A0..0x7FFF */
6839 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6840 : (font->min_char_or_byte2 < 0x80
6841 ? (font->max_char_or_byte2 < 0x80
6842 ? 2 /* 0xA020..0xFF7F */
6843 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6844 : 1))); /* 0xA0A0..0xFFFF */
6847 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6848 fontp->baseline_offset
6849 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6850 ? (long) value : 0);
6851 fontp->relative_compose
6852 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6853 ? (long) value : 0);
6854 fontp->default_ascent
6855 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6856 ? (long) value : 0);
6857 #else
6858 fontp->baseline_offset = 0;
6859 fontp->relative_compose = 0;
6860 fontp->default_ascent = 0;
6861 #endif
6863 /* Set global flag fonts_changed_p to non-zero if the font loaded
6864 has a character with a smaller width than any other character
6865 before, or if the font loaded has a smalle>r height than any
6866 other font loaded before. If this happens, it will make a
6867 glyph matrix reallocation necessary. */
6868 fonts_changed_p = x_compute_min_glyph_bounds (f);
6869 UNBLOCK_INPUT;
6870 return fontp;
6875 /* Return a pointer to struct font_info of a font named FONTNAME for
6876 frame F. If no such font is loaded, return NULL. */
6878 struct font_info *
6879 x_query_font (f, fontname)
6880 struct frame *f;
6881 register char *fontname;
6883 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6884 int i;
6886 for (i = 0; i < dpyinfo->n_fonts; i++)
6887 if (dpyinfo->font_table[i].name
6888 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6889 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6890 return (dpyinfo->font_table + i);
6891 return NULL;
6895 /* Find a CCL program for a font specified by FONTP, and set the member
6896 `encoder' of the structure. */
6898 void
6899 x_find_ccl_program (fontp)
6900 struct font_info *fontp;
6902 Lisp_Object list, elt;
6904 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6906 elt = XCAR (list);
6907 if (CONSP (elt)
6908 && STRINGP (XCAR (elt))
6909 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6910 >= 0))
6911 break;
6913 if (! NILP (list))
6915 struct ccl_program *ccl
6916 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6918 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6919 xfree (ccl);
6920 else
6921 fontp->font_encoder = ccl;
6927 /* The Mac Event loop code */
6929 #ifndef MAC_OSX
6930 #include <Events.h>
6931 #include <Quickdraw.h>
6932 #include <Balloons.h>
6933 #include <Devices.h>
6934 #include <Fonts.h>
6935 #include <Gestalt.h>
6936 #include <Menus.h>
6937 #include <Processes.h>
6938 #include <Sound.h>
6939 #include <ToolUtils.h>
6940 #include <TextUtils.h>
6941 #include <Dialogs.h>
6942 #include <Script.h>
6943 #include <Types.h>
6944 #include <TextEncodingConverter.h>
6945 #include <Resources.h>
6947 #if __MWERKS__
6948 #include <unix.h>
6949 #endif
6950 #endif /* ! MAC_OSX */
6952 #define M_APPLE 128
6953 #define I_ABOUT 1
6955 #define WINDOW_RESOURCE 128
6956 #define TERM_WINDOW_RESOURCE 129
6958 #define DEFAULT_NUM_COLS 80
6960 #define MIN_DOC_SIZE 64
6961 #define MAX_DOC_SIZE 32767
6963 /* sleep time for WaitNextEvent */
6964 #define WNE_SLEEP_AT_SUSPEND 10
6965 #define WNE_SLEEP_AT_RESUME 1
6967 /* true when cannot handle any Mac OS events */
6968 static int handling_window_update = 0;
6970 #if 0
6971 /* the flag appl_is_suspended is used both for determining the sleep
6972 time to be passed to WaitNextEvent and whether the cursor should be
6973 drawn when updating the display. The cursor is turned off when
6974 Emacs is suspended. Redrawing it is unnecessary and what needs to
6975 be done depends on whether the cursor lies inside or outside the
6976 redraw region. So we might as well skip drawing it when Emacs is
6977 suspended. */
6978 static Boolean app_is_suspended = false;
6979 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
6980 #endif
6982 #define EXTRA_STACK_ALLOC (256 * 1024)
6984 #define ARGV_STRING_LIST_ID 129
6985 #define ABOUT_ALERT_ID 128
6986 #define RAM_TOO_LARGE_ALERT_ID 129
6988 Boolean terminate_flag = false;
6990 /* Contains the string "reverse", which is a constant for mouse button emu.*/
6991 Lisp_Object Qreverse;
6993 /* True if using command key as meta key. */
6994 Lisp_Object Vmac_command_key_is_meta;
6996 /* Modifier associated with the option key, or nil for normal behavior. */
6997 Lisp_Object Vmac_option_modifier;
6999 /* True if the ctrl and meta keys should be reversed. */
7000 Lisp_Object Vmac_reverse_ctrl_meta;
7002 /* True if the option and command modifiers should be used to emulate
7003 a three button mouse */
7004 Lisp_Object Vmac_emulate_three_button_mouse;
7006 #if USE_CARBON_EVENTS
7007 /* True if the mouse wheel button (i.e. button 4) should map to
7008 mouse-2, instead of mouse-3. */
7009 Lisp_Object Vmac_wheel_button_is_mouse_2;
7011 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7012 for processing before Emacs sees it. */
7013 Lisp_Object Vmac_pass_command_to_system;
7015 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7016 for processing before Emacs sees it. */
7017 Lisp_Object Vmac_pass_control_to_system;
7018 #endif
7020 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7021 to this text encoding */
7022 int mac_keyboard_text_encoding;
7023 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7025 /* Set in term/mac-win.el to indicate that event loop can now generate
7026 drag and drop events. */
7027 Lisp_Object Qmac_ready_for_drag_n_drop;
7029 Lisp_Object drag_and_drop_file_list;
7031 Point saved_menu_event_location;
7033 #if !TARGET_API_MAC_CARBON
7034 /* Place holder for the default arrow cursor. */
7035 CursPtr arrow_cursor;
7036 #endif
7038 /* Apple Events */
7039 static void init_required_apple_events (void);
7040 static pascal OSErr
7041 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7042 static pascal OSErr
7043 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7044 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7045 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7047 /* Drag and Drop */
7048 static OSErr init_mac_drag_n_drop ();
7049 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7051 #if USE_CARBON_EVENTS
7052 /* Preliminary Support for the OSX Services Menu */
7053 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7054 static void init_service_handler ();
7055 #endif
7057 extern void init_emacs_passwd_dir ();
7058 extern int emacs_main (int, char **, char **);
7059 extern void check_alarm ();
7061 extern void initialize_applescript();
7062 extern void terminate_applescript();
7064 static unsigned int
7065 #if USE_CARBON_EVENTS
7066 mac_to_emacs_modifiers (UInt32 mods)
7067 #else
7068 mac_to_emacs_modifiers (EventModifiers mods)
7069 #endif
7071 unsigned int result = 0;
7072 if (mods & macShiftKey)
7073 result |= shift_modifier;
7074 if (mods & macCtrlKey)
7075 result |= ctrl_modifier;
7076 if (mods & macMetaKey)
7077 result |= meta_modifier;
7078 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7079 result |= alt_modifier;
7080 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7081 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7082 if (!NILP(val))
7083 result |= XUINT(val);
7086 return result;
7089 static int
7090 mac_get_emulated_btn ( UInt32 modifiers )
7092 int result = 0;
7093 if (!NILP (Vmac_emulate_three_button_mouse)) {
7094 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7095 if (modifiers & cmdKey)
7096 result = cmdIs3 ? 2 : 1;
7097 else if (modifiers & optionKey)
7098 result = cmdIs3 ? 1 : 2;
7100 return result;
7103 #if USE_CARBON_EVENTS
7104 /* Obtains the event modifiers from the event ref and then calls
7105 mac_to_emacs_modifiers. */
7106 static int
7107 mac_event_to_emacs_modifiers (EventRef eventRef)
7109 UInt32 mods = 0;
7110 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7111 sizeof (UInt32), NULL, &mods);
7112 if (!NILP (Vmac_emulate_three_button_mouse) &&
7113 GetEventClass(eventRef) == kEventClassMouse)
7115 mods &= ~(optionKey | cmdKey);
7117 return mac_to_emacs_modifiers (mods);
7120 /* Given an event ref, return the code to use for the mouse button
7121 code in the emacs input_event. */
7122 static int
7123 mac_get_mouse_btn (EventRef ref)
7125 EventMouseButton result = kEventMouseButtonPrimary;
7126 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7127 sizeof (EventMouseButton), NULL, &result);
7128 switch (result)
7130 case kEventMouseButtonPrimary:
7131 if (NILP (Vmac_emulate_three_button_mouse))
7132 return 0;
7133 else {
7134 UInt32 mods = 0;
7135 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7136 sizeof (UInt32), NULL, &mods);
7137 return mac_get_emulated_btn(mods);
7139 case kEventMouseButtonSecondary:
7140 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7141 case kEventMouseButtonTertiary:
7142 case 4: /* 4 is the number for the mouse wheel button */
7143 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7144 default:
7145 return 0;
7149 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7150 events. However the click of the mouse wheel is not converted to a
7151 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7152 checks to see if it is a mouse up or down carbon event that has not
7153 been converted, and if so, converts it by hand (to be picked up in
7154 the XTread_socket loop). */
7155 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7157 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7158 /* Do special case for mouse wheel button. */
7159 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7161 UInt32 kind = GetEventKind (eventRef);
7162 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7164 eventRec->what = mouseDown;
7165 result=1;
7167 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7169 eventRec->what = mouseUp;
7170 result=1;
7172 if (result)
7174 /* Need where and when. */
7175 UInt32 mods;
7176 GetEventParameter (eventRef, kEventParamMouseLocation,
7177 typeQDPoint, NULL, sizeof (Point),
7178 NULL, &eventRec->where);
7179 /* Use two step process because new event modifiers are
7180 32-bit and old are 16-bit. Currently, only loss is
7181 NumLock & Fn. */
7182 GetEventParameter (eventRef, kEventParamKeyModifiers,
7183 typeUInt32, NULL, sizeof (UInt32),
7184 NULL, &mods);
7185 eventRec->modifiers = mods;
7187 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7190 return result;
7193 #endif
7195 static void
7196 do_get_menus (void)
7198 Handle menubar_handle;
7199 MenuHandle menu_handle;
7201 menubar_handle = GetNewMBar (128);
7202 if(menubar_handle == NULL)
7203 abort ();
7204 SetMenuBar (menubar_handle);
7205 DrawMenuBar ();
7207 menu_handle = GetMenuHandle (M_APPLE);
7208 if(menu_handle != NULL)
7209 AppendResMenu (menu_handle,'DRVR');
7210 else
7211 abort ();
7215 static void
7216 do_init_managers (void)
7218 #if !TARGET_API_MAC_CARBON
7219 InitGraf (&qd.thePort);
7220 InitFonts ();
7221 FlushEvents (everyEvent, 0);
7222 InitWindows ();
7223 InitMenus ();
7224 TEInit ();
7225 InitDialogs (NULL);
7226 #endif /* !TARGET_API_MAC_CARBON */
7227 InitCursor ();
7229 #if !TARGET_API_MAC_CARBON
7230 arrow_cursor = &qd.arrow;
7232 /* set up some extra stack space for use by emacs */
7233 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7235 /* MaxApplZone must be called for AppleScript to execute more
7236 complicated scripts */
7237 MaxApplZone ();
7238 MoreMasters ();
7239 #endif /* !TARGET_API_MAC_CARBON */
7242 static void
7243 do_check_ram_size (void)
7245 SInt32 physical_ram_size, logical_ram_size;
7247 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7248 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7249 || physical_ram_size > (1 << VALBITS)
7250 || logical_ram_size > (1 << VALBITS))
7252 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7253 exit (1);
7257 static void
7258 do_window_update (WindowPtr win)
7260 struct frame *f = mac_window_to_frame (win);
7262 if (win == tip_window)
7263 /* The tooltip has been drawn already. Avoid the
7264 SET_FRAME_GARBAGED below. */
7265 return;
7267 if (f)
7269 if (f->async_visible == 0)
7271 f->async_visible = 1;
7272 f->async_iconified = 0;
7273 SET_FRAME_GARBAGED (f);
7275 /* An update event is equivalent to MapNotify on X, so report
7276 visibility changes properly. */
7277 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7278 /* Force a redisplay sooner or later to update the
7279 frame titles in case this is the second frame. */
7280 record_asynch_buffer_change ();
7282 else
7284 BeginUpdate (win);
7285 handling_window_update = 1;
7287 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
7289 expose_frame (f, 0, 0, 0, 0);
7291 handling_window_update = 0;
7292 EndUpdate (win);
7297 static int
7298 is_emacs_window (WindowPtr win)
7300 Lisp_Object tail, frame;
7302 if (!win)
7303 return 0;
7305 FOR_EACH_FRAME (tail, frame)
7306 if (FRAME_MAC_P (XFRAME (frame)))
7307 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7308 return 1;
7310 return 0;
7313 static void
7314 do_app_resume ()
7316 /* Window-activate events will do the job. */
7317 #if 0
7318 WindowPtr wp;
7319 struct frame *f;
7321 wp = front_emacs_window ();
7322 if (wp)
7324 f = mac_window_to_frame (wp);
7326 if (f)
7328 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7329 activate_scroll_bars (f);
7333 app_is_suspended = false;
7334 app_sleep_time = WNE_SLEEP_AT_RESUME;
7335 #endif
7338 static void
7339 do_app_suspend ()
7341 /* Window-deactivate events will do the job. */
7342 #if 0
7343 WindowPtr wp;
7344 struct frame *f;
7346 wp = front_emacs_window ();
7347 if (wp)
7349 f = mac_window_to_frame (wp);
7351 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7353 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7354 deactivate_scroll_bars (f);
7358 app_is_suspended = true;
7359 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7360 #endif
7364 static void
7365 do_mouse_moved (mouse_pos, f)
7366 Point mouse_pos;
7367 FRAME_PTR *f;
7369 WindowPtr wp = front_emacs_window ();
7370 struct x_display_info *dpyinfo;
7372 if (wp)
7374 *f = mac_window_to_frame (wp);
7375 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7377 if (dpyinfo->mouse_face_hidden)
7379 dpyinfo->mouse_face_hidden = 0;
7380 clear_mouse_face (dpyinfo);
7383 SetPortWindowPort (wp);
7385 GlobalToLocal (&mouse_pos);
7387 if (dpyinfo->grabbed && tracked_scroll_bar)
7388 x_scroll_bar_note_movement (tracked_scroll_bar,
7389 mouse_pos.v
7390 - XINT (tracked_scroll_bar->top),
7391 TickCount() * (1000 / 60));
7392 else
7393 note_mouse_movement (*f, &mouse_pos);
7398 static void
7399 do_apple_menu (SInt16 menu_item)
7401 #if !TARGET_API_MAC_CARBON
7402 Str255 item_name;
7403 SInt16 da_driver_refnum;
7405 if (menu_item == I_ABOUT)
7406 NoteAlert (ABOUT_ALERT_ID, NULL);
7407 else
7409 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7410 da_driver_refnum = OpenDeskAcc (item_name);
7412 #endif /* !TARGET_API_MAC_CARBON */
7415 void
7416 do_menu_choice (SInt32 menu_choice)
7418 SInt16 menu_id, menu_item;
7420 menu_id = HiWord (menu_choice);
7421 menu_item = LoWord (menu_choice);
7423 if (menu_id == 0)
7424 return;
7426 switch (menu_id)
7428 case M_APPLE:
7429 do_apple_menu (menu_item);
7430 break;
7432 default:
7434 struct frame *f = mac_window_to_frame (front_emacs_window ());
7435 MenuHandle menu = GetMenuHandle (menu_id);
7436 if (menu)
7438 UInt32 refcon;
7440 GetMenuItemRefCon (menu, menu_item, &refcon);
7441 menubar_selection_callback (f, refcon);
7446 HiliteMenu (0);
7450 /* Handle drags in size box. Based on code contributed by Ben
7451 Mesander and IM - Window Manager A. */
7453 static void
7454 do_grow_window (WindowPtr w, EventRecord *e)
7456 long grow_size;
7457 Rect limit_rect;
7458 int rows, columns;
7459 struct frame *f = mac_window_to_frame (w);
7461 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
7463 grow_size = GrowWindow (w, e->where, &limit_rect);
7465 /* see if it really changed size */
7466 if (grow_size != 0)
7468 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
7469 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
7471 x_set_window_size (f, 0, columns, rows);
7476 /* Handle clicks in zoom box. Calculation of "standard state" based
7477 on code in IM - Window Manager A and code contributed by Ben
7478 Mesander. The standard state of an Emacs window is 80-characters
7479 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7481 static void
7482 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7484 GrafPtr save_port;
7485 Rect zoom_rect, port_rect;
7486 Point top_left;
7487 int w_title_height, columns, rows;
7488 struct frame *f = mac_window_to_frame (w);
7490 #if TARGET_API_MAC_CARBON
7492 Point standard_size;
7494 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7495 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7497 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7498 zoom_in_or_out = inZoomIn;
7499 else
7501 /* Adjust the standard size according to character boundaries. */
7503 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7504 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7505 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7506 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7507 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7508 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7509 && port_rect.left == zoom_rect.left
7510 && port_rect.top == zoom_rect.top)
7511 zoom_in_or_out = inZoomIn;
7512 else
7513 zoom_in_or_out = inZoomOut;
7516 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7518 #else /* not TARGET_API_MAC_CARBON */
7519 GetPort (&save_port);
7521 SetPortWindowPort (w);
7523 /* Clear window to avoid flicker. */
7524 EraseRect (&(w->portRect));
7525 if (zoom_in_or_out == inZoomOut)
7527 SetPt (&top_left, w->portRect.left, w->portRect.top);
7528 LocalToGlobal (&top_left);
7530 /* calculate height of window's title bar */
7531 w_title_height = top_left.v - 1
7532 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7534 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7535 zoom_rect = qd.screenBits.bounds;
7536 zoom_rect.top += w_title_height;
7537 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7539 zoom_rect.right = zoom_rect.left
7540 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7542 /* Adjust the standard size according to character boundaries. */
7543 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7544 zoom_rect.bottom =
7545 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7547 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7548 = zoom_rect;
7551 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7553 SetPort (save_port);
7554 #endif /* not TARGET_API_MAC_CARBON */
7556 /* retrieve window size and update application values */
7557 #if TARGET_API_MAC_CARBON
7558 GetWindowPortBounds (w, &port_rect);
7559 #else
7560 port_rect = w->portRect;
7561 #endif
7562 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
7563 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
7564 x_set_window_size (f, 0, columns, rows);
7565 x_real_positions (f, &f->left_pos, &f->top_pos);
7568 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7569 static OSErr
7570 init_mac_drag_n_drop ()
7572 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7573 return result;
7576 /* Intialize AppleEvent dispatcher table for the required events. */
7577 void
7578 init_required_apple_events ()
7580 OSErr err;
7581 long result;
7583 /* Make sure we have apple events before starting. */
7584 err = Gestalt (gestaltAppleEventsAttr, &result);
7585 if (err != noErr)
7586 abort ();
7588 if (!(result & (1 << gestaltAppleEventsPresent)))
7589 abort ();
7591 #if TARGET_API_MAC_CARBON
7592 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7593 NewAEEventHandlerUPP
7594 ((AEEventHandlerProcPtr) do_ae_open_application),
7595 0L, false);
7596 #else
7597 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7598 NewAEEventHandlerProc
7599 ((AEEventHandlerProcPtr) do_ae_open_application),
7600 0L, false);
7601 #endif
7602 if (err != noErr)
7603 abort ();
7605 #if TARGET_API_MAC_CARBON
7606 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7607 NewAEEventHandlerUPP
7608 ((AEEventHandlerProcPtr) do_ae_open_documents),
7609 0L, false);
7610 #else
7611 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7612 NewAEEventHandlerProc
7613 ((AEEventHandlerProcPtr) do_ae_open_documents),
7614 0L, false);
7615 #endif
7616 if (err != noErr)
7617 abort ();
7619 #if TARGET_API_MAC_CARBON
7620 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7621 NewAEEventHandlerUPP
7622 ((AEEventHandlerProcPtr) do_ae_print_documents),
7623 0L, false);
7624 #else
7625 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7626 NewAEEventHandlerProc
7627 ((AEEventHandlerProcPtr) do_ae_print_documents),
7628 0L, false);
7629 #endif
7630 if (err != noErr)
7631 abort ();
7633 #if TARGET_API_MAC_CARBON
7634 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7635 NewAEEventHandlerUPP
7636 ((AEEventHandlerProcPtr) do_ae_quit_application),
7637 0L, false);
7638 #else
7639 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7640 NewAEEventHandlerProc
7641 ((AEEventHandlerProcPtr) do_ae_quit_application),
7642 0L, false);
7643 #endif
7644 if (err != noErr)
7645 abort ();
7648 #if USE_CARBON_EVENTS
7650 void
7651 init_service_handler ()
7653 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7654 {kEventClassService, kEventServiceCopy},
7655 {kEventClassService, kEventServicePaste}};
7656 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7657 3, specs, NULL, NULL);
7661 MAC_TODO: Check to see if this is called by AEProcessDesc...
7663 OSStatus
7664 mac_handle_service_event (EventHandlerCallRef callRef,
7665 EventRef event, void *data)
7667 OSStatus err = noErr;
7668 switch (GetEventKind (event))
7670 case kEventServiceGetTypes:
7672 CFMutableArrayRef copyTypes, pasteTypes;
7673 CFStringRef type;
7674 Boolean selection = true;
7676 GetEventParameter(event, kEventParamServicePasteTypes,
7677 typeCFMutableArrayRef, NULL,
7678 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7680 GetEventParameter(event, kEventParamServiceCopyTypes,
7681 typeCFMutableArrayRef, NULL,
7682 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7683 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7684 if (type) {
7685 CFArrayAppendValue (copyTypes, type);
7686 //CFArrayAppendValue (pasteTypes, type);
7687 CFRelease (type);
7690 case kEventServiceCopy:
7692 ScrapRef currentScrap, specificScrap;
7693 char * buf = "";
7694 Size byteCount = 0;
7696 GetCurrentScrap (&currentScrap);
7698 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7699 if (err == noErr)
7701 void *buffer = xmalloc (byteCount);
7702 if (buffer != NULL)
7704 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7705 sizeof (ScrapRef), NULL, &specificScrap);
7707 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7708 &byteCount, buffer);
7709 if (err == noErr)
7710 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7711 kScrapFlavorMaskNone, byteCount, buffer);
7712 xfree (buffer);
7715 err = noErr;
7717 case kEventServicePaste:
7720 // Get the current location
7721 Size byteCount;
7722 ScrapRef specificScrap;
7723 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7724 sizeof(ScrapRef), NULL, &specificScrap);
7725 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7726 if (err == noErr) {
7727 void * buffer = xmalloc(byteCount);
7728 if (buffer != NULL ) {
7729 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7730 &byteCount, buffer);
7731 if (err == noErr) {
7732 // Actually place in the buffer
7733 BLOCK_INPUT;
7734 // Get the current "selection" string here
7735 UNBLOCK_INPUT;
7738 xfree(buffer);
7743 return err;
7745 #endif
7747 /* Open Application Apple Event */
7748 static pascal OSErr
7749 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7751 return noErr;
7755 /* Defined in mac.c. */
7756 extern int
7757 path_from_vol_dir_name (char *, int, short, long, char *);
7760 /* Called when we receive an AppleEvent with an ID of
7761 "kAEOpenDocuments". This routine gets the direct parameter,
7762 extracts the FSSpecs in it, and puts their names on a list. */
7763 static pascal OSErr
7764 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7766 OSErr err, err2;
7767 AEDesc the_desc;
7768 AEKeyword keyword;
7769 DescType actual_type;
7770 Size actual_size;
7772 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7773 if (err != noErr)
7774 goto descriptor_error_exit;
7776 /* Check to see that we got all of the required parameters from the
7777 event descriptor. For an 'odoc' event this should just be the
7778 file list. */
7779 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
7780 &actual_type, (Ptr) &keyword,
7781 sizeof (keyword), &actual_size);
7782 /* No error means that we found some unused parameters.
7783 errAEDescNotFound means that there are no more parameters. If we
7784 get an error code other than that, flag it. */
7785 if ((err == noErr) || (err != errAEDescNotFound))
7787 err = errAEEventNotHandled;
7788 goto error_exit;
7790 err = noErr;
7792 /* Got all the parameters we need. Now, go through the direct
7793 object list and parse it up. */
7795 long num_files_to_open;
7797 err = AECountItems (&the_desc, &num_files_to_open);
7798 if (err == noErr)
7800 int i;
7802 /* AE file list is one based so just use that for indexing here. */
7803 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7805 FSSpec fs;
7806 Str255 path_name, unix_path_name;
7807 #ifdef MAC_OSX
7808 FSRef fref;
7809 #endif
7811 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7812 (Ptr) &fs, sizeof (fs), &actual_size);
7813 if (err != noErr) break;
7815 #ifdef MAC_OSX
7816 err = FSpMakeFSRef (&fs, &fref);
7817 if (err != noErr) break;
7819 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
7820 #else
7821 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
7822 fs.name) &&
7823 mac_to_posix_pathname (path_name, unix_path_name, 255))
7824 #endif
7825 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7826 drag_and_drop_file_list);
7831 error_exit:
7832 /* Nuke the coerced file list in any case */
7833 err2 = AEDisposeDesc(&the_desc);
7835 descriptor_error_exit:
7836 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7837 return err;
7841 static pascal OSErr
7842 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
7843 DragReference theDrag)
7845 short items;
7846 short index;
7847 FlavorFlags theFlags;
7848 Point mouse;
7849 OSErr result;
7850 ItemReference theItem;
7851 HFSFlavor data;
7852 FSRef fref;
7853 Size size = sizeof (HFSFlavor);
7855 drag_and_drop_file_list = Qnil;
7856 GetDragMouse (theDrag, &mouse, 0L);
7857 CountDragItems (theDrag, &items);
7858 for (index = 1; index <= items; index++)
7860 /* Only handle file references. */
7861 GetDragItemReferenceNumber (theDrag, index, &theItem);
7862 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
7863 if (result == noErr)
7865 #ifdef MAC_OSX
7866 FSRef frref;
7867 #else
7868 Str255 path_name;
7869 #endif
7870 Str255 unix_path_name;
7871 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
7872 #ifdef MAC_OSX
7873 /* Use Carbon routines, otherwise it converts the file name
7874 to /Macintosh HD/..., which is not correct. */
7875 FSpMakeFSRef (&data.fileSpec, &fref);
7876 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
7877 #else
7878 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
7879 data.fileSpec.parID, data.fileSpec.name) &&
7880 mac_to_posix_pathname (path_name, unix_path_name, 255))
7881 #endif
7882 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7883 drag_and_drop_file_list);
7885 else
7886 return;
7888 /* If there are items in the list, construct an event and post it to
7889 the queue like an interrupt using kbd_buffer_store_event. */
7890 if (!NILP (drag_and_drop_file_list))
7892 struct input_event event;
7893 Lisp_Object frame;
7894 struct frame *f = mac_window_to_frame (window);
7895 SetPortWindowPort (window);
7896 GlobalToLocal (&mouse);
7898 event.kind = DRAG_N_DROP_EVENT;
7899 event.code = 0;
7900 event.modifiers = 0;
7901 event.timestamp = TickCount () * (1000 / 60);
7902 XSETINT (event.x, mouse.h);
7903 XSETINT (event.y, mouse.v);
7904 XSETFRAME (frame, f);
7905 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
7906 event.arg = Qnil;
7907 /* Post to the interrupt queue */
7908 kbd_buffer_store_event (&event);
7909 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7911 ProcessSerialNumber psn;
7912 GetCurrentProcess (&psn);
7913 SetFrontProcess (&psn);
7919 /* Print Document Apple Event */
7920 static pascal OSErr
7921 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
7923 return errAEEventNotHandled;
7927 static pascal OSErr
7928 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
7930 /* FixMe: Do we need an unwind-protect or something here? And what
7931 do we do about unsaved files. Currently just forces quit rather
7932 than doing recursive callback to get user input. */
7934 terminate_flag = true;
7936 /* Fkill_emacs doesn't return. We have to return. (TI) */
7937 return noErr;
7941 #if __profile__
7942 void
7943 profiler_exit_proc ()
7945 ProfilerDump ("\pEmacs.prof");
7946 ProfilerTerm ();
7948 #endif
7950 /* These few functions implement Emacs as a normal Mac application
7951 (almost): set up the heap and the Toolbox, handle necessary
7952 system events plus a few simple menu events. They also set up
7953 Emacs's access to functions defined in the rest of this file.
7954 Emacs uses function hooks to perform all its terminal I/O. A
7955 complete list of these functions appear in termhooks.h. For what
7956 they do, read the comments there and see also w32term.c and
7957 xterm.c. What's noticeably missing here is the event loop, which
7958 is normally present in most Mac application. After performing the
7959 necessary Mac initializations, main passes off control to
7960 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7961 mac_read_socket (defined further below) to read input. This is
7962 where WaitNextEvent is called to process Mac events. This is also
7963 where check_alarm in sysdep.c is called to simulate alarm signals.
7964 This makes the cursor jump back to its correct position after
7965 briefly jumping to that of the matching parenthesis, print useful
7966 hints and prompts in the minibuffer after the user stops typing for
7967 a wait, etc. */
7969 #if !TARGET_API_MAC_CARBON
7970 #undef main
7972 main (void)
7974 #if __profile__ /* is the profiler on? */
7975 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
7976 exit(1);
7977 #endif
7979 #if __MWERKS__
7980 /* set creator and type for files created by MSL */
7981 _fcreator = 'EMAx';
7982 _ftype = 'TEXT';
7983 #endif
7985 do_init_managers ();
7987 do_get_menus ();
7989 #ifndef USE_LSB_TAG
7990 do_check_ram_size ();
7991 #endif
7993 init_emacs_passwd_dir ();
7995 init_environ ();
7997 initialize_applescript ();
7999 init_required_apple_events ();
8002 char **argv;
8003 int argc = 0;
8005 /* set up argv array from STR# resource */
8006 get_string_list (&argv, ARGV_STRING_LIST_ID);
8007 while (argv[argc])
8008 argc++;
8010 /* free up AppleScript resources on exit */
8011 atexit (terminate_applescript);
8013 #if __profile__ /* is the profiler on? */
8014 atexit (profiler_exit_proc);
8015 #endif
8017 /* 3rd param "envp" never used in emacs_main */
8018 (void) emacs_main (argc, argv, 0);
8021 /* Never reached - real exit in Fkill_emacs */
8022 return 0;
8024 #endif
8026 /* Table for translating Mac keycode to X keysym values. Contributed
8027 by Sudhir Shenoy. */
8028 static unsigned char keycode_to_xkeysym_table[] = {
8029 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8030 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8031 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8033 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8034 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8035 /*0x38*/ 0, 0, 0, 0,
8036 /*0x3C*/ 0, 0, 0, 0,
8038 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8039 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8040 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8041 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8043 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8044 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8045 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8046 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8048 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8049 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8050 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8051 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8053 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8054 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8055 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8056 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8059 static int
8060 keycode_to_xkeysym (int keyCode, int *xKeySym)
8062 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8063 return *xKeySym != 0;
8066 /* Emacs calls this whenever it wants to read an input event from the
8067 user. */
8069 XTread_socket (sd, expected, hold_quit)
8070 int sd, expected;
8071 struct input_event *hold_quit;
8073 struct input_event inev;
8074 int count = 0;
8075 #if USE_CARBON_EVENTS
8076 EventRef eventRef;
8077 EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget ();
8078 #else
8079 EventMask event_mask;
8080 #endif
8081 EventRecord er;
8082 struct mac_display_info *dpyinfo = &one_mac_display_info;
8084 if (interrupt_input_blocked)
8086 interrupt_input_pending = 1;
8087 return -1;
8090 interrupt_input_pending = 0;
8091 BLOCK_INPUT;
8093 /* So people can tell when we have read the available input. */
8094 input_signal_count++;
8096 /* Don't poll for events to process (specifically updateEvt) if
8097 window update currently already in progress. A call to redisplay
8098 (in do_window_update) can be preempted by another call to
8099 redisplay, causing blank regions to be left on the screen and the
8100 cursor to be left at strange places. */
8101 if (handling_window_update)
8103 UNBLOCK_INPUT;
8104 return 0;
8107 if (terminate_flag)
8108 Fkill_emacs (make_number (1));
8110 #if !USE_CARBON_EVENTS
8111 event_mask = everyEvent;
8112 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8113 event_mask -= highLevelEventMask;
8115 while (WaitNextEvent (event_mask, &er, 0L, NULL))
8116 #else /* USE_CARBON_EVENTS */
8117 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8118 kEventRemoveFromQueue, &eventRef))
8119 #endif /* USE_CARBON_EVENTS */
8121 int do_help = 0;
8122 struct frame *f;
8124 /* It is necessary to set this (additional) argument slot of an
8125 event to nil because keyboard.c protects incompletely
8126 processed event from being garbage collected by placing them
8127 in the kbd_buffer_gcpro vector. */
8128 EVENT_INIT (inev);
8129 inev.kind = NO_EVENT;
8130 inev.arg = Qnil;
8132 #if USE_CARBON_EVENTS
8133 /* Handle new events */
8134 if (!mac_convert_event_ref (eventRef, &er))
8135 switch (GetEventClass (eventRef))
8137 case kEventClassWindow:
8138 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8140 WindowPtr window_ptr;
8141 GetEventParameter(eventRef, kEventParamDirectObject,
8142 typeWindowRef, NULL, sizeof(WindowPtr),
8143 NULL, &window_ptr);
8144 f = mac_window_to_frame (window_ptr);
8145 if (f && !f->async_iconified)
8146 x_real_positions (f, &f->left_pos, &f->top_pos);
8147 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8149 break;
8150 case kEventClassMouse:
8151 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8153 SInt32 delta;
8154 Point point;
8155 WindowPtr window_ptr = front_emacs_window ();
8157 if (!IsValidWindowPtr (window_ptr))
8159 SysBeep(1);
8160 break;
8163 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8164 typeSInt32, NULL, sizeof (SInt32),
8165 NULL, &delta);
8166 GetEventParameter(eventRef, kEventParamMouseLocation,
8167 typeQDPoint, NULL, sizeof (Point),
8168 NULL, &point);
8169 inev.kind = WHEEL_EVENT;
8170 inev.code = 0;
8171 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8172 | ((delta < 0) ? down_modifier
8173 : up_modifier));
8174 SetPortWindowPort (window_ptr);
8175 GlobalToLocal (&point);
8176 XSETINT (inev.x, point.h);
8177 XSETINT (inev.y, point.v);
8178 XSETFRAME (inev.frame_or_window,
8179 mac_window_to_frame (window_ptr));
8180 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8182 else
8183 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8185 break;
8186 default:
8187 /* Send the event to the appropriate receiver. */
8188 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8190 else
8191 #endif /* USE_CARBON_EVENTS */
8192 switch (er.what)
8194 case mouseDown:
8195 case mouseUp:
8197 WindowPtr window_ptr;
8198 SInt16 part_code;
8199 int tool_bar_p = 0;
8201 #if USE_CARBON_EVENTS
8202 /* This is needed to send mouse events like aqua window
8203 buttons to the correct handler. */
8204 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8205 != eventNotHandledErr)
8206 break;
8207 #endif
8209 if (dpyinfo->grabbed && last_mouse_frame
8210 && FRAME_LIVE_P (last_mouse_frame))
8212 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8213 part_code = inContent;
8215 else
8217 part_code = FindWindow (er.where, &window_ptr);
8218 if (tip_window && window_ptr == tip_window)
8220 HideWindow (tip_window);
8221 part_code = FindWindow (er.where, &window_ptr);
8225 if (er.what != mouseDown && part_code != inContent)
8226 break;
8228 switch (part_code)
8230 case inMenuBar:
8231 f = mac_window_to_frame (front_emacs_window ());
8232 saved_menu_event_location = er.where;
8233 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8234 XSETFRAME (inev.frame_or_window, f);
8235 break;
8237 case inContent:
8238 if (window_ptr != front_emacs_window ())
8239 SelectWindow (window_ptr);
8240 else
8242 SInt16 control_part_code;
8243 ControlHandle ch;
8244 Point mouse_loc = er.where;
8246 f = mac_window_to_frame (window_ptr);
8247 /* convert to local coordinates of new window */
8248 SetPortWindowPort (window_ptr);
8250 GlobalToLocal (&mouse_loc);
8251 #if TARGET_API_MAC_CARBON
8252 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8253 &control_part_code);
8254 #else
8255 control_part_code = FindControl (mouse_loc, window_ptr,
8256 &ch);
8257 #endif
8259 #if USE_CARBON_EVENTS
8260 inev.code = mac_get_mouse_btn (eventRef);
8261 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8262 #else
8263 inev.code = mac_get_emulated_btn (er.modifiers);
8264 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8265 #endif
8266 XSETINT (inev.x, mouse_loc.h);
8267 XSETINT (inev.y, mouse_loc.v);
8268 inev.timestamp = er.when * (1000 / 60);
8269 /* ticks to milliseconds */
8271 if (dpyinfo->grabbed && tracked_scroll_bar
8272 #if TARGET_API_MAC_CARBON
8273 || ch != 0
8274 #else
8275 || control_part_code != 0
8276 #endif
8279 struct scroll_bar *bar;
8281 if (dpyinfo->grabbed && tracked_scroll_bar)
8283 bar = tracked_scroll_bar;
8284 control_part_code = kControlIndicatorPart;
8286 else
8287 bar = (struct scroll_bar *) GetControlReference (ch);
8288 x_scroll_bar_handle_click (bar, control_part_code,
8289 &er, &inev);
8290 if (er.what == mouseDown
8291 && control_part_code == kControlIndicatorPart)
8292 tracked_scroll_bar = bar;
8293 else
8294 tracked_scroll_bar = NULL;
8296 else
8298 Lisp_Object window;
8299 int x = mouse_loc.h;
8300 int y = mouse_loc.v;
8302 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8303 if (EQ (window, f->tool_bar_window))
8305 if (er.what == mouseDown)
8306 handle_tool_bar_click (f, x, y, 1, 0);
8307 else
8308 handle_tool_bar_click (f, x, y, 0,
8309 inev.modifiers);
8310 tool_bar_p = 1;
8312 else
8314 XSETFRAME (inev.frame_or_window, f);
8315 inev.kind = MOUSE_CLICK_EVENT;
8319 if (er.what == mouseDown)
8321 dpyinfo->grabbed |= (1 << inev.code);
8322 last_mouse_frame = f;
8323 /* Ignore any mouse motion that happened
8324 before this event; any subsequent
8325 mouse-movement Emacs events should reflect
8326 only motion after the ButtonPress. */
8327 if (f != 0)
8328 f->mouse_moved = 0;
8330 if (!tool_bar_p)
8331 last_tool_bar_item = -1;
8333 else
8335 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8336 /* If a button is released though it was not
8337 previously pressed, that would be because
8338 of multi-button emulation. */
8339 dpyinfo->grabbed = 0;
8340 else
8341 dpyinfo->grabbed &= ~(1 << inev.code);
8344 switch (er.what)
8346 case mouseDown:
8347 inev.modifiers |= down_modifier;
8348 break;
8349 case mouseUp:
8350 inev.modifiers |= up_modifier;
8351 break;
8354 break;
8356 case inDrag:
8357 #if TARGET_API_MAC_CARBON
8358 DragWindow (window_ptr, er.where, NULL);
8359 #else /* not TARGET_API_MAC_CARBON */
8360 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8361 #endif /* not TARGET_API_MAC_CARBON */
8362 /* Update the frame parameters. */
8364 struct frame *f = mac_window_to_frame (window_ptr);
8366 if (f && !f->async_iconified)
8367 x_real_positions (f, &f->left_pos, &f->top_pos);
8369 break;
8371 case inGoAway:
8372 if (TrackGoAway (window_ptr, er.where))
8374 inev.kind = DELETE_WINDOW_EVENT;
8375 XSETFRAME (inev.frame_or_window,
8376 mac_window_to_frame (window_ptr));
8378 break;
8380 /* window resize handling added --ben */
8381 case inGrow:
8382 do_grow_window (window_ptr, &er);
8383 break;
8385 /* window zoom handling added --ben */
8386 case inZoomIn:
8387 case inZoomOut:
8388 if (TrackBox (window_ptr, er.where, part_code))
8389 do_zoom_window (window_ptr, part_code);
8390 break;
8392 default:
8393 break;
8396 break;
8398 case updateEvt:
8399 #if USE_CARBON_EVENTS
8400 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8401 != eventNotHandledErr)
8402 break;
8403 #endif
8404 do_window_update ((WindowPtr) er.message);
8405 break;
8407 case osEvt:
8408 #if USE_CARBON_EVENTS
8409 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8410 != eventNotHandledErr)
8411 break;
8412 #endif
8413 switch ((er.message >> 24) & 0x000000FF)
8415 case suspendResumeMessage:
8416 if ((er.message & resumeFlag) == 1)
8417 do_app_resume ();
8418 else
8419 do_app_suspend ();
8420 break;
8422 case mouseMovedMessage:
8423 previous_help_echo_string = help_echo_string;
8424 help_echo_string = help_echo_object = help_echo_window = Qnil;
8425 help_echo_pos = -1;
8427 do_mouse_moved (er.where, &f);
8429 /* If the contents of the global variable
8430 help_echo_string has changed, generate a
8431 HELP_EVENT. */
8432 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8433 do_help = 1;
8434 break;
8436 break;
8438 case activateEvt:
8440 WindowPtr window_ptr = (WindowPtr) er.message;
8442 #if USE_CARBON_EVENTS
8443 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8444 != eventNotHandledErr)
8445 break;
8446 #endif
8447 if (window_ptr == tip_window)
8449 HideWindow (tip_window);
8450 break;
8453 if (!is_emacs_window (window_ptr))
8454 break;
8456 f = mac_window_to_frame (window_ptr);
8458 if ((er.modifiers & activeFlag) != 0)
8460 /* A window has been activated */
8461 Point mouse_loc = er.where;
8463 x_new_focus_frame (dpyinfo, f);
8464 activate_scroll_bars (f);
8466 SetPortWindowPort (window_ptr);
8467 GlobalToLocal (&mouse_loc);
8468 /* Window-activated event counts as mouse movement,
8469 so update things that depend on mouse position. */
8470 note_mouse_movement (mac_window_to_frame (window_ptr),
8471 &mouse_loc);
8473 else
8475 /* A window has been deactivated */
8476 dpyinfo->grabbed = 0;
8478 if (f == dpyinfo->x_focus_frame)
8480 x_new_focus_frame (dpyinfo, 0);
8481 deactivate_scroll_bars (f);
8485 if (f == dpyinfo->mouse_face_mouse_frame)
8487 /* If we move outside the frame, then we're
8488 certainly no longer on any text in the
8489 frame. */
8490 clear_mouse_face (dpyinfo);
8491 dpyinfo->mouse_face_mouse_frame = 0;
8494 /* Generate a nil HELP_EVENT to cancel a help-echo.
8495 Do it only if there's something to cancel.
8496 Otherwise, the startup message is cleared when the
8497 mouse leaves the frame. */
8498 if (any_help_event_p)
8499 do_help = -1;
8502 break;
8504 case keyDown:
8505 case autoKey:
8507 int keycode = (er.message & keyCodeMask) >> 8;
8508 int xkeysym;
8510 #if USE_CARBON_EVENTS
8511 /* When using Carbon Events, we need to pass raw keyboard
8512 events to the TSM ourselves. If TSM handles it, it
8513 will pass back noErr, otherwise it will pass back
8514 "eventNotHandledErr" and we can process it
8515 normally. */
8516 if ((!NILP (Vmac_pass_command_to_system)
8517 || !(er.modifiers & cmdKey))
8518 && (!NILP (Vmac_pass_control_to_system)
8519 || !(er.modifiers & controlKey)))
8520 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8521 != eventNotHandledErr)
8522 break;
8523 #endif
8525 #if TARGET_API_MAC_CARBON
8526 if (!IsValidWindowPtr (front_emacs_window ()))
8528 SysBeep (1);
8529 break;
8531 #endif
8533 ObscureCursor ();
8535 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8537 clear_mouse_face (dpyinfo);
8538 dpyinfo->mouse_face_hidden = 1;
8541 if (keycode_to_xkeysym (keycode, &xkeysym))
8543 inev.code = 0xff00 | xkeysym;
8544 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8546 else
8548 if (er.modifiers & (controlKey |
8549 (NILP (Vmac_command_key_is_meta) ? optionKey
8550 : cmdKey)))
8552 /* This code comes from Keyboard Resource,
8553 Appendix C of IM - Text. This is necessary
8554 since shift is ignored in KCHR table
8555 translation when option or command is pressed.
8556 It also does not translate correctly
8557 control-shift chars like C-% so mask off shift
8558 here also */
8559 int new_modifiers = er.modifiers & 0xe600;
8560 /* mask off option and command */
8561 int new_keycode = keycode | new_modifiers;
8562 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8563 unsigned long some_state = 0;
8564 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8565 &some_state) & 0xff;
8566 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
8568 /* When using the option key as an emacs modifier, convert
8569 the pressed key code back to one without the Mac option
8570 modifier applied. */
8571 int new_modifiers = er.modifiers & ~optionKey;
8572 int new_keycode = keycode | new_modifiers;
8573 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8574 unsigned long some_state = 0;
8575 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8576 &some_state) & 0xff;
8578 else
8579 inev.code = er.message & charCodeMask;
8580 inev.kind = ASCII_KEYSTROKE_EVENT;
8584 /* If variable mac-convert-keyboard-input-to-latin-1 is
8585 non-nil, convert non-ASCII characters typed at the Mac
8586 keyboard (presumed to be in the Mac Roman encoding) to
8587 iso-latin-1 encoding before they are passed to Emacs.
8588 This enables the Mac keyboard to be used to enter
8589 non-ASCII iso-latin-1 characters directly. */
8590 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
8591 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
8593 static TECObjectRef converter = NULL;
8594 OSStatus the_err = noErr;
8595 OSStatus convert_status = noErr;
8597 if (converter == NULL)
8599 the_err = TECCreateConverter (&converter,
8600 kTextEncodingMacRoman,
8601 mac_keyboard_text_encoding);
8602 current_mac_keyboard_text_encoding
8603 = mac_keyboard_text_encoding;
8605 else if (mac_keyboard_text_encoding
8606 != current_mac_keyboard_text_encoding)
8608 /* Free the converter for the current encoding
8609 before creating a new one. */
8610 TECDisposeConverter (converter);
8611 the_err = TECCreateConverter (&converter,
8612 kTextEncodingMacRoman,
8613 mac_keyboard_text_encoding);
8614 current_mac_keyboard_text_encoding
8615 = mac_keyboard_text_encoding;
8618 if (the_err == noErr)
8620 unsigned char ch = inev.code;
8621 ByteCount actual_input_length, actual_output_length;
8622 unsigned char outch;
8624 convert_status = TECConvertText (converter, &ch, 1,
8625 &actual_input_length,
8626 &outch, 1,
8627 &actual_output_length);
8628 if (convert_status == noErr
8629 && actual_input_length == 1
8630 && actual_output_length == 1)
8631 inev.code = outch;
8635 #if USE_CARBON_EVENTS
8636 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8637 #else
8638 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8639 #endif
8640 XSETFRAME (inev.frame_or_window,
8641 mac_window_to_frame (front_emacs_window ()));
8642 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8643 break;
8645 case kHighLevelEvent:
8646 drag_and_drop_file_list = Qnil;
8648 AEProcessAppleEvent(&er);
8650 /* Build a DRAG_N_DROP_EVENT type event as is done in
8651 constuct_drag_n_drop in w32term.c. */
8652 if (!NILP (drag_and_drop_file_list))
8654 struct frame *f = NULL;
8655 WindowPtr wp;
8656 Lisp_Object frame;
8658 wp = front_emacs_window ();
8660 if (!wp)
8662 struct frame *f = XFRAME (XCAR (Vframe_list));
8663 CollapseWindow (FRAME_MAC_WINDOW (f), false);
8664 wp = front_emacs_window ();
8667 if (wp)
8668 f = mac_window_to_frame (wp);
8670 inev.kind = DRAG_N_DROP_EVENT;
8671 inev.code = 0;
8672 inev.timestamp = er.when * (1000 / 60);
8673 /* ticks to milliseconds */
8674 #if USE_CARBON_EVENTS
8675 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8676 #else
8677 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8678 #endif
8680 XSETINT (inev.x, 0);
8681 XSETINT (inev.y, 0);
8683 XSETFRAME (frame, f);
8684 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8686 /* Regardless of whether Emacs was suspended or in the
8687 foreground, ask it to redraw its entire screen.
8688 Otherwise parts of the screen can be left in an
8689 inconsistent state. */
8690 if (wp)
8691 #if TARGET_API_MAC_CARBON
8693 Rect r;
8695 GetWindowPortBounds (wp, &r);
8696 InvalWindowRect (wp, &r);
8698 #else /* not TARGET_API_MAC_CARBON */
8699 InvalRect (&(wp->portRect));
8700 #endif /* not TARGET_API_MAC_CARBON */
8702 default:
8703 break;
8705 #if USE_CARBON_EVENTS
8706 ReleaseEvent (eventRef);
8707 #endif
8709 if (inev.kind != NO_EVENT)
8711 kbd_buffer_store_event_hold (&inev, hold_quit);
8712 count++;
8715 if (do_help
8716 && !(hold_quit && hold_quit->kind != NO_EVENT))
8718 Lisp_Object frame;
8720 if (f)
8721 XSETFRAME (frame, f);
8722 else
8723 frame = Qnil;
8725 if (do_help > 0)
8727 any_help_event_p = 1;
8728 gen_help_event (help_echo_string, frame, help_echo_window,
8729 help_echo_object, help_echo_pos);
8731 else
8733 help_echo_string = Qnil;
8734 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
8736 count++;
8741 /* If the focus was just given to an autoraising frame,
8742 raise it now. */
8743 /* ??? This ought to be able to handle more than one such frame. */
8744 if (pending_autoraise_frame)
8746 x_raise_frame (pending_autoraise_frame);
8747 pending_autoraise_frame = 0;
8750 #if !TARGET_API_MAC_CARBON
8751 check_alarm (); /* simulate the handling of a SIGALRM */
8752 #endif
8754 UNBLOCK_INPUT;
8755 return count;
8759 /* Need to override CodeWarrior's input function so no conversion is
8760 done on newlines Otherwise compiled functions in .elc files will be
8761 read incorrectly. Defined in ...:MSL C:MSL
8762 Common:Source:buffer_io.c. */
8763 #ifdef __MWERKS__
8764 void
8765 __convert_to_newlines (unsigned char * p, size_t * n)
8767 #pragma unused(p,n)
8770 void
8771 __convert_from_newlines (unsigned char * p, size_t * n)
8773 #pragma unused(p,n)
8775 #endif
8778 /* Initialize the struct pointed to by MW to represent a new COLS x
8779 ROWS Macintosh window, using font with name FONTNAME and size
8780 FONTSIZE. */
8781 void
8782 make_mac_frame (FRAME_PTR fp)
8784 mac_output *mwp;
8785 #if TARGET_API_MAC_CARBON
8786 static int making_terminal_window = 0;
8787 #else
8788 static int making_terminal_window = 1;
8789 #endif
8791 mwp = fp->output_data.mac;
8793 BLOCK_INPUT;
8794 if (making_terminal_window)
8796 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
8797 (WindowPtr) -1)))
8798 abort ();
8799 making_terminal_window = 0;
8801 else
8803 #if TARGET_API_MAC_CARBON
8804 Rect r;
8806 SetRect (&r, 0, 0, 1, 1);
8807 if (CreateNewWindow (kDocumentWindowClass,
8808 kWindowStandardDocumentAttributes
8809 /* | kWindowToolbarButtonAttribute */,
8810 &r, &mwp->mWP) != noErr)
8811 #else
8812 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
8813 #endif
8814 abort ();
8817 SetWRefCon (mwp->mWP, (long) mwp);
8818 /* so that update events can find this mac_output struct */
8819 mwp->mFP = fp; /* point back to emacs frame */
8821 SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
8822 UNBLOCK_INPUT;
8826 void
8827 make_mac_terminal_frame (struct frame *f)
8829 Lisp_Object frame;
8831 XSETFRAME (frame, f);
8833 f->output_method = output_mac;
8834 f->output_data.mac = (struct mac_output *)
8835 xmalloc (sizeof (struct mac_output));
8836 bzero (f->output_data.mac, sizeof (struct mac_output));
8838 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8840 FRAME_COLS (f) = 96;
8841 FRAME_LINES (f) = 4;
8843 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8844 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8846 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8848 f->output_data.mac->cursor_pixel = 0;
8849 f->output_data.mac->border_pixel = 0x00ff00;
8850 f->output_data.mac->mouse_pixel = 0xff00ff;
8851 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
8853 FRAME_FONTSET (f) = -1;
8854 f->output_data.mac->explicit_parent = 0;
8855 f->left_pos = 4;
8856 f->top_pos = 4;
8857 f->border_width = 0;
8859 f->internal_border_width = 0;
8861 f->auto_raise = 1;
8862 f->auto_lower = 1;
8864 f->new_text_cols = 0;
8865 f->new_text_lines = 0;
8867 make_mac_frame (f);
8869 x_make_gc (f);
8871 /* Need to be initialized for unshow_buffer in window.c. */
8872 selected_window = f->selected_window;
8874 Fmodify_frame_parameters (frame,
8875 Fcons (Fcons (Qfont,
8876 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
8877 Fmodify_frame_parameters (frame,
8878 Fcons (Fcons (Qforeground_color,
8879 build_string ("black")), Qnil));
8880 Fmodify_frame_parameters (frame,
8881 Fcons (Fcons (Qbackground_color,
8882 build_string ("white")), Qnil));
8884 ShowWindow (f->output_data.mac->mWP);
8888 /***********************************************************************
8889 Initialization
8890 ***********************************************************************/
8892 int mac_initialized = 0;
8894 void
8895 mac_initialize_display_info ()
8897 struct mac_display_info *dpyinfo = &one_mac_display_info;
8898 GDHandle main_device_handle;
8900 bzero (dpyinfo, sizeof (*dpyinfo));
8902 /* Put it on x_display_name_list. */
8903 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
8904 x_display_name_list);
8905 dpyinfo->name_list_element = XCAR (x_display_name_list);
8907 #if 0
8908 dpyinfo->mac_id_name
8909 = (char *) xmalloc (SCHARS (Vinvocation_name)
8910 + SCHARS (Vsystem_name)
8911 + 2);
8912 sprintf (dpyinfo->mac_id_name, "%s@%s",
8913 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8914 #else
8915 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
8916 strcpy (dpyinfo->mac_id_name, "Mac Display");
8917 #endif
8919 main_device_handle = LMGetMainDevice();
8921 dpyinfo->reference_count = 0;
8922 dpyinfo->resx = 75.0;
8923 dpyinfo->resy = 75.0;
8924 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
8925 #ifdef MAC_OSX
8926 /* HasDepth returns true if it is possible to have a 32 bit display,
8927 but this may not be what is actually used. Mac OSX can do better.
8928 CGMainDisplayID is only available on OSX 10.2 and higher, but the
8929 header for CGGetActiveDisplayList says that the first display returned
8930 is the active one, so we use that. */
8932 CGDirectDisplayID disp_id[1];
8933 CGDisplayCount disp_count;
8934 CGDisplayErr error_code;
8936 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
8937 if (error_code != 0)
8938 error ("No display found, CGGetActiveDisplayList error %d", error_code);
8940 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
8942 #else
8943 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
8944 if (HasDepth (main_device_handle, dpyinfo->n_planes,
8945 gdDevType, dpyinfo->color_p))
8946 break;
8947 #endif
8948 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8949 dpyinfo->width = (**main_device_handle).gdRect.right;
8950 dpyinfo->grabbed = 0;
8951 dpyinfo->root_window = NULL;
8952 dpyinfo->image_cache = make_image_cache ();
8954 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8955 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8956 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8957 dpyinfo->mouse_face_window = Qnil;
8958 dpyinfo->mouse_face_overlay = Qnil;
8959 dpyinfo->mouse_face_hidden = 0;
8962 struct mac_display_info *
8963 mac_term_init (display_name, xrm_option, resource_name)
8964 Lisp_Object display_name;
8965 char *xrm_option;
8966 char *resource_name;
8968 struct mac_display_info *dpyinfo;
8969 GDHandle main_device_handle;
8971 if (!mac_initialized)
8973 mac_initialize ();
8974 mac_initialized = 1;
8977 mac_initialize_display_info (display_name);
8979 dpyinfo = &one_mac_display_info;
8981 main_device_handle = LMGetMainDevice();
8983 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8984 dpyinfo->width = (**main_device_handle).gdRect.right;
8986 return dpyinfo;
8989 #ifdef MAC_OSX
8990 void
8991 mac_check_bundle()
8993 extern int inhibit_window_system;
8994 extern int noninteractive;
8995 CFBundleRef appsBundle;
8996 pid_t child;
8998 /* No need to test if already -nw*/
8999 if (inhibit_window_system || noninteractive)
9000 return;
9002 appsBundle = CFBundleGetMainBundle();
9003 if (appsBundle != NULL)
9005 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9006 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9007 /* We found the bundle identifier, now we know we are valid. */
9008 if (res != NULL)
9010 CFRelease(res);
9011 return;
9014 /* MAC_TODO: Have this start the bundled executable */
9016 /* For now, prevent the fatal error by bringing it up in the terminal */
9017 inhibit_window_system = 1;
9020 void
9021 MakeMeTheFrontProcess ()
9023 ProcessSerialNumber psn;
9024 OSErr err;
9026 err = GetCurrentProcess (&psn);
9027 if (err == noErr)
9028 (void) SetFrontProcess (&psn);
9031 /***** Code to handle C-g testing *****/
9033 /* Contains the Mac modifier formed from quit_char */
9034 static mac_quit_char_modifiers = 0;
9035 static mac_quit_char_keycode;
9036 extern int quit_char;
9038 static void
9039 mac_determine_quit_char_modifiers()
9041 /* Todo: Determine modifiers from quit_char. */
9042 UInt32 qc_modifiers = ctrl_modifier;
9044 /* Map modifiers */
9045 mac_quit_char_modifiers = 0;
9046 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9047 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9048 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9049 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9052 static void
9053 init_quit_char_handler ()
9055 /* TODO: Let this support keys other the 'g' */
9056 mac_quit_char_keycode = 5;
9057 /* Look at <architecture/adb_kb_map.h> for details */
9058 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9060 mac_determine_quit_char_modifiers();
9063 static Boolean
9064 quit_char_comp (EventRef inEvent, void *inCompData)
9066 if (GetEventClass(inEvent) != kEventClassKeyboard)
9067 return false;
9068 if (GetEventKind(inEvent) != kEventRawKeyDown)
9069 return false;
9071 UInt32 keyCode;
9072 UInt32 keyModifiers;
9073 GetEventParameter(inEvent, kEventParamKeyCode,
9074 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9075 if (keyCode != mac_quit_char_keycode)
9076 return false;
9077 GetEventParameter(inEvent, kEventParamKeyModifiers,
9078 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9079 if (keyModifiers != mac_quit_char_modifiers)
9080 return false;
9082 return true;
9085 void
9086 mac_check_for_quit_char ()
9088 EventRef event;
9089 static EMACS_TIME last_check_time = { 0, 0 };
9090 static EMACS_TIME one_second = { 1, 0 };
9091 EMACS_TIME now, t;
9093 /* If windows are not initialized, return immediately (keep it bouncin'). */
9094 if (!mac_quit_char_modifiers)
9095 return;
9097 /* Don't check if last check is less than a second ago. */
9098 EMACS_GET_TIME (now);
9099 EMACS_SUB_TIME (t, now, last_check_time);
9100 if (EMACS_TIME_LT (t, one_second))
9101 return;
9102 last_check_time = now;
9104 /* Redetermine modifiers because they are based on lisp variables */
9105 mac_determine_quit_char_modifiers ();
9107 /* Fill the queue with events */
9108 BLOCK_INPUT;
9109 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9110 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9111 NULL);
9112 UNBLOCK_INPUT;
9113 if (event)
9115 struct input_event e;
9117 /* Use an input_event to emulate what the interrupt handler does. */
9118 EVENT_INIT (e);
9119 e.kind = ASCII_KEYSTROKE_EVENT;
9120 e.code = quit_char;
9121 e.arg = Qnil;
9122 e.modifiers = NULL;
9123 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9124 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9125 /* Remove event from queue to prevent looping. */
9126 RemoveEventFromQueue (GetMainEventQueue (), event);
9127 ReleaseEvent (event);
9128 kbd_buffer_store_event (&e);
9132 #endif /* MAC_OSX */
9134 /* Set up use of X before we make the first connection. */
9136 extern frame_parm_handler mac_frame_parm_handlers[];
9138 static struct redisplay_interface x_redisplay_interface =
9140 mac_frame_parm_handlers,
9141 x_produce_glyphs,
9142 x_write_glyphs,
9143 x_insert_glyphs,
9144 x_clear_end_of_line,
9145 x_scroll_run,
9146 x_after_update_window_line,
9147 x_update_window_begin,
9148 x_update_window_end,
9149 x_cursor_to,
9150 x_flush,
9151 x_flush,
9152 x_clear_window_mouse_face,
9153 x_get_glyph_overhangs,
9154 x_fix_overlapping_area,
9155 x_draw_fringe_bitmap,
9156 0, /* define_fringe_bitmap */
9157 0, /* destroy_fringe_bitmap */
9158 mac_per_char_metric,
9159 mac_encode_char,
9160 NULL, /* mac_compute_glyph_string_overhangs */
9161 x_draw_glyph_string,
9162 mac_define_frame_cursor,
9163 mac_clear_frame_area,
9164 mac_draw_window_cursor,
9165 mac_draw_vertical_window_border,
9166 mac_shift_glyphs_for_insert
9169 void
9170 mac_initialize ()
9172 rif = &x_redisplay_interface;
9174 clear_frame_hook = x_clear_frame;
9175 ins_del_lines_hook = x_ins_del_lines;
9176 delete_glyphs_hook = x_delete_glyphs;
9177 ring_bell_hook = XTring_bell;
9178 reset_terminal_modes_hook = XTreset_terminal_modes;
9179 set_terminal_modes_hook = XTset_terminal_modes;
9180 update_begin_hook = x_update_begin;
9181 update_end_hook = x_update_end;
9182 set_terminal_window_hook = XTset_terminal_window;
9183 read_socket_hook = XTread_socket;
9184 frame_up_to_date_hook = XTframe_up_to_date;
9185 mouse_position_hook = XTmouse_position;
9186 frame_rehighlight_hook = XTframe_rehighlight;
9187 frame_raise_lower_hook = XTframe_raise_lower;
9189 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9190 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9191 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9192 judge_scroll_bars_hook = XTjudge_scroll_bars;
9194 scroll_region_ok = 1; /* we'll scroll partial frames */
9195 char_ins_del_ok = 1;
9196 line_ins_del_ok = 1; /* we'll just blt 'em */
9197 fast_clear_end_of_line = 1; /* X does this well */
9198 memory_below_frame = 0; /* we don't remember what scrolls
9199 off the bottom */
9200 baud_rate = 19200;
9202 x_noop_count = 0;
9203 last_tool_bar_item = -1;
9204 any_help_event_p = 0;
9206 /* Try to use interrupt input; if we can't, then start polling. */
9207 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9209 #ifdef USE_X_TOOLKIT
9210 XtToolkitInitialize ();
9211 Xt_app_con = XtCreateApplicationContext ();
9212 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9214 /* Install an asynchronous timer that processes Xt timeout events
9215 every 0.1s. This is necessary because some widget sets use
9216 timeouts internally, for example the LessTif menu bar, or the
9217 Xaw3d scroll bar. When Xt timouts aren't processed, these
9218 widgets don't behave normally. */
9220 EMACS_TIME interval;
9221 EMACS_SET_SECS_USECS (interval, 0, 100000);
9222 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9224 #endif
9226 #if USE_TOOLKIT_SCROLL_BARS
9227 xaw3d_arrow_scroll = False;
9228 xaw3d_pick_top = True;
9229 #endif
9231 #if 0
9232 /* Note that there is no real way portable across R3/R4 to get the
9233 original error handler. */
9234 XSetErrorHandler (x_error_handler);
9235 XSetIOErrorHandler (x_io_error_quitter);
9237 /* Disable Window Change signals; they are handled by X events. */
9238 #ifdef SIGWINCH
9239 signal (SIGWINCH, SIG_DFL);
9240 #endif /* ! defined (SIGWINCH) */
9242 signal (SIGPIPE, x_connection_signal);
9243 #endif
9245 BLOCK_INPUT;
9246 mac_initialize_display_info ();
9248 #if TARGET_API_MAC_CARBON
9249 init_required_apple_events ();
9251 init_mac_drag_n_drop ();
9253 #if USE_CARBON_EVENTS
9254 init_service_handler ();
9256 init_quit_char_handler ();
9257 #endif
9259 DisableMenuCommand (NULL, kHICommandQuit);
9261 if (!inhibit_window_system)
9262 MakeMeTheFrontProcess ();
9263 #endif
9264 UNBLOCK_INPUT;
9268 void
9269 syms_of_macterm ()
9271 #if 0
9272 staticpro (&x_error_message_string);
9273 x_error_message_string = Qnil;
9274 #endif
9276 Qmodifier_value = intern ("modifier-value");
9277 Qalt = intern ("alt");
9278 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9279 Qhyper = intern ("hyper");
9280 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9281 Qsuper = intern ("super");
9282 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9284 Fprovide (intern ("mac-carbon"), Qnil);
9286 staticpro (&Qreverse);
9287 Qreverse = intern ("reverse");
9289 staticpro (&x_display_name_list);
9290 x_display_name_list = Qnil;
9292 staticpro (&last_mouse_scroll_bar);
9293 last_mouse_scroll_bar = Qnil;
9295 staticpro (&Qvendor_specific_keysyms);
9296 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9298 staticpro (&last_mouse_press_frame);
9299 last_mouse_press_frame = Qnil;
9301 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9302 staticpro (&Qmac_ready_for_drag_n_drop);
9304 Qbig5 = intern ("big5");
9305 staticpro (&Qbig5);
9307 Qcn_gb = intern ("cn-gb");
9308 staticpro (&Qcn_gb);
9310 Qsjis = intern ("sjis");
9311 staticpro (&Qsjis);
9313 Qeuc_kr = intern ("euc-kr");
9314 staticpro (&Qeuc_kr);
9316 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9317 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9318 x_autoselect_window_p = 0;
9320 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9321 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9322 Vx_toolkit_scroll_bars = Qt;
9324 DEFVAR_BOOL ("x-use-underline-position-properties",
9325 &x_use_underline_position_properties,
9326 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9327 nil means ignore them. If you encounter fonts with bogus
9328 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9329 to 4.1, set this to nil. */);
9330 x_use_underline_position_properties = 0;
9332 staticpro (&last_mouse_motion_frame);
9333 last_mouse_motion_frame = Qnil;
9335 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9336 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9337 Otherwise the option key is used. */);
9338 Vmac_command_key_is_meta = Qt;
9340 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9341 doc: /* Modifier to use for the Mac alt/option key. The value can
9342 be alt, hyper, or super for the respective modifier. If the value is
9343 nil then the key will act as the normal Mac option modifier. */);
9344 Vmac_option_modifier = Qnil;
9346 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9347 doc: /* Non-nil means that the control and meta keys are reversed. This is
9348 useful for non-standard keyboard layouts. */);
9349 Vmac_reverse_ctrl_meta = Qnil;
9351 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9352 &Vmac_emulate_three_button_mouse,
9353 doc: /* t means that when the option-key is held down while pressing the
9354 mouse button, the click will register as mouse-2 and while the
9355 command-key is held down, the click will register as mouse-3.
9356 'reverse means that the the option-key will register for mouse-3
9357 and the command-key will register for mouse-2. nil means that
9358 not emulation should be done and the modifiers should be placed
9359 on the mouse-1 event. */);
9360 Vmac_emulate_three_button_mouse = Qnil;
9362 #if USE_CARBON_EVENTS
9363 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9364 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9365 the right click will be mouse-3.
9366 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9367 Vmac_wheel_button_is_mouse_2 = Qt;
9369 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9370 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9371 Toolbox for processing before Emacs sees it. */);
9372 Vmac_pass_command_to_system = Qt;
9374 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9375 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9376 Toolbox for processing before Emacs sees it. */);
9377 Vmac_pass_control_to_system = Qt;
9378 #endif
9380 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9381 doc: /* One of the Text Encoding Base constant values defined in the
9382 Basic Text Constants section of Inside Macintosh - Text Encoding
9383 Conversion Manager. Its value determines the encoding characters
9384 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9385 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9386 its default value, no conversion takes place. If it is set to
9387 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9388 characters typed on Mac keyboard are first converted into the
9389 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9390 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9391 command, this enables the Mac keyboard to be used to enter non-ASCII
9392 characters directly. */);
9393 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9396 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9397 (do not change this comment) */