(map-keymap): Definition deleted.
[emacs.git] / src / macterm.c
blobeae892fb7fc0fc3ae058c965339243937a30c402
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 *, 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, gc);
1458 row->y = oldY;
1459 row->visible_height = oldVH;
1461 else
1462 x_clip_to_row (w, row, 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, gc)
4619 struct window *w;
4620 struct glyph_row *row;
4621 GC gc;
4623 struct frame *f = XFRAME (WINDOW_FRAME (w));
4624 Rect clip_rect;
4625 int window_y, window_width;
4627 window_box (w, -1, 0, &window_y, &window_width, 0);
4629 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
4630 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4631 clip_rect.top = max (clip_rect.top, window_y);
4632 clip_rect.right = clip_rect.left + window_width;
4633 clip_rect.bottom = clip_rect.top + row->visible_height;
4635 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4639 /* Draw a hollow box cursor on window W in glyph row ROW. */
4641 static void
4642 x_draw_hollow_cursor (w, row)
4643 struct window *w;
4644 struct glyph_row *row;
4646 struct frame *f = XFRAME (WINDOW_FRAME (w));
4647 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4648 Display *dpy = FRAME_MAC_DISPLAY (f);
4649 int x, y, wd, h;
4650 XGCValues xgcv;
4651 struct glyph *cursor_glyph;
4652 GC gc;
4654 /* Get the glyph the cursor is on. If we can't tell because
4655 the current matrix is invalid or such, give up. */
4656 cursor_glyph = get_phys_cursor_glyph (w);
4657 if (cursor_glyph == NULL)
4658 return;
4660 /* Compute the width of the rectangle to draw. If on a stretch
4661 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4662 rectangle as wide as the glyph, but use a canonical character
4663 width instead. */
4664 wd = cursor_glyph->pixel_width - 1;
4665 if (cursor_glyph->type == STRETCH_GLYPH
4666 && !x_stretch_cursor_p)
4667 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4668 w->phys_cursor_width = wd;
4670 /* Compute frame-relative coordinates from window-relative
4671 coordinates. */
4672 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4673 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4675 /* Compute the proper height and ascent of the rectangle, based
4676 on the actual glyph. Using the full height of the row looks
4677 bad when there are tall images on that row. */
4678 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4679 cursor_glyph->ascent + cursor_glyph->descent);
4680 if (h < row->height)
4681 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4682 h--;
4684 /* The foreground of cursor_gc is typically the same as the normal
4685 background color, which can cause the cursor box to be invisible. */
4686 xgcv.foreground = f->output_data.mac->cursor_pixel;
4687 if (dpyinfo->scratch_cursor_gc)
4688 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4689 else
4690 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4691 GCForeground, &xgcv);
4692 gc = dpyinfo->scratch_cursor_gc;
4694 /* Set clipping, draw the rectangle, and reset clipping again. */
4695 x_clip_to_row (w, row, gc);
4696 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4697 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4701 /* Draw a bar cursor on window W in glyph row ROW.
4703 Implementation note: One would like to draw a bar cursor with an
4704 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4705 Unfortunately, I didn't find a font yet that has this property set.
4706 --gerd. */
4708 static void
4709 x_draw_bar_cursor (w, row, width, kind)
4710 struct window *w;
4711 struct glyph_row *row;
4712 int width;
4713 enum text_cursor_kinds kind;
4715 struct frame *f = XFRAME (w->frame);
4716 struct glyph *cursor_glyph;
4718 /* If cursor is out of bounds, don't draw garbage. This can happen
4719 in mini-buffer windows when switching between echo area glyphs
4720 and mini-buffer. */
4721 cursor_glyph = get_phys_cursor_glyph (w);
4722 if (cursor_glyph == NULL)
4723 return;
4725 /* If on an image, draw like a normal cursor. That's usually better
4726 visible than drawing a bar, esp. if the image is large so that
4727 the bar might not be in the window. */
4728 if (cursor_glyph->type == IMAGE_GLYPH)
4730 struct glyph_row *row;
4731 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4732 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4734 else
4736 Display *dpy = FRAME_MAC_DISPLAY (f);
4737 Window window = FRAME_MAC_WINDOW (f);
4738 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4739 unsigned long mask = GCForeground | GCBackground;
4740 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4741 XGCValues xgcv;
4743 /* If the glyph's background equals the color we normally draw
4744 the bar cursor in, the bar cursor in its normal color is
4745 invisible. Use the glyph's foreground color instead in this
4746 case, on the assumption that the glyph's colors are chosen so
4747 that the glyph is legible. */
4748 if (face->background == f->output_data.mac->cursor_pixel)
4749 xgcv.background = xgcv.foreground = face->foreground;
4750 else
4751 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4753 if (gc)
4754 XChangeGC (dpy, gc, mask, &xgcv);
4755 else
4757 gc = XCreateGC (dpy, window, mask, &xgcv);
4758 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4761 if (width < 0)
4762 width = FRAME_CURSOR_WIDTH (f);
4763 width = min (cursor_glyph->pixel_width, width);
4765 w->phys_cursor_width = width;
4766 x_clip_to_row (w, row, gc);
4768 if (kind == BAR_CURSOR)
4769 XFillRectangle (dpy, window, gc,
4770 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4771 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4772 width, row->height);
4773 else
4774 XFillRectangle (dpy, window, gc,
4775 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4776 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4777 row->height - width),
4778 cursor_glyph->pixel_width,
4779 width);
4781 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4786 /* RIF: Define cursor CURSOR on frame F. */
4788 static void
4789 mac_define_frame_cursor (f, cursor)
4790 struct frame *f;
4791 Cursor cursor;
4793 #if TARGET_API_MAC_CARBON
4794 SetThemeCursor (cursor);
4795 #else
4796 SetCursor (*cursor);
4797 #endif
4801 /* RIF: Clear area on frame F. */
4803 static void
4804 mac_clear_frame_area (f, x, y, width, height)
4805 struct frame *f;
4806 int x, y, width, height;
4808 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4809 x, y, width, height, 0);
4813 /* RIF: Draw cursor on window W. */
4815 static void
4816 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4817 struct window *w;
4818 struct glyph_row *glyph_row;
4819 int x, y;
4820 int cursor_type, cursor_width;
4821 int on_p, active_p;
4823 if (on_p)
4825 w->phys_cursor_type = cursor_type;
4826 w->phys_cursor_on_p = 1;
4828 if (glyph_row->exact_window_width_line_p
4829 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4831 glyph_row->cursor_in_fringe_p = 1;
4832 draw_fringe_bitmap (w, glyph_row, 0);
4834 else
4835 switch (cursor_type)
4837 case HOLLOW_BOX_CURSOR:
4838 x_draw_hollow_cursor (w, glyph_row);
4839 break;
4841 case FILLED_BOX_CURSOR:
4842 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4843 break;
4845 case BAR_CURSOR:
4846 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4847 break;
4849 case HBAR_CURSOR:
4850 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4851 break;
4853 case NO_CURSOR:
4854 w->phys_cursor_width = 0;
4855 break;
4857 default:
4858 abort ();
4864 /* Icons. */
4866 #if 0 /* MAC_TODO: no icon support yet. */
4868 x_bitmap_icon (f, icon)
4869 struct frame *f;
4870 Lisp_Object icon;
4872 HANDLE hicon;
4874 if (FRAME_W32_WINDOW (f) == 0)
4875 return 1;
4877 if (NILP (icon))
4878 hicon = LoadIcon (hinst, EMACS_CLASS);
4879 else if (STRINGP (icon))
4880 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4881 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4882 else if (SYMBOLP (icon))
4884 LPCTSTR name;
4886 if (EQ (icon, intern ("application")))
4887 name = (LPCTSTR) IDI_APPLICATION;
4888 else if (EQ (icon, intern ("hand")))
4889 name = (LPCTSTR) IDI_HAND;
4890 else if (EQ (icon, intern ("question")))
4891 name = (LPCTSTR) IDI_QUESTION;
4892 else if (EQ (icon, intern ("exclamation")))
4893 name = (LPCTSTR) IDI_EXCLAMATION;
4894 else if (EQ (icon, intern ("asterisk")))
4895 name = (LPCTSTR) IDI_ASTERISK;
4896 else if (EQ (icon, intern ("winlogo")))
4897 name = (LPCTSTR) IDI_WINLOGO;
4898 else
4899 return 1;
4901 hicon = LoadIcon (NULL, name);
4903 else
4904 return 1;
4906 if (hicon == NULL)
4907 return 1;
4909 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4910 (LPARAM) hicon);
4912 return 0;
4914 #endif /* MAC_TODO */
4916 /************************************************************************
4917 Handling X errors
4918 ************************************************************************/
4920 /* Display Error Handling functions not used on W32. Listing them here
4921 helps diff stay in step when comparing w32term.c with xterm.c.
4923 x_error_catcher (display, error)
4924 x_catch_errors (dpy)
4925 x_catch_errors_unwind (old_val)
4926 x_check_errors (dpy, format)
4927 x_had_errors_p (dpy)
4928 x_clear_errors (dpy)
4929 x_uncatch_errors (dpy, count)
4930 x_trace_wire ()
4931 x_connection_signal (signalnum)
4932 x_connection_closed (dpy, error_message)
4933 x_error_quitter (display, error)
4934 x_error_handler (display, error)
4935 x_io_error_quitter (display)
4940 /* Changing the font of the frame. */
4942 /* Give frame F the font named FONTNAME as its default font, and
4943 return the full name of that font. FONTNAME may be a wildcard
4944 pattern; in that case, we choose some font that fits the pattern.
4945 The return value shows which font we chose. */
4947 Lisp_Object
4948 x_new_font (f, fontname)
4949 struct frame *f;
4950 register char *fontname;
4952 struct font_info *fontp
4953 = FS_LOAD_FONT (f, 0, fontname, -1);
4955 if (!fontp)
4956 return Qnil;
4958 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4959 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4960 FRAME_FONTSET (f) = -1;
4962 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4963 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4965 compute_fringe_widths (f, 1);
4967 /* Compute the scroll bar width in character columns. */
4968 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4970 int wid = FRAME_COLUMN_WIDTH (f);
4971 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4972 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4974 else
4976 int wid = FRAME_COLUMN_WIDTH (f);
4977 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4980 /* Now make the frame display the given font. */
4981 if (FRAME_MAC_WINDOW (f) != 0)
4983 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4984 FRAME_FONT (f));
4985 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4986 FRAME_FONT (f));
4987 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4988 FRAME_FONT (f));
4990 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4991 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4994 return build_string (fontp->full_name);
4997 /* Give frame F the fontset named FONTSETNAME as its default font, and
4998 return the full name of that fontset. FONTSETNAME may be a wildcard
4999 pattern; in that case, we choose some fontset that fits the pattern.
5000 The return value shows which fontset we chose. */
5002 Lisp_Object
5003 x_new_fontset (f, fontsetname)
5004 struct frame *f;
5005 char *fontsetname;
5007 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5008 Lisp_Object result;
5010 if (fontset < 0)
5011 return Qnil;
5013 if (FRAME_FONTSET (f) == fontset)
5014 /* This fontset is already set in frame F. There's nothing more
5015 to do. */
5016 return fontset_name (fontset);
5018 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5020 if (!STRINGP (result))
5021 /* Can't load ASCII font. */
5022 return Qnil;
5024 /* Since x_new_font doesn't update any fontset information, do it now. */
5025 FRAME_FONTSET(f) = fontset;
5027 return build_string (fontsetname);
5031 /***********************************************************************
5032 TODO: W32 Input Methods
5033 ***********************************************************************/
5034 /* Listing missing functions from xterm.c helps diff stay in step.
5036 xim_destroy_callback (xim, client_data, call_data)
5037 xim_open_dpy (dpyinfo, resource_name)
5038 struct xim_inst_t
5039 xim_instantiate_callback (display, client_data, call_data)
5040 xim_initialize (dpyinfo, resource_name)
5041 xim_close_dpy (dpyinfo)
5046 void
5047 mac_get_window_bounds (f, inner, outer)
5048 struct frame *f;
5049 Rect *inner, *outer;
5051 #if TARGET_API_MAC_CARBON
5052 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5053 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5054 #else /* not TARGET_API_MAC_CARBON */
5055 RgnHandle region = NewRgn ();
5057 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5058 *inner = (*region)->rgnBBox;
5059 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5060 *outer = (*region)->rgnBBox;
5061 DisposeRgn (region);
5062 #endif /* not TARGET_API_MAC_CARBON */
5066 /* Calculate the absolute position in frame F
5067 from its current recorded position values and gravity. */
5069 void
5070 x_calc_absolute_position (f)
5071 struct frame *f;
5073 int width_diff = 0, height_diff = 0;
5074 int flags = f->size_hint_flags;
5075 Rect inner, outer;
5077 /* We have nothing to do if the current position
5078 is already for the top-left corner. */
5079 if (! ((flags & XNegative) || (flags & YNegative)))
5080 return;
5082 /* Find the offsets of the outside upper-left corner of
5083 the inner window, with respect to the outer window. */
5084 mac_get_window_bounds (f, &inner, &outer);
5086 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5087 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5089 /* Treat negative positions as relative to the leftmost bottommost
5090 position that fits on the screen. */
5091 if (flags & XNegative)
5092 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5093 - width_diff
5094 - FRAME_PIXEL_WIDTH (f)
5095 + f->left_pos);
5097 if (flags & YNegative)
5098 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5099 - height_diff
5100 - FRAME_PIXEL_HEIGHT (f)
5101 + f->top_pos);
5103 /* The left_pos and top_pos
5104 are now relative to the top and left screen edges,
5105 so the flags should correspond. */
5106 f->size_hint_flags &= ~ (XNegative | YNegative);
5109 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5110 to really change the position, and 0 when calling from
5111 x_make_frame_visible (in that case, XOFF and YOFF are the current
5112 position values). It is -1 when calling from x_set_frame_parameters,
5113 which means, do adjust for borders but don't change the gravity. */
5115 void
5116 x_set_offset (f, xoff, yoff, change_gravity)
5117 struct frame *f;
5118 register int xoff, yoff;
5119 int change_gravity;
5121 if (change_gravity > 0)
5123 f->top_pos = yoff;
5124 f->left_pos = xoff;
5125 f->size_hint_flags &= ~ (XNegative | YNegative);
5126 if (xoff < 0)
5127 f->size_hint_flags |= XNegative;
5128 if (yoff < 0)
5129 f->size_hint_flags |= YNegative;
5130 f->win_gravity = NorthWestGravity;
5132 x_calc_absolute_position (f);
5134 BLOCK_INPUT;
5135 x_wm_set_size_hint (f, (long) 0, 0);
5137 #if TARGET_API_MAC_CARBON
5138 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5139 /* If the title bar is completely outside the screen, adjust the
5140 position. */
5141 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5142 kWindowConstrainMoveRegardlessOfFit
5143 | kWindowConstrainAllowPartial, NULL, NULL);
5144 x_real_positions (f, &f->left_pos, &f->top_pos);
5145 #else
5147 Rect inner, outer, screen_rect, dummy;
5148 RgnHandle region = NewRgn ();
5150 mac_get_window_bounds (f, &inner, &outer);
5151 f->x_pixels_diff = inner.left - outer.left;
5152 f->y_pixels_diff = inner.top - outer.top;
5153 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5154 f->top_pos + f->y_pixels_diff, false);
5156 /* If the title bar is completely outside the screen, adjust the
5157 position. The variable `outer' holds the title bar rectangle.
5158 The variable `inner' holds slightly smaller one than `outer',
5159 so that the calculation of overlapping may not become too
5160 strict. */
5161 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5162 outer = (*region)->rgnBBox;
5163 DisposeRgn (region);
5164 inner = outer;
5165 InsetRect (&inner, 8, 8);
5166 screen_rect = qd.screenBits.bounds;
5167 screen_rect.top += GetMBarHeight ();
5169 if (!SectRect (&inner, &screen_rect, &dummy))
5171 if (inner.right <= screen_rect.left)
5172 f->left_pos = screen_rect.left;
5173 else if (inner.left >= screen_rect.right)
5174 f->left_pos = screen_rect.right - (outer.right - outer.left);
5176 if (inner.bottom <= screen_rect.top)
5177 f->top_pos = screen_rect.top;
5178 else if (inner.top >= screen_rect.bottom)
5179 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5181 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5182 f->top_pos + f->y_pixels_diff, false);
5185 #endif
5187 UNBLOCK_INPUT;
5190 /* Call this to change the size of frame F's x-window.
5191 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5192 for this size change and subsequent size changes.
5193 Otherwise we leave the window gravity unchanged. */
5195 void
5196 x_set_window_size (f, change_gravity, cols, rows)
5197 struct frame *f;
5198 int change_gravity;
5199 int cols, rows;
5201 int pixelwidth, pixelheight;
5203 BLOCK_INPUT;
5205 check_frame_size (f, &rows, &cols);
5206 f->scroll_bar_actual_width
5207 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5209 compute_fringe_widths (f, 0);
5211 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5212 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5214 f->win_gravity = NorthWestGravity;
5215 x_wm_set_size_hint (f, (long) 0, 0);
5217 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5219 /* Now, strictly speaking, we can't be sure that this is accurate,
5220 but the window manager will get around to dealing with the size
5221 change request eventually, and we'll hear how it went when the
5222 ConfigureNotify event gets here.
5224 We could just not bother storing any of this information here,
5225 and let the ConfigureNotify event set everything up, but that
5226 might be kind of confusing to the Lisp code, since size changes
5227 wouldn't be reported in the frame parameters until some random
5228 point in the future when the ConfigureNotify event arrives.
5230 We pass 1 for DELAY since we can't run Lisp code inside of
5231 a BLOCK_INPUT. */
5232 change_frame_size (f, rows, cols, 0, 1, 0);
5233 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5234 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5236 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5237 receive in the ConfigureNotify event; if we get what we asked
5238 for, then the event won't cause the screen to become garbaged, so
5239 we have to make sure to do it here. */
5240 SET_FRAME_GARBAGED (f);
5242 XFlush (FRAME_X_DISPLAY (f));
5244 /* If cursor was outside the new size, mark it as off. */
5245 mark_window_cursors_off (XWINDOW (f->root_window));
5247 /* Clear out any recollection of where the mouse highlighting was,
5248 since it might be in a place that's outside the new frame size.
5249 Actually checking whether it is outside is a pain in the neck,
5250 so don't try--just let the highlighting be done afresh with new size. */
5251 cancel_mouse_face (f);
5253 UNBLOCK_INPUT;
5256 /* Mouse warping. */
5258 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5260 void
5261 x_set_mouse_position (f, x, y)
5262 struct frame *f;
5263 int x, y;
5265 int pix_x, pix_y;
5267 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5268 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5270 if (pix_x < 0) pix_x = 0;
5271 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5273 if (pix_y < 0) pix_y = 0;
5274 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5276 x_set_mouse_pixel_position (f, pix_x, pix_y);
5279 void
5280 x_set_mouse_pixel_position (f, pix_x, pix_y)
5281 struct frame *f;
5282 int pix_x, pix_y;
5284 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5285 BLOCK_INPUT;
5287 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5288 0, 0, 0, 0, pix_x, pix_y);
5289 UNBLOCK_INPUT;
5290 #endif
5294 /* focus shifting, raising and lowering. */
5296 void
5297 x_focus_on_frame (f)
5298 struct frame *f;
5300 #if 0 /* This proves to be unpleasant. */
5301 x_raise_frame (f);
5302 #endif
5303 #if 0
5304 /* I don't think that the ICCCM allows programs to do things like this
5305 without the interaction of the window manager. Whatever you end up
5306 doing with this code, do it to x_unfocus_frame too. */
5307 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5308 RevertToPointerRoot, CurrentTime);
5309 #endif /* ! 0 */
5312 void
5313 x_unfocus_frame (f)
5314 struct frame *f;
5318 /* Raise frame F. */
5319 void
5320 x_raise_frame (f)
5321 struct frame *f;
5323 if (f->async_visible)
5325 BLOCK_INPUT;
5326 SelectWindow (FRAME_MAC_WINDOW (f));
5327 UNBLOCK_INPUT;
5331 /* Lower frame F. */
5332 void
5333 x_lower_frame (f)
5334 struct frame *f;
5336 if (f->async_visible)
5338 BLOCK_INPUT;
5339 SendBehind (FRAME_MAC_WINDOW (f), nil);
5340 UNBLOCK_INPUT;
5344 static void
5345 XTframe_raise_lower (f, raise_flag)
5346 FRAME_PTR f;
5347 int raise_flag;
5349 if (raise_flag)
5350 x_raise_frame (f);
5351 else
5352 x_lower_frame (f);
5355 /* Change of visibility. */
5357 /* This tries to wait until the frame is really visible.
5358 However, if the window manager asks the user where to position
5359 the frame, this will return before the user finishes doing that.
5360 The frame will not actually be visible at that time,
5361 but it will become visible later when the window manager
5362 finishes with it. */
5364 void
5365 x_make_frame_visible (f)
5366 struct frame *f;
5368 Lisp_Object type;
5369 int original_top, original_left;
5371 BLOCK_INPUT;
5373 if (! FRAME_VISIBLE_P (f))
5375 /* We test FRAME_GARBAGED_P here to make sure we don't
5376 call x_set_offset a second time
5377 if we get to x_make_frame_visible a second time
5378 before the window gets really visible. */
5379 if (! FRAME_ICONIFIED_P (f)
5380 && ! f->output_data.mac->asked_for_visible)
5381 x_set_offset (f, f->left_pos, f->top_pos, 0);
5383 f->output_data.mac->asked_for_visible = 1;
5385 ShowWindow (FRAME_MAC_WINDOW (f));
5388 XFlush (FRAME_MAC_DISPLAY (f));
5390 /* Synchronize to ensure Emacs knows the frame is visible
5391 before we do anything else. We do this loop with input not blocked
5392 so that incoming events are handled. */
5394 Lisp_Object frame;
5395 int count;
5397 /* This must come after we set COUNT. */
5398 UNBLOCK_INPUT;
5400 XSETFRAME (frame, f);
5402 /* Wait until the frame is visible. Process X events until a
5403 MapNotify event has been seen, or until we think we won't get a
5404 MapNotify at all.. */
5405 for (count = input_signal_count + 10;
5406 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5408 /* Force processing of queued events. */
5409 x_sync (f);
5411 /* Machines that do polling rather than SIGIO have been
5412 observed to go into a busy-wait here. So we'll fake an
5413 alarm signal to let the handler know that there's something
5414 to be read. We used to raise a real alarm, but it seems
5415 that the handler isn't always enabled here. This is
5416 probably a bug. */
5417 if (input_polling_used ())
5419 /* It could be confusing if a real alarm arrives while
5420 processing the fake one. Turn it off and let the
5421 handler reset it. */
5422 extern void poll_for_input_1 P_ ((void));
5423 int old_poll_suppress_count = poll_suppress_count;
5424 poll_suppress_count = 1;
5425 poll_for_input_1 ();
5426 poll_suppress_count = old_poll_suppress_count;
5429 /* See if a MapNotify event has been processed. */
5430 FRAME_SAMPLE_VISIBILITY (f);
5435 /* Change from mapped state to withdrawn state. */
5437 /* Make the frame visible (mapped and not iconified). */
5439 void
5440 x_make_frame_invisible (f)
5441 struct frame *f;
5443 /* Don't keep the highlight on an invisible frame. */
5444 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5445 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5447 BLOCK_INPUT;
5449 HideWindow (FRAME_MAC_WINDOW (f));
5451 /* We can't distinguish this from iconification
5452 just by the event that we get from the server.
5453 So we can't win using the usual strategy of letting
5454 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5455 and synchronize with the server to make sure we agree. */
5456 f->visible = 0;
5457 FRAME_ICONIFIED_P (f) = 0;
5458 f->async_visible = 0;
5459 f->async_iconified = 0;
5461 UNBLOCK_INPUT;
5464 /* Change window state from mapped to iconified. */
5466 void
5467 x_iconify_frame (f)
5468 struct frame *f;
5470 /* Don't keep the highlight on an invisible frame. */
5471 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5472 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5474 #if 0
5475 /* Review: Since window is still visible in dock, still allow updates? */
5476 if (f->async_iconified)
5477 return;
5478 #endif
5480 BLOCK_INPUT;
5482 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5484 UNBLOCK_INPUT;
5488 /* Free X resources of frame F. */
5490 void
5491 x_free_frame_resources (f)
5492 struct frame *f;
5494 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5495 WindowPtr wp = FRAME_MAC_WINDOW (f);
5497 BLOCK_INPUT;
5499 DisposeWindow (wp);
5500 if (wp == tip_window)
5501 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5502 closed' event. So we reset tip_window here. */
5503 tip_window = NULL;
5505 free_frame_menubar (f);
5507 if (FRAME_FACE_CACHE (f))
5508 free_frame_faces (f);
5510 x_free_gcs (f);
5512 xfree (f->output_data.mac);
5513 f->output_data.mac = NULL;
5515 if (f == dpyinfo->x_focus_frame)
5516 dpyinfo->x_focus_frame = 0;
5517 if (f == dpyinfo->x_focus_event_frame)
5518 dpyinfo->x_focus_event_frame = 0;
5519 if (f == dpyinfo->x_highlight_frame)
5520 dpyinfo->x_highlight_frame = 0;
5522 if (f == dpyinfo->mouse_face_mouse_frame)
5524 dpyinfo->mouse_face_beg_row
5525 = dpyinfo->mouse_face_beg_col = -1;
5526 dpyinfo->mouse_face_end_row
5527 = dpyinfo->mouse_face_end_col = -1;
5528 dpyinfo->mouse_face_window = Qnil;
5529 dpyinfo->mouse_face_deferred_gc = 0;
5530 dpyinfo->mouse_face_mouse_frame = 0;
5533 UNBLOCK_INPUT;
5537 /* Destroy the X window of frame F. */
5539 void
5540 x_destroy_window (f)
5541 struct frame *f;
5543 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5545 x_free_frame_resources (f);
5547 dpyinfo->reference_count--;
5551 /* Setting window manager hints. */
5553 /* Set the normal size hints for the window manager, for frame F.
5554 FLAGS is the flags word to use--or 0 meaning preserve the flags
5555 that the window now has.
5556 If USER_POSITION is nonzero, we set the USPosition
5557 flag (this is useful when FLAGS is 0). */
5558 void
5559 x_wm_set_size_hint (f, flags, user_position)
5560 struct frame *f;
5561 long flags;
5562 int user_position;
5564 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5565 XSizeHints size_hints;
5567 #ifdef USE_X_TOOLKIT
5568 Arg al[2];
5569 int ac = 0;
5570 Dimension widget_width, widget_height;
5571 Window window = XtWindow (f->output_data.x->widget);
5572 #else /* not USE_X_TOOLKIT */
5573 Window window = FRAME_X_WINDOW (f);
5574 #endif /* not USE_X_TOOLKIT */
5576 /* Setting PMaxSize caused various problems. */
5577 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5579 size_hints.x = f->left_pos;
5580 size_hints.y = f->top_pos;
5582 #ifdef USE_X_TOOLKIT
5583 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5584 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5585 XtGetValues (f->output_data.x->widget, al, ac);
5586 size_hints.height = widget_height;
5587 size_hints.width = widget_width;
5588 #else /* not USE_X_TOOLKIT */
5589 size_hints.height = FRAME_PIXEL_HEIGHT (f);
5590 size_hints.width = FRAME_PIXEL_WIDTH (f);
5591 #endif /* not USE_X_TOOLKIT */
5593 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
5594 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
5595 size_hints.max_width
5596 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5597 size_hints.max_height
5598 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5600 /* Calculate the base and minimum sizes.
5602 (When we use the X toolkit, we don't do it here.
5603 Instead we copy the values that the widgets are using, below.) */
5604 #ifndef USE_X_TOOLKIT
5606 int base_width, base_height;
5607 int min_rows = 0, min_cols = 0;
5609 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5610 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5612 check_frame_size (f, &min_rows, &min_cols);
5614 /* The window manager uses the base width hints to calculate the
5615 current number of rows and columns in the frame while
5616 resizing; min_width and min_height aren't useful for this
5617 purpose, since they might not give the dimensions for a
5618 zero-row, zero-column frame.
5620 We use the base_width and base_height members if we have
5621 them; otherwise, we set the min_width and min_height members
5622 to the size for a zero x zero frame. */
5624 #ifdef HAVE_X11R4
5625 size_hints.flags |= PBaseSize;
5626 size_hints.base_width = base_width;
5627 size_hints.base_height = base_height;
5628 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5629 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5630 #else
5631 size_hints.min_width = base_width;
5632 size_hints.min_height = base_height;
5633 #endif
5636 /* If we don't need the old flags, we don't need the old hint at all. */
5637 if (flags)
5639 size_hints.flags |= flags;
5640 goto no_read;
5642 #endif /* not USE_X_TOOLKIT */
5645 XSizeHints hints; /* Sometimes I hate X Windows... */
5646 long supplied_return;
5647 int value;
5649 #ifdef HAVE_X11R4
5650 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5651 &supplied_return);
5652 #else
5653 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5654 #endif
5656 #ifdef USE_X_TOOLKIT
5657 size_hints.base_height = hints.base_height;
5658 size_hints.base_width = hints.base_width;
5659 size_hints.min_height = hints.min_height;
5660 size_hints.min_width = hints.min_width;
5661 #endif
5663 if (flags)
5664 size_hints.flags |= flags;
5665 else
5667 if (value == 0)
5668 hints.flags = 0;
5669 if (hints.flags & PSize)
5670 size_hints.flags |= PSize;
5671 if (hints.flags & PPosition)
5672 size_hints.flags |= PPosition;
5673 if (hints.flags & USPosition)
5674 size_hints.flags |= USPosition;
5675 if (hints.flags & USSize)
5676 size_hints.flags |= USSize;
5680 #ifndef USE_X_TOOLKIT
5681 no_read:
5682 #endif
5684 #ifdef PWinGravity
5685 size_hints.win_gravity = f->win_gravity;
5686 size_hints.flags |= PWinGravity;
5688 if (user_position)
5690 size_hints.flags &= ~ PPosition;
5691 size_hints.flags |= USPosition;
5693 #endif /* PWinGravity */
5695 #ifdef HAVE_X11R4
5696 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5697 #else
5698 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5699 #endif
5700 #endif /* MAC_TODO */
5703 #if 0 /* MAC_TODO: hide application instead of iconify? */
5704 /* Used for IconicState or NormalState */
5706 void
5707 x_wm_set_window_state (f, state)
5708 struct frame *f;
5709 int state;
5711 #ifdef USE_X_TOOLKIT
5712 Arg al[1];
5714 XtSetArg (al[0], XtNinitialState, state);
5715 XtSetValues (f->output_data.x->widget, al, 1);
5716 #else /* not USE_X_TOOLKIT */
5717 Window window = FRAME_X_WINDOW (f);
5719 f->output_data.x->wm_hints.flags |= StateHint;
5720 f->output_data.x->wm_hints.initial_state = state;
5722 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5723 #endif /* not USE_X_TOOLKIT */
5726 void
5727 x_wm_set_icon_pixmap (f, pixmap_id)
5728 struct frame *f;
5729 int pixmap_id;
5731 Pixmap icon_pixmap;
5733 #ifndef USE_X_TOOLKIT
5734 Window window = FRAME_X_WINDOW (f);
5735 #endif
5737 if (pixmap_id > 0)
5739 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5740 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5742 else
5744 /* It seems there is no way to turn off use of an icon pixmap.
5745 The following line does it, only if no icon has yet been created,
5746 for some window managers. But with mwm it crashes.
5747 Some people say it should clear the IconPixmapHint bit in this case,
5748 but that doesn't work, and the X consortium said it isn't the
5749 right thing at all. Since there is no way to win,
5750 best to explicitly give up. */
5751 #if 0
5752 f->output_data.x->wm_hints.icon_pixmap = None;
5753 #else
5754 return;
5755 #endif
5758 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5761 Arg al[1];
5762 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5763 XtSetValues (f->output_data.x->widget, al, 1);
5766 #else /* not USE_X_TOOLKIT */
5768 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5769 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5771 #endif /* not USE_X_TOOLKIT */
5774 #endif /* MAC_TODO */
5776 void
5777 x_wm_set_icon_position (f, icon_x, icon_y)
5778 struct frame *f;
5779 int icon_x, icon_y;
5781 #if 0 /* MAC_TODO: no icons on Mac */
5782 #ifdef USE_X_TOOLKIT
5783 Window window = XtWindow (f->output_data.x->widget);
5784 #else
5785 Window window = FRAME_X_WINDOW (f);
5786 #endif
5788 f->output_data.x->wm_hints.flags |= IconPositionHint;
5789 f->output_data.x->wm_hints.icon_x = icon_x;
5790 f->output_data.x->wm_hints.icon_y = icon_y;
5792 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5793 #endif /* MAC_TODO */
5797 /***********************************************************************
5798 Fonts
5799 ***********************************************************************/
5801 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5803 struct font_info *
5804 x_get_font_info (f, font_idx)
5805 FRAME_PTR f;
5806 int font_idx;
5808 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5811 /* the global font name table */
5812 char **font_name_table = NULL;
5813 int font_name_table_size = 0;
5814 int font_name_count = 0;
5816 #if 0
5817 /* compare two strings ignoring case */
5818 static int
5819 stricmp (const char *s, const char *t)
5821 for ( ; tolower (*s) == tolower (*t); s++, t++)
5822 if (*s == '\0')
5823 return 0;
5824 return tolower (*s) - tolower (*t);
5827 /* compare two strings ignoring case and handling wildcard */
5828 static int
5829 wildstrieq (char *s1, char *s2)
5831 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5832 return true;
5834 return stricmp (s1, s2) == 0;
5837 /* Assume parameter 1 is fully qualified, no wildcards. */
5838 static int
5839 mac_font_pattern_match (fontname, pattern)
5840 char * fontname;
5841 char * pattern;
5843 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5844 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5845 char *ptr;
5847 /* Copy fontname so we can modify it during comparison. */
5848 strcpy (font_name_copy, fontname);
5850 ptr = regex;
5851 *ptr++ = '^';
5853 /* Turn pattern into a regexp and do a regexp match. */
5854 for (; *pattern; pattern++)
5856 if (*pattern == '?')
5857 *ptr++ = '.';
5858 else if (*pattern == '*')
5860 *ptr++ = '.';
5861 *ptr++ = '*';
5863 else
5864 *ptr++ = *pattern;
5866 *ptr = '$';
5867 *(ptr + 1) = '\0';
5869 return (fast_c_string_match_ignore_case (build_string (regex),
5870 font_name_copy) >= 0);
5873 /* Two font specs are considered to match if their foundry, family,
5874 weight, slant, and charset match. */
5875 static int
5876 mac_font_match (char *mf, char *xf)
5878 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5879 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5881 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5882 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5883 return mac_font_pattern_match (mf, xf);
5885 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5886 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5887 return mac_font_pattern_match (mf, xf);
5889 return (wildstrieq (m_foundry, x_foundry)
5890 && wildstrieq (m_family, x_family)
5891 && wildstrieq (m_weight, x_weight)
5892 && wildstrieq (m_slant, x_slant)
5893 && wildstrieq (m_charset, x_charset))
5894 || mac_font_pattern_match (mf, xf);
5896 #endif
5898 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5900 static void
5901 decode_mac_font_name (char *name, int size, short scriptcode)
5903 Lisp_Object coding_system;
5904 struct coding_system coding;
5905 char *buf;
5907 switch (scriptcode)
5909 case smTradChinese:
5910 coding_system = Qbig5;
5911 break;
5912 case smSimpChinese:
5913 coding_system = Qcn_gb;
5914 break;
5915 case smJapanese:
5916 coding_system = Qsjis;
5917 break;
5918 case smKorean:
5919 coding_system = Qeuc_kr;
5920 break;
5921 default:
5922 return;
5925 setup_coding_system (coding_system, &coding);
5926 coding.src_multibyte = 0;
5927 coding.dst_multibyte = 1;
5928 coding.mode |= CODING_MODE_LAST_BLOCK;
5929 coding.composing = COMPOSITION_DISABLED;
5930 buf = (char *) alloca (size);
5932 decode_coding (&coding, name, buf, strlen (name), size - 1);
5933 bcopy (buf, name, coding.produced);
5934 name[coding.produced] = '\0';
5938 static char *
5939 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
5941 char foundry[32], family[32], cs[32];
5942 char xf[256], *result, *p;
5944 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5946 strcpy(foundry, "Apple");
5947 strcpy(family, name);
5949 switch (scriptcode)
5951 case smTradChinese:
5952 strcpy(cs, "big5-0");
5953 break;
5954 case smSimpChinese:
5955 strcpy(cs, "gb2312.1980-0");
5956 break;
5957 case smJapanese:
5958 strcpy(cs, "jisx0208.1983-sjis");
5959 break;
5960 case -smJapanese:
5961 /* Each Apple Japanese font is entered into the font table
5962 twice: once as a jisx0208.1983-sjis font and once as a
5963 jisx0201.1976-0 font. The latter can be used to display
5964 the ascii charset and katakana-jisx0201 charset. A
5965 negative script code signals that the name of this latter
5966 font is being built. */
5967 strcpy(cs, "jisx0201.1976-0");
5968 break;
5969 case smKorean:
5970 strcpy(cs, "ksc5601.1989-0");
5971 break;
5972 default:
5973 strcpy(cs, "mac-roman");
5974 break;
5978 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5979 foundry, family, style & bold ? "bold" : "medium",
5980 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5982 result = (char *) xmalloc (strlen (xf) + 1);
5983 strcpy (result, xf);
5984 for (p = result; *p; p++)
5985 *p = tolower(*p);
5986 return result;
5990 /* Convert an X font spec to the corresponding mac font name, which
5991 can then be passed to GetFNum after conversion to a Pascal string.
5992 For ordinary Mac fonts, this should just be their names, like
5993 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5994 collection contain their charset designation in their names, like
5995 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5996 names are handled accordingly. */
5997 static void
5998 x_font_name_to_mac_font_name (char *xf, char *mf)
6000 char foundry[32], family[32], weight[20], slant[2], cs[32];
6001 Lisp_Object coding_system = Qnil;
6002 struct coding_system coding;
6004 strcpy (mf, "");
6006 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6007 foundry, family, weight, slant, cs) != 5 &&
6008 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6009 foundry, family, weight, slant, cs) != 5)
6010 return;
6012 if (strcmp (cs, "big5-0") == 0)
6013 coding_system = Qbig5;
6014 else if (strcmp (cs, "gb2312.1980-0") == 0)
6015 coding_system = Qcn_gb;
6016 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
6017 || strcmp (cs, "jisx0201.1976-0") == 0)
6018 coding_system = Qsjis;
6019 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6020 coding_system = Qeuc_kr;
6021 else if (strcmp (cs, "mac-roman") == 0)
6022 strcpy (mf, family);
6023 else
6024 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6026 if (!NILP (coding_system))
6028 setup_coding_system (coding_system, &coding);
6029 coding.src_multibyte = 1;
6030 coding.dst_multibyte = 1;
6031 coding.mode |= CODING_MODE_LAST_BLOCK;
6032 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6033 mf[coding.produced] = '\0';
6038 static void
6039 add_font_name_table_entry (char *font_name)
6041 if (font_name_table_size == 0)
6043 font_name_table_size = 16;
6044 font_name_table = (char **)
6045 xmalloc (font_name_table_size * sizeof (char *));
6047 else if (font_name_count + 1 >= font_name_table_size)
6049 font_name_table_size += 16;
6050 font_name_table = (char **)
6051 xrealloc (font_name_table,
6052 font_name_table_size * sizeof (char *));
6055 font_name_table[font_name_count++] = font_name;
6058 /* Sets up the table font_name_table to contain the list of all fonts
6059 in the system the first time the table is used so that the Resource
6060 Manager need not be accessed every time this information is
6061 needed. */
6063 static void
6064 init_font_name_table ()
6066 #if TARGET_API_MAC_CARBON
6067 SInt32 sv;
6069 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6071 FMFontFamilyIterator ffi;
6072 FMFontFamilyInstanceIterator ffii;
6073 FMFontFamily ff;
6075 /* Create a dummy instance iterator here to avoid creating and
6076 destroying it in the loop. */
6077 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6078 return;
6079 /* Create an iterator to enumerate the font families. */
6080 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6081 != noErr)
6083 FMDisposeFontFamilyInstanceIterator (&ffii);
6084 return;
6087 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6089 Str255 name;
6090 FMFont font;
6091 FMFontStyle style;
6092 FMFontSize size;
6093 SInt16 sc;
6095 if (FMGetFontFamilyName (ff, name) != noErr)
6096 break;
6097 p2cstr (name);
6098 if (*name == '.')
6099 continue;
6101 sc = FontToScript (ff);
6102 decode_mac_font_name (name, sizeof (name), sc);
6104 /* Point the instance iterator at the current font family. */
6105 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6106 break;
6108 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6109 == noErr)
6111 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6112 contained in Apple Japanese (SJIS) font. */
6113 again:
6114 if (size == 0)
6116 add_font_name_table_entry (mac_to_x_fontname (name, size,
6117 style, sc));
6118 add_font_name_table_entry (mac_to_x_fontname (name, size,
6119 italic, sc));
6120 add_font_name_table_entry (mac_to_x_fontname (name, size,
6121 bold, sc));
6122 add_font_name_table_entry (mac_to_x_fontname (name, size,
6123 italic | bold,
6124 sc));
6126 else
6127 add_font_name_table_entry (mac_to_x_fontname (name, size,
6128 style, sc));
6129 if (sc == smJapanese)
6131 sc = -smJapanese;
6132 goto again;
6134 else if (sc == -smJapanese)
6135 sc = smJapanese;
6139 /* Dispose of the iterators. */
6140 FMDisposeFontFamilyIterator (&ffi);
6141 FMDisposeFontFamilyInstanceIterator (&ffii);
6143 else
6145 #endif /* TARGET_API_MAC_CARBON */
6146 GrafPtr port;
6147 SInt16 fontnum, old_fontnum;
6148 int num_mac_fonts = CountResources('FOND');
6149 int i, j;
6150 Handle font_handle, font_handle_2;
6151 short id, scriptcode;
6152 ResType type;
6153 Str32 name;
6154 struct FontAssoc *fat;
6155 struct AsscEntry *assc_entry;
6157 GetPort (&port); /* save the current font number used */
6158 #if TARGET_API_MAC_CARBON
6159 old_fontnum = GetPortTextFont (port);
6160 #else
6161 old_fontnum = port->txFont;
6162 #endif
6164 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6166 font_handle = GetIndResource ('FOND', i);
6167 if (!font_handle)
6168 continue;
6170 GetResInfo (font_handle, &id, &type, name);
6171 GetFNum (name, &fontnum);
6172 p2cstr (name);
6173 if (fontnum == 0)
6174 continue;
6176 TextFont (fontnum);
6177 scriptcode = FontToScript (fontnum);
6178 decode_mac_font_name (name, sizeof (name), scriptcode);
6181 HLock (font_handle);
6183 if (GetResourceSizeOnDisk (font_handle)
6184 >= sizeof (struct FamRec))
6186 fat = (struct FontAssoc *) (*font_handle
6187 + sizeof (struct FamRec));
6188 assc_entry
6189 = (struct AsscEntry *) (*font_handle
6190 + sizeof (struct FamRec)
6191 + sizeof (struct FontAssoc));
6193 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6195 if (font_name_table_size == 0)
6197 font_name_table_size = 16;
6198 font_name_table = (char **)
6199 xmalloc (font_name_table_size * sizeof (char *));
6201 else if (font_name_count >= font_name_table_size)
6203 font_name_table_size += 16;
6204 font_name_table = (char **)
6205 xrealloc (font_name_table,
6206 font_name_table_size * sizeof (char *));
6208 font_name_table[font_name_count++]
6209 = mac_to_x_fontname (name,
6210 assc_entry->fontSize,
6211 assc_entry->fontStyle,
6212 scriptcode);
6213 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6214 parts are contained in Apple Japanese (SJIS)
6215 font. */
6216 if (smJapanese == scriptcode)
6218 font_name_table[font_name_count++]
6219 = mac_to_x_fontname (name,
6220 assc_entry->fontSize,
6221 assc_entry->fontStyle,
6222 -smJapanese);
6227 HUnlock (font_handle);
6228 font_handle_2 = GetNextFOND (font_handle);
6229 ReleaseResource (font_handle);
6230 font_handle = font_handle_2;
6232 while (ResError () == noErr && font_handle);
6235 TextFont (old_fontnum);
6236 #if TARGET_API_MAC_CARBON
6238 #endif /* TARGET_API_MAC_CARBON */
6242 enum xlfd_scalable_field_index
6244 XLFD_SCL_PIXEL_SIZE,
6245 XLFD_SCL_POINT_SIZE,
6246 XLFD_SCL_AVGWIDTH,
6247 XLFD_SCL_LAST
6250 static int xlfd_scalable_fields[] =
6252 6, /* PIXEL_SIZE */
6253 7, /* POINT_SIZE */
6254 11, /* AVGWIDTH */
6258 static Lisp_Object
6259 mac_do_list_fonts (pattern, maxnames)
6260 char *pattern;
6261 int maxnames;
6263 int i, n_fonts = 0;
6264 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6265 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6266 char scaled[256];
6267 char *ptr;
6268 int scl_val[XLFD_SCL_LAST], *field, *val;
6270 for (i = 0; i < XLFD_SCL_LAST; i++)
6271 scl_val[i] = -1;
6273 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6274 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6275 fonts are scaled according to the specified size. */
6276 ptr = pattern;
6277 i = 0;
6278 field = xlfd_scalable_fields;
6279 val = scl_val;
6280 if (*ptr == '-')
6283 ptr++;
6284 if (i == *field)
6286 if ('1' <= *ptr && *ptr <= '9')
6288 *val = *ptr++ - '0';
6289 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6290 *val = *val * 10 + *ptr++ - '0';
6291 if (*ptr != '-')
6292 *val = -1;
6294 field++;
6295 val++;
6297 ptr = strchr (ptr, '-');
6298 i++;
6300 while (ptr && i < 14);
6302 if (i == 14 && ptr == NULL)
6304 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6306 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6307 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6309 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6311 scl_val[XLFD_SCL_POINT_SIZE] =
6312 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6314 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6316 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6317 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6320 else
6321 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6323 ptr = regex;
6324 *ptr++ = '^';
6326 /* Turn pattern into a regexp and do a regexp match. */
6327 for (; *pattern; pattern++)
6329 if (*pattern == '?')
6330 *ptr++ = '.';
6331 else if (*pattern == '*')
6333 *ptr++ = '.';
6334 *ptr++ = '*';
6336 else
6337 *ptr++ = tolower (*pattern);
6339 *ptr = '$';
6340 *(ptr + 1) = '\0';
6342 pattern_regex = build_string (regex);
6344 for (i = 0; i < font_name_count; i++)
6346 fontname = build_string (font_name_table[i]);
6347 if (fast_string_match (pattern_regex, fontname) >= 0)
6349 font_list = Fcons (fontname, font_list);
6351 n_fonts++;
6352 if (maxnames > 0 && n_fonts >= maxnames)
6353 break;
6355 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6356 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6358 int former_len = ptr - font_name_table[i];
6360 memcpy (scaled, font_name_table[i], former_len);
6361 sprintf (scaled + former_len,
6362 "-%d-%d-75-75-m-%d-%s",
6363 scl_val[XLFD_SCL_PIXEL_SIZE],
6364 scl_val[XLFD_SCL_POINT_SIZE],
6365 scl_val[XLFD_SCL_AVGWIDTH],
6366 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6367 fontname = build_string (scaled);
6368 if (fast_string_match (pattern_regex, fontname) >= 0)
6370 font_list = Fcons (fontname, font_list);
6372 n_fonts++;
6373 if (maxnames > 0 && n_fonts >= maxnames)
6374 break;
6378 return font_list;
6381 /* Return a list of at most MAXNAMES font specs matching the one in
6382 PATTERN. Cache matching fonts for patterns in
6383 dpyinfo->name_list_element to avoid looking them up again by
6384 calling mac_font_pattern_match (slow). Return as many matching
6385 fonts as possible if MAXNAMES = -1. */
6387 Lisp_Object
6388 x_list_fonts (struct frame *f,
6389 Lisp_Object pattern,
6390 int size,
6391 int maxnames)
6393 Lisp_Object newlist = Qnil, tem, key;
6394 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6396 if (font_name_table == NULL) /* Initialize when first used. */
6397 init_font_name_table ();
6399 if (dpyinfo)
6401 tem = XCDR (dpyinfo->name_list_element);
6402 key = Fcons (pattern, make_number (maxnames));
6404 newlist = Fassoc (key, tem);
6405 if (!NILP (newlist))
6407 newlist = Fcdr_safe (newlist);
6408 goto label_cached;
6412 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6414 /* MAC_TODO: add code for matching outline fonts here */
6416 if (dpyinfo)
6418 XSETCDR (dpyinfo->name_list_element,
6419 Fcons (Fcons (key, newlist),
6420 XCDR (dpyinfo->name_list_element)));
6422 label_cached:
6424 return newlist;
6428 #if GLYPH_DEBUG
6430 /* Check that FONT is valid on frame F. It is if it can be found in F's
6431 font table. */
6433 static void
6434 x_check_font (f, font)
6435 struct frame *f;
6436 XFontStruct *font;
6438 int i;
6439 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6441 xassert (font != NULL);
6443 for (i = 0; i < dpyinfo->n_fonts; i++)
6444 if (dpyinfo->font_table[i].name
6445 && font == dpyinfo->font_table[i].font)
6446 break;
6448 xassert (i < dpyinfo->n_fonts);
6451 #endif /* GLYPH_DEBUG != 0 */
6453 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6454 Note: There are (broken) X fonts out there with invalid XFontStruct
6455 min_bounds contents. For example, handa@etl.go.jp reports that
6456 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6457 have font->min_bounds.width == 0. */
6459 static INLINE void
6460 x_font_min_bounds (font, w, h)
6461 MacFontStruct *font;
6462 int *w, *h;
6465 * TODO: Windows does not appear to offer min bound, only
6466 * average and maximum width, and maximum height.
6468 *h = FONT_HEIGHT (font);
6469 *w = FONT_WIDTH (font);
6473 /* Compute the smallest character width and smallest font height over
6474 all fonts available on frame F. Set the members smallest_char_width
6475 and smallest_font_height in F's x_display_info structure to
6476 the values computed. Value is non-zero if smallest_font_height or
6477 smallest_char_width become smaller than they were before. */
6480 x_compute_min_glyph_bounds (f)
6481 struct frame *f;
6483 int i;
6484 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6485 MacFontStruct *font;
6486 int old_width = dpyinfo->smallest_char_width;
6487 int old_height = dpyinfo->smallest_font_height;
6489 dpyinfo->smallest_font_height = 100000;
6490 dpyinfo->smallest_char_width = 100000;
6492 for (i = 0; i < dpyinfo->n_fonts; ++i)
6493 if (dpyinfo->font_table[i].name)
6495 struct font_info *fontp = dpyinfo->font_table + i;
6496 int w, h;
6498 font = (MacFontStruct *) fontp->font;
6499 xassert (font != (MacFontStruct *) ~0);
6500 x_font_min_bounds (font, &w, &h);
6502 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6503 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6506 xassert (dpyinfo->smallest_char_width > 0
6507 && dpyinfo->smallest_font_height > 0);
6509 return (dpyinfo->n_fonts == 1
6510 || dpyinfo->smallest_char_width < old_width
6511 || dpyinfo->smallest_font_height < old_height);
6515 /* Determine whether given string is a fully-specified XLFD: all 14
6516 fields are present, none is '*'. */
6518 static int
6519 is_fully_specified_xlfd (char *p)
6521 int i;
6522 char *q;
6524 if (*p != '-')
6525 return 0;
6527 for (i = 0; i < 13; i++)
6529 q = strchr (p + 1, '-');
6530 if (q == NULL)
6531 return 0;
6532 if (q - p == 2 && *(p + 1) == '*')
6533 return 0;
6534 p = q;
6537 if (strchr (p + 1, '-') != NULL)
6538 return 0;
6540 if (*(p + 1) == '*' && *(p + 2) == '\0')
6541 return 0;
6543 return 1;
6547 const int kDefaultFontSize = 9;
6550 /* XLoadQueryFont creates and returns an internal representation for a
6551 font in a MacFontStruct struct. There is really no concept
6552 corresponding to "loading" a font on the Mac. But we check its
6553 existence and find the font number and all other information for it
6554 and store them in the returned MacFontStruct. */
6556 static MacFontStruct *
6557 XLoadQueryFont (Display *dpy, char *fontname)
6559 int i, size, is_two_byte_font, char_width;
6560 char *name;
6561 GrafPtr port;
6562 SInt16 old_fontnum, old_fontsize;
6563 Style old_fontface;
6564 Str32 mfontname;
6565 SInt16 fontnum;
6566 Style fontface = normal;
6567 MacFontStruct *font;
6568 FontInfo the_fontinfo;
6569 char s_weight[7], c_slant;
6571 if (is_fully_specified_xlfd (fontname))
6572 name = fontname;
6573 else
6575 Lisp_Object matched_fonts;
6577 matched_fonts = mac_do_list_fonts (fontname, 1);
6578 if (NILP (matched_fonts))
6579 return NULL;
6580 name = SDATA (XCAR (matched_fonts));
6583 GetPort (&port); /* save the current font number used */
6584 #if TARGET_API_MAC_CARBON
6585 old_fontnum = GetPortTextFont (port);
6586 old_fontsize = GetPortTextSize (port);
6587 old_fontface = GetPortTextFace (port);
6588 #else
6589 old_fontnum = port->txFont;
6590 old_fontsize = port->txSize;
6591 old_fontface = port->txFace;
6592 #endif
6594 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6595 size = kDefaultFontSize;
6597 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6598 if (strcmp (s_weight, "bold") == 0)
6599 fontface |= bold;
6601 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6602 if (c_slant == 'i')
6603 fontface |= italic;
6605 x_font_name_to_mac_font_name (name, mfontname);
6606 c2pstr (mfontname);
6607 GetFNum (mfontname, &fontnum);
6608 if (fontnum == 0)
6609 return NULL;
6611 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6613 font->fontname = (char *) xmalloc (strlen (name) + 1);
6614 bcopy (name, font->fontname, strlen (name) + 1);
6616 font->mac_fontnum = fontnum;
6617 font->mac_fontsize = size;
6618 font->mac_fontface = fontface;
6619 font->mac_scriptcode = FontToScript (fontnum);
6621 /* Apple Japanese (SJIS) font is listed as both
6622 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6623 (Roman script) in init_font_name_table (). The latter should be
6624 treated as a one-byte font. */
6626 char cs[32];
6628 if (sscanf (name,
6629 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6630 cs) == 1
6631 && 0 == strcmp (cs, "jisx0201.1976-0"))
6632 font->mac_scriptcode = smRoman;
6635 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6636 font->mac_scriptcode == smTradChinese ||
6637 font->mac_scriptcode == smSimpChinese ||
6638 font->mac_scriptcode == smKorean;
6640 TextFont (fontnum);
6641 TextSize (size);
6642 TextFace (fontface);
6644 GetFontInfo (&the_fontinfo);
6646 font->ascent = the_fontinfo.ascent;
6647 font->descent = the_fontinfo.descent;
6649 font->min_byte1 = 0;
6650 if (is_two_byte_font)
6651 font->max_byte1 = 1;
6652 else
6653 font->max_byte1 = 0;
6654 font->min_char_or_byte2 = 0x20;
6655 font->max_char_or_byte2 = 0xff;
6657 if (is_two_byte_font)
6659 /* Use the width of an "ideographic space" of that font because
6660 the_fontinfo.widMax returns the wrong width for some fonts. */
6661 switch (font->mac_scriptcode)
6663 case smJapanese:
6664 char_width = StringWidth("\p\x81\x40");
6665 break;
6666 case smTradChinese:
6667 char_width = StringWidth("\p\xa1\x40");
6668 break;
6669 case smSimpChinese:
6670 char_width = StringWidth("\p\xa1\xa1");
6671 break;
6672 case smKorean:
6673 char_width = StringWidth("\p\xa1\xa1");
6674 break;
6677 else
6678 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6679 returns 15 for 12-point Monaco! */
6680 char_width = CharWidth ('m');
6682 font->max_bounds.rbearing = char_width;
6683 font->max_bounds.lbearing = 0;
6684 font->max_bounds.width = char_width;
6685 font->max_bounds.ascent = the_fontinfo.ascent;
6686 font->max_bounds.descent = the_fontinfo.descent;
6688 font->min_bounds = font->max_bounds;
6690 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6691 font->per_char = NULL;
6692 else
6694 font->per_char = (XCharStruct *)
6695 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6697 int c;
6699 for (c = 0x20; c <= 0xff; c++)
6701 font->per_char[c - 0x20] = font->max_bounds;
6702 font->per_char[c - 0x20].width =
6703 font->per_char[c - 0x20].rbearing = CharWidth (c);
6708 TextFont (old_fontnum); /* restore previous font number, size and face */
6709 TextSize (old_fontsize);
6710 TextFace (old_fontface);
6712 return font;
6716 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6717 pointer to the structure font_info while allocating it dynamically.
6718 If SIZE is 0, load any size of font.
6719 If loading is failed, return NULL. */
6721 struct font_info *
6722 x_load_font (f, fontname, size)
6723 struct frame *f;
6724 register char *fontname;
6725 int size;
6727 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6728 Lisp_Object font_names;
6730 /* Get a list of all the fonts that match this name. Once we
6731 have a list of matching fonts, we compare them against the fonts
6732 we already have by comparing names. */
6733 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6735 if (!NILP (font_names))
6737 Lisp_Object tail;
6738 int i;
6740 for (i = 0; i < dpyinfo->n_fonts; i++)
6741 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6742 if (dpyinfo->font_table[i].name
6743 && (!strcmp (dpyinfo->font_table[i].name,
6744 SDATA (XCAR (tail)))
6745 || !strcmp (dpyinfo->font_table[i].full_name,
6746 SDATA (XCAR (tail)))))
6747 return (dpyinfo->font_table + i);
6750 /* Load the font and add it to the table. */
6752 char *full_name;
6753 struct MacFontStruct *font;
6754 struct font_info *fontp;
6755 unsigned long value;
6756 int i;
6758 /* If we have found fonts by x_list_font, load one of them. If
6759 not, we still try to load a font by the name given as FONTNAME
6760 because XListFonts (called in x_list_font) of some X server has
6761 a bug of not finding a font even if the font surely exists and
6762 is loadable by XLoadQueryFont. */
6763 if (size > 0 && !NILP (font_names))
6764 fontname = (char *) SDATA (XCAR (font_names));
6766 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6767 if (!font)
6768 return NULL;
6770 /* Find a free slot in the font table. */
6771 for (i = 0; i < dpyinfo->n_fonts; ++i)
6772 if (dpyinfo->font_table[i].name == NULL)
6773 break;
6775 /* If no free slot found, maybe enlarge the font table. */
6776 if (i == dpyinfo->n_fonts
6777 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6779 int sz;
6780 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6781 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6782 dpyinfo->font_table
6783 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6786 fontp = dpyinfo->font_table + i;
6787 if (i == dpyinfo->n_fonts)
6788 ++dpyinfo->n_fonts;
6790 /* Now fill in the slots of *FONTP. */
6791 BLOCK_INPUT;
6792 bzero (fontp, sizeof (*fontp));
6793 fontp->font = font;
6794 fontp->font_idx = i;
6795 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6796 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6798 fontp->full_name = fontp->name;
6800 fontp->size = font->max_bounds.width;
6801 fontp->height = FONT_HEIGHT (font);
6803 /* For some font, ascent and descent in max_bounds field is
6804 larger than the above value. */
6805 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6806 if (max_height > fontp->height)
6807 fontp->height = max_height;
6810 /* The slot `encoding' specifies how to map a character
6811 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6812 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6813 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6814 2:0xA020..0xFF7F). For the moment, we don't know which charset
6815 uses this font. So, we set information in fontp->encoding[1]
6816 which is never used by any charset. If mapping can't be
6817 decided, set FONT_ENCODING_NOT_DECIDED. */
6818 if (font->mac_scriptcode == smJapanese)
6819 fontp->encoding[1] = 4;
6820 else
6822 fontp->encoding[1]
6823 = (font->max_byte1 == 0
6824 /* 1-byte font */
6825 ? (font->min_char_or_byte2 < 0x80
6826 ? (font->max_char_or_byte2 < 0x80
6827 ? 0 /* 0x20..0x7F */
6828 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6829 : 1) /* 0xA0..0xFF */
6830 /* 2-byte font */
6831 : (font->min_byte1 < 0x80
6832 ? (font->max_byte1 < 0x80
6833 ? (font->min_char_or_byte2 < 0x80
6834 ? (font->max_char_or_byte2 < 0x80
6835 ? 0 /* 0x2020..0x7F7F */
6836 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6837 : 3) /* 0x20A0..0x7FFF */
6838 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6839 : (font->min_char_or_byte2 < 0x80
6840 ? (font->max_char_or_byte2 < 0x80
6841 ? 2 /* 0xA020..0xFF7F */
6842 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6843 : 1))); /* 0xA0A0..0xFFFF */
6846 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6847 fontp->baseline_offset
6848 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6849 ? (long) value : 0);
6850 fontp->relative_compose
6851 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6852 ? (long) value : 0);
6853 fontp->default_ascent
6854 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6855 ? (long) value : 0);
6856 #else
6857 fontp->baseline_offset = 0;
6858 fontp->relative_compose = 0;
6859 fontp->default_ascent = 0;
6860 #endif
6862 /* Set global flag fonts_changed_p to non-zero if the font loaded
6863 has a character with a smaller width than any other character
6864 before, or if the font loaded has a smalle>r height than any
6865 other font loaded before. If this happens, it will make a
6866 glyph matrix reallocation necessary. */
6867 fonts_changed_p = x_compute_min_glyph_bounds (f);
6868 UNBLOCK_INPUT;
6869 return fontp;
6874 /* Return a pointer to struct font_info of a font named FONTNAME for
6875 frame F. If no such font is loaded, return NULL. */
6877 struct font_info *
6878 x_query_font (f, fontname)
6879 struct frame *f;
6880 register char *fontname;
6882 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6883 int i;
6885 for (i = 0; i < dpyinfo->n_fonts; i++)
6886 if (dpyinfo->font_table[i].name
6887 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6888 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6889 return (dpyinfo->font_table + i);
6890 return NULL;
6894 /* Find a CCL program for a font specified by FONTP, and set the member
6895 `encoder' of the structure. */
6897 void
6898 x_find_ccl_program (fontp)
6899 struct font_info *fontp;
6901 Lisp_Object list, elt;
6903 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6905 elt = XCAR (list);
6906 if (CONSP (elt)
6907 && STRINGP (XCAR (elt))
6908 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6909 >= 0))
6910 break;
6912 if (! NILP (list))
6914 struct ccl_program *ccl
6915 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6917 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6918 xfree (ccl);
6919 else
6920 fontp->font_encoder = ccl;
6926 /* The Mac Event loop code */
6928 #ifndef MAC_OSX
6929 #include <Events.h>
6930 #include <Quickdraw.h>
6931 #include <Balloons.h>
6932 #include <Devices.h>
6933 #include <Fonts.h>
6934 #include <Gestalt.h>
6935 #include <Menus.h>
6936 #include <Processes.h>
6937 #include <Sound.h>
6938 #include <ToolUtils.h>
6939 #include <TextUtils.h>
6940 #include <Dialogs.h>
6941 #include <Script.h>
6942 #include <Types.h>
6943 #include <TextEncodingConverter.h>
6944 #include <Resources.h>
6946 #if __MWERKS__
6947 #include <unix.h>
6948 #endif
6949 #endif /* ! MAC_OSX */
6951 #define M_APPLE 128
6952 #define I_ABOUT 1
6954 #define WINDOW_RESOURCE 128
6955 #define TERM_WINDOW_RESOURCE 129
6957 #define DEFAULT_NUM_COLS 80
6959 #define MIN_DOC_SIZE 64
6960 #define MAX_DOC_SIZE 32767
6962 /* sleep time for WaitNextEvent */
6963 #define WNE_SLEEP_AT_SUSPEND 10
6964 #define WNE_SLEEP_AT_RESUME 1
6966 /* true when cannot handle any Mac OS events */
6967 static int handling_window_update = 0;
6969 #if 0
6970 /* the flag appl_is_suspended is used both for determining the sleep
6971 time to be passed to WaitNextEvent and whether the cursor should be
6972 drawn when updating the display. The cursor is turned off when
6973 Emacs is suspended. Redrawing it is unnecessary and what needs to
6974 be done depends on whether the cursor lies inside or outside the
6975 redraw region. So we might as well skip drawing it when Emacs is
6976 suspended. */
6977 static Boolean app_is_suspended = false;
6978 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
6979 #endif
6981 #define EXTRA_STACK_ALLOC (256 * 1024)
6983 #define ARGV_STRING_LIST_ID 129
6984 #define ABOUT_ALERT_ID 128
6985 #define RAM_TOO_LARGE_ALERT_ID 129
6987 Boolean terminate_flag = false;
6989 /* Contains the string "reverse", which is a constant for mouse button emu.*/
6990 Lisp_Object Qreverse;
6992 /* True if using command key as meta key. */
6993 Lisp_Object Vmac_command_key_is_meta;
6995 /* Modifier associated with the option key, or nil for normal behavior. */
6996 Lisp_Object Vmac_option_modifier;
6998 /* True if the ctrl and meta keys should be reversed. */
6999 Lisp_Object Vmac_reverse_ctrl_meta;
7001 /* True if the option and command modifiers should be used to emulate
7002 a three button mouse */
7003 Lisp_Object Vmac_emulate_three_button_mouse;
7005 #if USE_CARBON_EVENTS
7006 /* True if the mouse wheel button (i.e. button 4) should map to
7007 mouse-2, instead of mouse-3. */
7008 Lisp_Object Vmac_wheel_button_is_mouse_2;
7010 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7011 for processing before Emacs sees it. */
7012 Lisp_Object Vmac_pass_command_to_system;
7014 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7015 for processing before Emacs sees it. */
7016 Lisp_Object Vmac_pass_control_to_system;
7017 #endif
7019 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7020 to this text encoding */
7021 int mac_keyboard_text_encoding;
7022 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7024 /* Set in term/mac-win.el to indicate that event loop can now generate
7025 drag and drop events. */
7026 Lisp_Object Qmac_ready_for_drag_n_drop;
7028 Lisp_Object drag_and_drop_file_list;
7030 Point saved_menu_event_location;
7032 #if !TARGET_API_MAC_CARBON
7033 /* Place holder for the default arrow cursor. */
7034 CursPtr arrow_cursor;
7035 #endif
7037 /* Apple Events */
7038 static void init_required_apple_events (void);
7039 static pascal OSErr
7040 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7041 static pascal OSErr
7042 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7043 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7044 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7046 /* Drag and Drop */
7047 static OSErr init_mac_drag_n_drop ();
7048 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7050 #if USE_CARBON_EVENTS
7051 /* Preliminary Support for the OSX Services Menu */
7052 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7053 static void init_service_handler ();
7054 #endif
7056 extern void init_emacs_passwd_dir ();
7057 extern int emacs_main (int, char **, char **);
7058 extern void check_alarm ();
7060 extern void initialize_applescript();
7061 extern void terminate_applescript();
7063 static unsigned int
7064 #if USE_CARBON_EVENTS
7065 mac_to_emacs_modifiers (UInt32 mods)
7066 #else
7067 mac_to_emacs_modifiers (EventModifiers mods)
7068 #endif
7070 unsigned int result = 0;
7071 if (mods & macShiftKey)
7072 result |= shift_modifier;
7073 if (mods & macCtrlKey)
7074 result |= ctrl_modifier;
7075 if (mods & macMetaKey)
7076 result |= meta_modifier;
7077 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7078 result |= alt_modifier;
7079 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7080 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7081 if (!NILP(val))
7082 result |= XUINT(val);
7085 return result;
7088 static int
7089 mac_get_emulated_btn ( UInt32 modifiers )
7091 int result = 0;
7092 if (!NILP (Vmac_emulate_three_button_mouse)) {
7093 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7094 if (modifiers & cmdKey)
7095 result = cmdIs3 ? 2 : 1;
7096 else if (modifiers & optionKey)
7097 result = cmdIs3 ? 1 : 2;
7099 return result;
7102 #if USE_CARBON_EVENTS
7103 /* Obtains the event modifiers from the event ref and then calls
7104 mac_to_emacs_modifiers. */
7105 static int
7106 mac_event_to_emacs_modifiers (EventRef eventRef)
7108 UInt32 mods = 0;
7109 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7110 sizeof (UInt32), NULL, &mods);
7111 if (!NILP (Vmac_emulate_three_button_mouse) &&
7112 GetEventClass(eventRef) == kEventClassMouse)
7114 mods &= ~(optionKey | cmdKey);
7116 return mac_to_emacs_modifiers (mods);
7119 /* Given an event ref, return the code to use for the mouse button
7120 code in the emacs input_event. */
7121 static int
7122 mac_get_mouse_btn (EventRef ref)
7124 EventMouseButton result = kEventMouseButtonPrimary;
7125 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7126 sizeof (EventMouseButton), NULL, &result);
7127 switch (result)
7129 case kEventMouseButtonPrimary:
7130 if (NILP (Vmac_emulate_three_button_mouse))
7131 return 0;
7132 else {
7133 UInt32 mods = 0;
7134 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7135 sizeof (UInt32), NULL, &mods);
7136 return mac_get_emulated_btn(mods);
7138 case kEventMouseButtonSecondary:
7139 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7140 case kEventMouseButtonTertiary:
7141 case 4: /* 4 is the number for the mouse wheel button */
7142 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7143 default:
7144 return 0;
7148 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7149 events. However the click of the mouse wheel is not converted to a
7150 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7151 checks to see if it is a mouse up or down carbon event that has not
7152 been converted, and if so, converts it by hand (to be picked up in
7153 the XTread_socket loop). */
7154 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7156 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7157 /* Do special case for mouse wheel button. */
7158 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7160 UInt32 kind = GetEventKind (eventRef);
7161 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7163 eventRec->what = mouseDown;
7164 result=1;
7166 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7168 eventRec->what = mouseUp;
7169 result=1;
7171 if (result)
7173 /* Need where and when. */
7174 UInt32 mods;
7175 GetEventParameter (eventRef, kEventParamMouseLocation,
7176 typeQDPoint, NULL, sizeof (Point),
7177 NULL, &eventRec->where);
7178 /* Use two step process because new event modifiers are
7179 32-bit and old are 16-bit. Currently, only loss is
7180 NumLock & Fn. */
7181 GetEventParameter (eventRef, kEventParamKeyModifiers,
7182 typeUInt32, NULL, sizeof (UInt32),
7183 NULL, &mods);
7184 eventRec->modifiers = mods;
7186 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7189 return result;
7192 #endif
7194 static void
7195 do_get_menus (void)
7197 Handle menubar_handle;
7198 MenuHandle menu_handle;
7200 menubar_handle = GetNewMBar (128);
7201 if(menubar_handle == NULL)
7202 abort ();
7203 SetMenuBar (menubar_handle);
7204 DrawMenuBar ();
7206 menu_handle = GetMenuHandle (M_APPLE);
7207 if(menu_handle != NULL)
7208 AppendResMenu (menu_handle,'DRVR');
7209 else
7210 abort ();
7214 static void
7215 do_init_managers (void)
7217 #if !TARGET_API_MAC_CARBON
7218 InitGraf (&qd.thePort);
7219 InitFonts ();
7220 FlushEvents (everyEvent, 0);
7221 InitWindows ();
7222 InitMenus ();
7223 TEInit ();
7224 InitDialogs (NULL);
7225 #endif /* !TARGET_API_MAC_CARBON */
7226 InitCursor ();
7228 #if !TARGET_API_MAC_CARBON
7229 arrow_cursor = &qd.arrow;
7231 /* set up some extra stack space for use by emacs */
7232 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7234 /* MaxApplZone must be called for AppleScript to execute more
7235 complicated scripts */
7236 MaxApplZone ();
7237 MoreMasters ();
7238 #endif /* !TARGET_API_MAC_CARBON */
7241 static void
7242 do_check_ram_size (void)
7244 SInt32 physical_ram_size, logical_ram_size;
7246 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7247 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7248 || physical_ram_size > (1 << VALBITS)
7249 || logical_ram_size > (1 << VALBITS))
7251 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7252 exit (1);
7256 static void
7257 do_window_update (WindowPtr win)
7259 struct frame *f = mac_window_to_frame (win);
7261 if (win == tip_window)
7262 /* The tooltip has been drawn already. Avoid the
7263 SET_FRAME_GARBAGED below. */
7264 return;
7266 if (f)
7268 if (f->async_visible == 0)
7270 f->async_visible = 1;
7271 f->async_iconified = 0;
7272 SET_FRAME_GARBAGED (f);
7274 /* An update event is equivalent to MapNotify on X, so report
7275 visibility changes properly. */
7276 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7277 /* Force a redisplay sooner or later to update the
7278 frame titles in case this is the second frame. */
7279 record_asynch_buffer_change ();
7281 else
7283 BeginUpdate (win);
7284 handling_window_update = 1;
7286 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
7288 expose_frame (f, 0, 0, 0, 0);
7290 handling_window_update = 0;
7291 EndUpdate (win);
7296 static int
7297 is_emacs_window (WindowPtr win)
7299 Lisp_Object tail, frame;
7301 if (!win)
7302 return 0;
7304 FOR_EACH_FRAME (tail, frame)
7305 if (FRAME_MAC_P (XFRAME (frame)))
7306 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7307 return 1;
7309 return 0;
7312 static void
7313 do_app_resume ()
7315 /* Window-activate events will do the job. */
7316 #if 0
7317 WindowPtr wp;
7318 struct frame *f;
7320 wp = front_emacs_window ();
7321 if (wp)
7323 f = mac_window_to_frame (wp);
7325 if (f)
7327 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7328 activate_scroll_bars (f);
7332 app_is_suspended = false;
7333 app_sleep_time = WNE_SLEEP_AT_RESUME;
7334 #endif
7337 static void
7338 do_app_suspend ()
7340 /* Window-deactivate events will do the job. */
7341 #if 0
7342 WindowPtr wp;
7343 struct frame *f;
7345 wp = front_emacs_window ();
7346 if (wp)
7348 f = mac_window_to_frame (wp);
7350 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7352 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7353 deactivate_scroll_bars (f);
7357 app_is_suspended = true;
7358 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7359 #endif
7363 static void
7364 do_mouse_moved (mouse_pos, f)
7365 Point mouse_pos;
7366 FRAME_PTR *f;
7368 WindowPtr wp = front_emacs_window ();
7369 struct x_display_info *dpyinfo;
7371 if (wp)
7373 *f = mac_window_to_frame (wp);
7374 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7376 if (dpyinfo->mouse_face_hidden)
7378 dpyinfo->mouse_face_hidden = 0;
7379 clear_mouse_face (dpyinfo);
7382 SetPortWindowPort (wp);
7384 GlobalToLocal (&mouse_pos);
7386 if (dpyinfo->grabbed && tracked_scroll_bar)
7387 x_scroll_bar_note_movement (tracked_scroll_bar,
7388 mouse_pos.v
7389 - XINT (tracked_scroll_bar->top),
7390 TickCount() * (1000 / 60));
7391 else
7392 note_mouse_movement (*f, &mouse_pos);
7397 static void
7398 do_apple_menu (SInt16 menu_item)
7400 #if !TARGET_API_MAC_CARBON
7401 Str255 item_name;
7402 SInt16 da_driver_refnum;
7404 if (menu_item == I_ABOUT)
7405 NoteAlert (ABOUT_ALERT_ID, NULL);
7406 else
7408 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7409 da_driver_refnum = OpenDeskAcc (item_name);
7411 #endif /* !TARGET_API_MAC_CARBON */
7414 void
7415 do_menu_choice (SInt32 menu_choice)
7417 SInt16 menu_id, menu_item;
7419 menu_id = HiWord (menu_choice);
7420 menu_item = LoWord (menu_choice);
7422 if (menu_id == 0)
7423 return;
7425 switch (menu_id)
7427 case M_APPLE:
7428 do_apple_menu (menu_item);
7429 break;
7431 default:
7433 struct frame *f = mac_window_to_frame (front_emacs_window ());
7434 MenuHandle menu = GetMenuHandle (menu_id);
7435 if (menu)
7437 UInt32 refcon;
7439 GetMenuItemRefCon (menu, menu_item, &refcon);
7440 menubar_selection_callback (f, refcon);
7445 HiliteMenu (0);
7449 /* Handle drags in size box. Based on code contributed by Ben
7450 Mesander and IM - Window Manager A. */
7452 static void
7453 do_grow_window (WindowPtr w, EventRecord *e)
7455 long grow_size;
7456 Rect limit_rect;
7457 int rows, columns;
7458 struct frame *f = mac_window_to_frame (w);
7460 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
7462 grow_size = GrowWindow (w, e->where, &limit_rect);
7464 /* see if it really changed size */
7465 if (grow_size != 0)
7467 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
7468 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
7470 x_set_window_size (f, 0, columns, rows);
7475 /* Handle clicks in zoom box. Calculation of "standard state" based
7476 on code in IM - Window Manager A and code contributed by Ben
7477 Mesander. The standard state of an Emacs window is 80-characters
7478 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7480 static void
7481 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7483 GrafPtr save_port;
7484 Rect zoom_rect, port_rect;
7485 Point top_left;
7486 int w_title_height, columns, rows;
7487 struct frame *f = mac_window_to_frame (w);
7489 #if TARGET_API_MAC_CARBON
7491 Point standard_size;
7493 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7494 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7496 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7497 zoom_in_or_out = inZoomIn;
7498 else
7500 /* Adjust the standard size according to character boundaries. */
7502 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7503 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7504 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7505 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7506 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7507 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7508 && port_rect.left == zoom_rect.left
7509 && port_rect.top == zoom_rect.top)
7510 zoom_in_or_out = inZoomIn;
7511 else
7512 zoom_in_or_out = inZoomOut;
7515 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7517 #else /* not TARGET_API_MAC_CARBON */
7518 GetPort (&save_port);
7520 SetPortWindowPort (w);
7522 /* Clear window to avoid flicker. */
7523 EraseRect (&(w->portRect));
7524 if (zoom_in_or_out == inZoomOut)
7526 SetPt (&top_left, w->portRect.left, w->portRect.top);
7527 LocalToGlobal (&top_left);
7529 /* calculate height of window's title bar */
7530 w_title_height = top_left.v - 1
7531 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7533 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7534 zoom_rect = qd.screenBits.bounds;
7535 zoom_rect.top += w_title_height;
7536 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7538 zoom_rect.right = zoom_rect.left
7539 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7541 /* Adjust the standard size according to character boundaries. */
7542 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7543 zoom_rect.bottom =
7544 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7546 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7547 = zoom_rect;
7550 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7552 SetPort (save_port);
7553 #endif /* not TARGET_API_MAC_CARBON */
7555 /* retrieve window size and update application values */
7556 #if TARGET_API_MAC_CARBON
7557 GetWindowPortBounds (w, &port_rect);
7558 #else
7559 port_rect = w->portRect;
7560 #endif
7561 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
7562 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
7563 x_set_window_size (f, 0, columns, rows);
7564 x_real_positions (f, &f->left_pos, &f->top_pos);
7567 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7568 static OSErr
7569 init_mac_drag_n_drop ()
7571 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7572 return result;
7575 /* Intialize AppleEvent dispatcher table for the required events. */
7576 void
7577 init_required_apple_events ()
7579 OSErr err;
7580 long result;
7582 /* Make sure we have apple events before starting. */
7583 err = Gestalt (gestaltAppleEventsAttr, &result);
7584 if (err != noErr)
7585 abort ();
7587 if (!(result & (1 << gestaltAppleEventsPresent)))
7588 abort ();
7590 #if TARGET_API_MAC_CARBON
7591 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7592 NewAEEventHandlerUPP
7593 ((AEEventHandlerProcPtr) do_ae_open_application),
7594 0L, false);
7595 #else
7596 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7597 NewAEEventHandlerProc
7598 ((AEEventHandlerProcPtr) do_ae_open_application),
7599 0L, false);
7600 #endif
7601 if (err != noErr)
7602 abort ();
7604 #if TARGET_API_MAC_CARBON
7605 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7606 NewAEEventHandlerUPP
7607 ((AEEventHandlerProcPtr) do_ae_open_documents),
7608 0L, false);
7609 #else
7610 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7611 NewAEEventHandlerProc
7612 ((AEEventHandlerProcPtr) do_ae_open_documents),
7613 0L, false);
7614 #endif
7615 if (err != noErr)
7616 abort ();
7618 #if TARGET_API_MAC_CARBON
7619 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7620 NewAEEventHandlerUPP
7621 ((AEEventHandlerProcPtr) do_ae_print_documents),
7622 0L, false);
7623 #else
7624 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7625 NewAEEventHandlerProc
7626 ((AEEventHandlerProcPtr) do_ae_print_documents),
7627 0L, false);
7628 #endif
7629 if (err != noErr)
7630 abort ();
7632 #if TARGET_API_MAC_CARBON
7633 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7634 NewAEEventHandlerUPP
7635 ((AEEventHandlerProcPtr) do_ae_quit_application),
7636 0L, false);
7637 #else
7638 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7639 NewAEEventHandlerProc
7640 ((AEEventHandlerProcPtr) do_ae_quit_application),
7641 0L, false);
7642 #endif
7643 if (err != noErr)
7644 abort ();
7647 #if USE_CARBON_EVENTS
7649 void
7650 init_service_handler ()
7652 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7653 {kEventClassService, kEventServiceCopy},
7654 {kEventClassService, kEventServicePaste}};
7655 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7656 3, specs, NULL, NULL);
7660 MAC_TODO: Check to see if this is called by AEProcessDesc...
7662 OSStatus
7663 mac_handle_service_event (EventHandlerCallRef callRef,
7664 EventRef event, void *data)
7666 OSStatus err = noErr;
7667 switch (GetEventKind (event))
7669 case kEventServiceGetTypes:
7671 CFMutableArrayRef copyTypes, pasteTypes;
7672 CFStringRef type;
7673 Boolean selection = true;
7675 GetEventParameter(event, kEventParamServicePasteTypes,
7676 typeCFMutableArrayRef, NULL,
7677 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7679 GetEventParameter(event, kEventParamServiceCopyTypes,
7680 typeCFMutableArrayRef, NULL,
7681 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7682 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7683 if (type) {
7684 CFArrayAppendValue (copyTypes, type);
7685 //CFArrayAppendValue (pasteTypes, type);
7686 CFRelease (type);
7689 case kEventServiceCopy:
7691 ScrapRef currentScrap, specificScrap;
7692 char * buf = "";
7693 Size byteCount = 0;
7695 GetCurrentScrap (&currentScrap);
7697 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7698 if (err == noErr)
7700 void *buffer = xmalloc (byteCount);
7701 if (buffer != NULL)
7703 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7704 sizeof (ScrapRef), NULL, &specificScrap);
7706 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7707 &byteCount, buffer);
7708 if (err == noErr)
7709 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7710 kScrapFlavorMaskNone, byteCount, buffer);
7711 xfree (buffer);
7714 err = noErr;
7716 case kEventServicePaste:
7719 // Get the current location
7720 Size byteCount;
7721 ScrapRef specificScrap;
7722 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7723 sizeof(ScrapRef), NULL, &specificScrap);
7724 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7725 if (err == noErr) {
7726 void * buffer = xmalloc(byteCount);
7727 if (buffer != NULL ) {
7728 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7729 &byteCount, buffer);
7730 if (err == noErr) {
7731 // Actually place in the buffer
7732 BLOCK_INPUT;
7733 // Get the current "selection" string here
7734 UNBLOCK_INPUT;
7737 xfree(buffer);
7742 return err;
7744 #endif
7746 /* Open Application Apple Event */
7747 static pascal OSErr
7748 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7750 return noErr;
7754 /* Defined in mac.c. */
7755 extern int
7756 path_from_vol_dir_name (char *, int, short, long, char *);
7759 /* Called when we receive an AppleEvent with an ID of
7760 "kAEOpenDocuments". This routine gets the direct parameter,
7761 extracts the FSSpecs in it, and puts their names on a list. */
7762 static pascal OSErr
7763 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7765 OSErr err, err2;
7766 AEDesc the_desc;
7767 AEKeyword keyword;
7768 DescType actual_type;
7769 Size actual_size;
7771 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7772 if (err != noErr)
7773 goto descriptor_error_exit;
7775 /* Check to see that we got all of the required parameters from the
7776 event descriptor. For an 'odoc' event this should just be the
7777 file list. */
7778 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
7779 &actual_type, (Ptr) &keyword,
7780 sizeof (keyword), &actual_size);
7781 /* No error means that we found some unused parameters.
7782 errAEDescNotFound means that there are no more parameters. If we
7783 get an error code other than that, flag it. */
7784 if ((err == noErr) || (err != errAEDescNotFound))
7786 err = errAEEventNotHandled;
7787 goto error_exit;
7789 err = noErr;
7791 /* Got all the parameters we need. Now, go through the direct
7792 object list and parse it up. */
7794 long num_files_to_open;
7796 err = AECountItems (&the_desc, &num_files_to_open);
7797 if (err == noErr)
7799 int i;
7801 /* AE file list is one based so just use that for indexing here. */
7802 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7804 FSSpec fs;
7805 Str255 path_name, unix_path_name;
7806 #ifdef MAC_OSX
7807 FSRef fref;
7808 #endif
7810 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7811 (Ptr) &fs, sizeof (fs), &actual_size);
7812 if (err != noErr) break;
7814 #ifdef MAC_OSX
7815 err = FSpMakeFSRef (&fs, &fref);
7816 if (err != noErr) break;
7818 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
7819 #else
7820 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
7821 fs.name) &&
7822 mac_to_posix_pathname (path_name, unix_path_name, 255))
7823 #endif
7824 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7825 drag_and_drop_file_list);
7830 error_exit:
7831 /* Nuke the coerced file list in any case */
7832 err2 = AEDisposeDesc(&the_desc);
7834 descriptor_error_exit:
7835 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7836 return err;
7840 static pascal OSErr
7841 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
7842 DragReference theDrag)
7844 short items;
7845 short index;
7846 FlavorFlags theFlags;
7847 Point mouse;
7848 OSErr result;
7849 ItemReference theItem;
7850 HFSFlavor data;
7851 FSRef fref;
7852 Size size = sizeof (HFSFlavor);
7854 drag_and_drop_file_list = Qnil;
7855 GetDragMouse (theDrag, &mouse, 0L);
7856 CountDragItems (theDrag, &items);
7857 for (index = 1; index <= items; index++)
7859 /* Only handle file references. */
7860 GetDragItemReferenceNumber (theDrag, index, &theItem);
7861 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
7862 if (result == noErr)
7864 #ifdef MAC_OSX
7865 FSRef frref;
7866 #else
7867 Str255 path_name;
7868 #endif
7869 Str255 unix_path_name;
7870 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
7871 #ifdef MAC_OSX
7872 /* Use Carbon routines, otherwise it converts the file name
7873 to /Macintosh HD/..., which is not correct. */
7874 FSpMakeFSRef (&data.fileSpec, &fref);
7875 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
7876 #else
7877 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
7878 data.fileSpec.parID, data.fileSpec.name) &&
7879 mac_to_posix_pathname (path_name, unix_path_name, 255))
7880 #endif
7881 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7882 drag_and_drop_file_list);
7884 else
7885 return;
7887 /* If there are items in the list, construct an event and post it to
7888 the queue like an interrupt using kbd_buffer_store_event. */
7889 if (!NILP (drag_and_drop_file_list))
7891 struct input_event event;
7892 Lisp_Object frame;
7893 struct frame *f = mac_window_to_frame (window);
7894 SetPortWindowPort (window);
7895 GlobalToLocal (&mouse);
7897 event.kind = DRAG_N_DROP_EVENT;
7898 event.code = 0;
7899 event.modifiers = 0;
7900 event.timestamp = TickCount () * (1000 / 60);
7901 XSETINT (event.x, mouse.h);
7902 XSETINT (event.y, mouse.v);
7903 XSETFRAME (frame, f);
7904 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
7905 event.arg = Qnil;
7906 /* Post to the interrupt queue */
7907 kbd_buffer_store_event (&event);
7908 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7910 ProcessSerialNumber psn;
7911 GetCurrentProcess (&psn);
7912 SetFrontProcess (&psn);
7918 /* Print Document Apple Event */
7919 static pascal OSErr
7920 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
7922 return errAEEventNotHandled;
7926 static pascal OSErr
7927 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
7929 /* FixMe: Do we need an unwind-protect or something here? And what
7930 do we do about unsaved files. Currently just forces quit rather
7931 than doing recursive callback to get user input. */
7933 terminate_flag = true;
7935 /* Fkill_emacs doesn't return. We have to return. (TI) */
7936 return noErr;
7940 #if __profile__
7941 void
7942 profiler_exit_proc ()
7944 ProfilerDump ("\pEmacs.prof");
7945 ProfilerTerm ();
7947 #endif
7949 /* These few functions implement Emacs as a normal Mac application
7950 (almost): set up the heap and the Toolbox, handle necessary
7951 system events plus a few simple menu events. They also set up
7952 Emacs's access to functions defined in the rest of this file.
7953 Emacs uses function hooks to perform all its terminal I/O. A
7954 complete list of these functions appear in termhooks.h. For what
7955 they do, read the comments there and see also w32term.c and
7956 xterm.c. What's noticeably missing here is the event loop, which
7957 is normally present in most Mac application. After performing the
7958 necessary Mac initializations, main passes off control to
7959 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7960 mac_read_socket (defined further below) to read input. This is
7961 where WaitNextEvent is called to process Mac events. This is also
7962 where check_alarm in sysdep.c is called to simulate alarm signals.
7963 This makes the cursor jump back to its correct position after
7964 briefly jumping to that of the matching parenthesis, print useful
7965 hints and prompts in the minibuffer after the user stops typing for
7966 a wait, etc. */
7968 #if !TARGET_API_MAC_CARBON
7969 #undef main
7971 main (void)
7973 #if __profile__ /* is the profiler on? */
7974 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
7975 exit(1);
7976 #endif
7978 #if __MWERKS__
7979 /* set creator and type for files created by MSL */
7980 _fcreator = 'EMAx';
7981 _ftype = 'TEXT';
7982 #endif
7984 do_init_managers ();
7986 do_get_menus ();
7988 #ifndef USE_LSB_TAG
7989 do_check_ram_size ();
7990 #endif
7992 init_emacs_passwd_dir ();
7994 init_environ ();
7996 initialize_applescript ();
7998 init_required_apple_events ();
8001 char **argv;
8002 int argc = 0;
8004 /* set up argv array from STR# resource */
8005 get_string_list (&argv, ARGV_STRING_LIST_ID);
8006 while (argv[argc])
8007 argc++;
8009 /* free up AppleScript resources on exit */
8010 atexit (terminate_applescript);
8012 #if __profile__ /* is the profiler on? */
8013 atexit (profiler_exit_proc);
8014 #endif
8016 /* 3rd param "envp" never used in emacs_main */
8017 (void) emacs_main (argc, argv, 0);
8020 /* Never reached - real exit in Fkill_emacs */
8021 return 0;
8023 #endif
8025 /* Table for translating Mac keycode to X keysym values. Contributed
8026 by Sudhir Shenoy. */
8027 static unsigned char keycode_to_xkeysym_table[] = {
8028 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8029 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8030 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8032 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8033 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8034 /*0x38*/ 0, 0, 0, 0,
8035 /*0x3C*/ 0, 0, 0, 0,
8037 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8038 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8039 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8040 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8042 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8043 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8044 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8045 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8047 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8048 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8049 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8050 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8052 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8053 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8054 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8055 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8058 static int
8059 keycode_to_xkeysym (int keyCode, int *xKeySym)
8061 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8062 return *xKeySym != 0;
8065 /* Emacs calls this whenever it wants to read an input event from the
8066 user. */
8068 XTread_socket (sd, expected, hold_quit)
8069 int sd, expected;
8070 struct input_event *hold_quit;
8072 struct input_event inev;
8073 int count = 0;
8074 #if USE_CARBON_EVENTS
8075 EventRef eventRef;
8076 EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget ();
8077 #else
8078 EventMask event_mask;
8079 #endif
8080 EventRecord er;
8081 struct mac_display_info *dpyinfo = &one_mac_display_info;
8083 if (interrupt_input_blocked)
8085 interrupt_input_pending = 1;
8086 return -1;
8089 interrupt_input_pending = 0;
8090 BLOCK_INPUT;
8092 /* So people can tell when we have read the available input. */
8093 input_signal_count++;
8095 /* Don't poll for events to process (specifically updateEvt) if
8096 window update currently already in progress. A call to redisplay
8097 (in do_window_update) can be preempted by another call to
8098 redisplay, causing blank regions to be left on the screen and the
8099 cursor to be left at strange places. */
8100 if (handling_window_update)
8102 UNBLOCK_INPUT;
8103 return 0;
8106 if (terminate_flag)
8107 Fkill_emacs (make_number (1));
8109 #if !USE_CARBON_EVENTS
8110 event_mask = everyEvent;
8111 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8112 event_mask -= highLevelEventMask;
8114 while (WaitNextEvent (event_mask, &er, 0L, NULL))
8115 #else /* USE_CARBON_EVENTS */
8116 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8117 kEventRemoveFromQueue, &eventRef))
8118 #endif /* USE_CARBON_EVENTS */
8120 int do_help = 0;
8121 struct frame *f;
8123 /* It is necessary to set this (additional) argument slot of an
8124 event to nil because keyboard.c protects incompletely
8125 processed event from being garbage collected by placing them
8126 in the kbd_buffer_gcpro vector. */
8127 EVENT_INIT (inev);
8128 inev.kind = NO_EVENT;
8129 inev.arg = Qnil;
8131 #if USE_CARBON_EVENTS
8132 /* Handle new events */
8133 if (!mac_convert_event_ref (eventRef, &er))
8134 switch (GetEventClass (eventRef))
8136 case kEventClassWindow:
8137 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8139 WindowPtr window_ptr;
8140 GetEventParameter(eventRef, kEventParamDirectObject,
8141 typeWindowRef, NULL, sizeof(WindowPtr),
8142 NULL, &window_ptr);
8143 f = mac_window_to_frame (window_ptr);
8144 if (f && !f->async_iconified)
8145 x_real_positions (f, &f->left_pos, &f->top_pos);
8146 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8148 break;
8149 case kEventClassMouse:
8150 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8152 SInt32 delta;
8153 Point point;
8154 WindowPtr window_ptr = front_emacs_window ();
8156 if (!IsValidWindowPtr (window_ptr))
8158 SysBeep(1);
8159 break;
8162 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8163 typeSInt32, NULL, sizeof (SInt32),
8164 NULL, &delta);
8165 GetEventParameter(eventRef, kEventParamMouseLocation,
8166 typeQDPoint, NULL, sizeof (Point),
8167 NULL, &point);
8168 inev.kind = WHEEL_EVENT;
8169 inev.code = 0;
8170 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8171 | ((delta < 0) ? down_modifier
8172 : up_modifier));
8173 SetPortWindowPort (window_ptr);
8174 GlobalToLocal (&point);
8175 XSETINT (inev.x, point.h);
8176 XSETINT (inev.y, point.v);
8177 XSETFRAME (inev.frame_or_window,
8178 mac_window_to_frame (window_ptr));
8179 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8181 else
8182 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8184 break;
8185 default:
8186 /* Send the event to the appropriate receiver. */
8187 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8189 else
8190 #endif /* USE_CARBON_EVENTS */
8191 switch (er.what)
8193 case mouseDown:
8194 case mouseUp:
8196 WindowPtr window_ptr;
8197 SInt16 part_code;
8198 int tool_bar_p = 0;
8200 #if USE_CARBON_EVENTS
8201 /* This is needed to send mouse events like aqua window
8202 buttons to the correct handler. */
8203 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8204 != eventNotHandledErr)
8205 break;
8206 #endif
8208 if (dpyinfo->grabbed && last_mouse_frame
8209 && FRAME_LIVE_P (last_mouse_frame))
8211 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8212 part_code = inContent;
8214 else
8216 part_code = FindWindow (er.where, &window_ptr);
8217 if (tip_window && window_ptr == tip_window)
8219 HideWindow (tip_window);
8220 part_code = FindWindow (er.where, &window_ptr);
8224 if (er.what != mouseDown && part_code != inContent)
8225 break;
8227 switch (part_code)
8229 case inMenuBar:
8230 f = mac_window_to_frame (front_emacs_window ());
8231 saved_menu_event_location = er.where;
8232 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8233 XSETFRAME (inev.frame_or_window, f);
8234 break;
8236 case inContent:
8237 if (window_ptr != front_emacs_window ())
8238 SelectWindow (window_ptr);
8239 else
8241 SInt16 control_part_code;
8242 ControlHandle ch;
8243 Point mouse_loc = er.where;
8245 f = mac_window_to_frame (window_ptr);
8246 /* convert to local coordinates of new window */
8247 SetPortWindowPort (window_ptr);
8249 GlobalToLocal (&mouse_loc);
8250 #if TARGET_API_MAC_CARBON
8251 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8252 &control_part_code);
8253 #else
8254 control_part_code = FindControl (mouse_loc, window_ptr,
8255 &ch);
8256 #endif
8258 #if USE_CARBON_EVENTS
8259 inev.code = mac_get_mouse_btn (eventRef);
8260 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8261 #else
8262 inev.code = mac_get_emulated_btn (er.modifiers);
8263 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8264 #endif
8265 XSETINT (inev.x, mouse_loc.h);
8266 XSETINT (inev.y, mouse_loc.v);
8267 inev.timestamp = er.when * (1000 / 60);
8268 /* ticks to milliseconds */
8270 if (dpyinfo->grabbed && tracked_scroll_bar
8271 #if TARGET_API_MAC_CARBON
8272 || ch != 0
8273 #else
8274 || control_part_code != 0
8275 #endif
8278 struct scroll_bar *bar;
8280 if (dpyinfo->grabbed && tracked_scroll_bar)
8282 bar = tracked_scroll_bar;
8283 control_part_code = kControlIndicatorPart;
8285 else
8286 bar = (struct scroll_bar *) GetControlReference (ch);
8287 x_scroll_bar_handle_click (bar, control_part_code,
8288 &er, &inev);
8289 if (er.what == mouseDown
8290 && control_part_code == kControlIndicatorPart)
8291 tracked_scroll_bar = bar;
8292 else
8293 tracked_scroll_bar = NULL;
8295 else
8297 Lisp_Object window;
8298 int x = mouse_loc.h;
8299 int y = mouse_loc.v;
8301 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8302 if (EQ (window, f->tool_bar_window))
8304 if (er.what == mouseDown)
8305 handle_tool_bar_click (f, x, y, 1, 0);
8306 else
8307 handle_tool_bar_click (f, x, y, 0,
8308 inev.modifiers);
8309 tool_bar_p = 1;
8311 else
8313 XSETFRAME (inev.frame_or_window, f);
8314 inev.kind = MOUSE_CLICK_EVENT;
8318 if (er.what == mouseDown)
8320 dpyinfo->grabbed |= (1 << inev.code);
8321 last_mouse_frame = f;
8322 /* Ignore any mouse motion that happened
8323 before this event; any subsequent
8324 mouse-movement Emacs events should reflect
8325 only motion after the ButtonPress. */
8326 if (f != 0)
8327 f->mouse_moved = 0;
8329 if (!tool_bar_p)
8330 last_tool_bar_item = -1;
8332 else
8334 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8335 /* If a button is released though it was not
8336 previously pressed, that would be because
8337 of multi-button emulation. */
8338 dpyinfo->grabbed = 0;
8339 else
8340 dpyinfo->grabbed &= ~(1 << inev.code);
8343 switch (er.what)
8345 case mouseDown:
8346 inev.modifiers |= down_modifier;
8347 break;
8348 case mouseUp:
8349 inev.modifiers |= up_modifier;
8350 break;
8353 break;
8355 case inDrag:
8356 #if TARGET_API_MAC_CARBON
8357 DragWindow (window_ptr, er.where, NULL);
8358 #else /* not TARGET_API_MAC_CARBON */
8359 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8360 #endif /* not TARGET_API_MAC_CARBON */
8361 /* Update the frame parameters. */
8363 struct frame *f = mac_window_to_frame (window_ptr);
8365 if (f && !f->async_iconified)
8366 x_real_positions (f, &f->left_pos, &f->top_pos);
8368 break;
8370 case inGoAway:
8371 if (TrackGoAway (window_ptr, er.where))
8373 inev.kind = DELETE_WINDOW_EVENT;
8374 XSETFRAME (inev.frame_or_window,
8375 mac_window_to_frame (window_ptr));
8377 break;
8379 /* window resize handling added --ben */
8380 case inGrow:
8381 do_grow_window (window_ptr, &er);
8382 break;
8384 /* window zoom handling added --ben */
8385 case inZoomIn:
8386 case inZoomOut:
8387 if (TrackBox (window_ptr, er.where, part_code))
8388 do_zoom_window (window_ptr, part_code);
8389 break;
8391 default:
8392 break;
8395 break;
8397 case updateEvt:
8398 #if USE_CARBON_EVENTS
8399 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8400 != eventNotHandledErr)
8401 break;
8402 #endif
8403 do_window_update ((WindowPtr) er.message);
8404 break;
8406 case osEvt:
8407 #if USE_CARBON_EVENTS
8408 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8409 != eventNotHandledErr)
8410 break;
8411 #endif
8412 switch ((er.message >> 24) & 0x000000FF)
8414 case suspendResumeMessage:
8415 if ((er.message & resumeFlag) == 1)
8416 do_app_resume ();
8417 else
8418 do_app_suspend ();
8419 break;
8421 case mouseMovedMessage:
8422 previous_help_echo_string = help_echo_string;
8423 help_echo_string = help_echo_object = help_echo_window = Qnil;
8424 help_echo_pos = -1;
8426 do_mouse_moved (er.where, &f);
8428 /* If the contents of the global variable
8429 help_echo_string has changed, generate a
8430 HELP_EVENT. */
8431 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8432 do_help = 1;
8433 break;
8435 break;
8437 case activateEvt:
8439 WindowPtr window_ptr = (WindowPtr) er.message;
8441 #if USE_CARBON_EVENTS
8442 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8443 != eventNotHandledErr)
8444 break;
8445 #endif
8446 if (window_ptr == tip_window)
8448 HideWindow (tip_window);
8449 break;
8452 if (!is_emacs_window (window_ptr))
8453 break;
8455 f = mac_window_to_frame (window_ptr);
8457 if ((er.modifiers & activeFlag) != 0)
8459 /* A window has been activated */
8460 Point mouse_loc = er.where;
8462 x_new_focus_frame (dpyinfo, f);
8463 activate_scroll_bars (f);
8465 SetPortWindowPort (window_ptr);
8466 GlobalToLocal (&mouse_loc);
8467 /* Window-activated event counts as mouse movement,
8468 so update things that depend on mouse position. */
8469 note_mouse_movement (mac_window_to_frame (window_ptr),
8470 &mouse_loc);
8472 else
8474 /* A window has been deactivated */
8475 dpyinfo->grabbed = 0;
8477 if (f == dpyinfo->x_focus_frame)
8479 x_new_focus_frame (dpyinfo, 0);
8480 deactivate_scroll_bars (f);
8484 if (f == dpyinfo->mouse_face_mouse_frame)
8486 /* If we move outside the frame, then we're
8487 certainly no longer on any text in the
8488 frame. */
8489 clear_mouse_face (dpyinfo);
8490 dpyinfo->mouse_face_mouse_frame = 0;
8493 /* Generate a nil HELP_EVENT to cancel a help-echo.
8494 Do it only if there's something to cancel.
8495 Otherwise, the startup message is cleared when the
8496 mouse leaves the frame. */
8497 if (any_help_event_p)
8498 do_help = -1;
8501 break;
8503 case keyDown:
8504 case autoKey:
8506 int keycode = (er.message & keyCodeMask) >> 8;
8507 int xkeysym;
8509 #if USE_CARBON_EVENTS
8510 /* When using Carbon Events, we need to pass raw keyboard
8511 events to the TSM ourselves. If TSM handles it, it
8512 will pass back noErr, otherwise it will pass back
8513 "eventNotHandledErr" and we can process it
8514 normally. */
8515 if ((!NILP (Vmac_pass_command_to_system)
8516 || !(er.modifiers & cmdKey))
8517 && (!NILP (Vmac_pass_control_to_system)
8518 || !(er.modifiers & controlKey)))
8519 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8520 != eventNotHandledErr)
8521 break;
8522 #endif
8524 #if TARGET_API_MAC_CARBON
8525 if (!IsValidWindowPtr (front_emacs_window ()))
8527 SysBeep (1);
8528 break;
8530 #endif
8532 ObscureCursor ();
8534 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8536 clear_mouse_face (dpyinfo);
8537 dpyinfo->mouse_face_hidden = 1;
8540 if (keycode_to_xkeysym (keycode, &xkeysym))
8542 inev.code = 0xff00 | xkeysym;
8543 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8545 else
8547 if (er.modifiers & (controlKey |
8548 (NILP (Vmac_command_key_is_meta) ? optionKey
8549 : cmdKey)))
8551 /* This code comes from Keyboard Resource,
8552 Appendix C of IM - Text. This is necessary
8553 since shift is ignored in KCHR table
8554 translation when option or command is pressed.
8555 It also does not translate correctly
8556 control-shift chars like C-% so mask off shift
8557 here also */
8558 int new_modifiers = er.modifiers & 0xe600;
8559 /* mask off option and command */
8560 int new_keycode = keycode | new_modifiers;
8561 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8562 unsigned long some_state = 0;
8563 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8564 &some_state) & 0xff;
8565 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
8567 /* When using the option key as an emacs modifier, convert
8568 the pressed key code back to one without the Mac option
8569 modifier applied. */
8570 int new_modifiers = er.modifiers & ~optionKey;
8571 int new_keycode = keycode | new_modifiers;
8572 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8573 unsigned long some_state = 0;
8574 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8575 &some_state) & 0xff;
8577 else
8578 inev.code = er.message & charCodeMask;
8579 inev.kind = ASCII_KEYSTROKE_EVENT;
8583 /* If variable mac-convert-keyboard-input-to-latin-1 is
8584 non-nil, convert non-ASCII characters typed at the Mac
8585 keyboard (presumed to be in the Mac Roman encoding) to
8586 iso-latin-1 encoding before they are passed to Emacs.
8587 This enables the Mac keyboard to be used to enter
8588 non-ASCII iso-latin-1 characters directly. */
8589 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
8590 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
8592 static TECObjectRef converter = NULL;
8593 OSStatus the_err = noErr;
8594 OSStatus convert_status = noErr;
8596 if (converter == NULL)
8598 the_err = TECCreateConverter (&converter,
8599 kTextEncodingMacRoman,
8600 mac_keyboard_text_encoding);
8601 current_mac_keyboard_text_encoding
8602 = mac_keyboard_text_encoding;
8604 else if (mac_keyboard_text_encoding
8605 != current_mac_keyboard_text_encoding)
8607 /* Free the converter for the current encoding
8608 before creating a new one. */
8609 TECDisposeConverter (converter);
8610 the_err = TECCreateConverter (&converter,
8611 kTextEncodingMacRoman,
8612 mac_keyboard_text_encoding);
8613 current_mac_keyboard_text_encoding
8614 = mac_keyboard_text_encoding;
8617 if (the_err == noErr)
8619 unsigned char ch = inev.code;
8620 ByteCount actual_input_length, actual_output_length;
8621 unsigned char outch;
8623 convert_status = TECConvertText (converter, &ch, 1,
8624 &actual_input_length,
8625 &outch, 1,
8626 &actual_output_length);
8627 if (convert_status == noErr
8628 && actual_input_length == 1
8629 && actual_output_length == 1)
8630 inev.code = outch;
8634 #if USE_CARBON_EVENTS
8635 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8636 #else
8637 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8638 #endif
8639 XSETFRAME (inev.frame_or_window,
8640 mac_window_to_frame (front_emacs_window ()));
8641 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8642 break;
8644 case kHighLevelEvent:
8645 drag_and_drop_file_list = Qnil;
8647 AEProcessAppleEvent(&er);
8649 /* Build a DRAG_N_DROP_EVENT type event as is done in
8650 constuct_drag_n_drop in w32term.c. */
8651 if (!NILP (drag_and_drop_file_list))
8653 struct frame *f = NULL;
8654 WindowPtr wp;
8655 Lisp_Object frame;
8657 wp = front_emacs_window ();
8659 if (!wp)
8661 struct frame *f = XFRAME (XCAR (Vframe_list));
8662 CollapseWindow (FRAME_MAC_WINDOW (f), false);
8663 wp = front_emacs_window ();
8666 if (wp)
8667 f = mac_window_to_frame (wp);
8669 inev.kind = DRAG_N_DROP_EVENT;
8670 inev.code = 0;
8671 inev.timestamp = er.when * (1000 / 60);
8672 /* ticks to milliseconds */
8673 #if USE_CARBON_EVENTS
8674 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8675 #else
8676 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8677 #endif
8679 XSETINT (inev.x, 0);
8680 XSETINT (inev.y, 0);
8682 XSETFRAME (frame, f);
8683 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8685 /* Regardless of whether Emacs was suspended or in the
8686 foreground, ask it to redraw its entire screen.
8687 Otherwise parts of the screen can be left in an
8688 inconsistent state. */
8689 if (wp)
8690 #if TARGET_API_MAC_CARBON
8692 Rect r;
8694 GetWindowPortBounds (wp, &r);
8695 InvalWindowRect (wp, &r);
8697 #else /* not TARGET_API_MAC_CARBON */
8698 InvalRect (&(wp->portRect));
8699 #endif /* not TARGET_API_MAC_CARBON */
8701 default:
8702 break;
8704 #if USE_CARBON_EVENTS
8705 ReleaseEvent (eventRef);
8706 #endif
8708 if (inev.kind != NO_EVENT)
8710 kbd_buffer_store_event_hold (&inev, hold_quit);
8711 count++;
8714 if (do_help
8715 && !(hold_quit && hold_quit->kind != NO_EVENT))
8717 Lisp_Object frame;
8719 if (f)
8720 XSETFRAME (frame, f);
8721 else
8722 frame = Qnil;
8724 if (do_help > 0)
8726 any_help_event_p = 1;
8727 gen_help_event (help_echo_string, frame, help_echo_window,
8728 help_echo_object, help_echo_pos);
8730 else
8732 help_echo_string = Qnil;
8733 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
8735 count++;
8740 /* If the focus was just given to an autoraising frame,
8741 raise it now. */
8742 /* ??? This ought to be able to handle more than one such frame. */
8743 if (pending_autoraise_frame)
8745 x_raise_frame (pending_autoraise_frame);
8746 pending_autoraise_frame = 0;
8749 #if !TARGET_API_MAC_CARBON
8750 check_alarm (); /* simulate the handling of a SIGALRM */
8751 #endif
8753 UNBLOCK_INPUT;
8754 return count;
8758 /* Need to override CodeWarrior's input function so no conversion is
8759 done on newlines Otherwise compiled functions in .elc files will be
8760 read incorrectly. Defined in ...:MSL C:MSL
8761 Common:Source:buffer_io.c. */
8762 #ifdef __MWERKS__
8763 void
8764 __convert_to_newlines (unsigned char * p, size_t * n)
8766 #pragma unused(p,n)
8769 void
8770 __convert_from_newlines (unsigned char * p, size_t * n)
8772 #pragma unused(p,n)
8774 #endif
8777 /* Initialize the struct pointed to by MW to represent a new COLS x
8778 ROWS Macintosh window, using font with name FONTNAME and size
8779 FONTSIZE. */
8780 void
8781 make_mac_frame (FRAME_PTR fp)
8783 mac_output *mwp;
8784 #if TARGET_API_MAC_CARBON
8785 static int making_terminal_window = 0;
8786 #else
8787 static int making_terminal_window = 1;
8788 #endif
8790 mwp = fp->output_data.mac;
8792 BLOCK_INPUT;
8793 if (making_terminal_window)
8795 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
8796 (WindowPtr) -1)))
8797 abort ();
8798 making_terminal_window = 0;
8800 else
8802 #if TARGET_API_MAC_CARBON
8803 Rect r;
8805 SetRect (&r, 0, 0, 1, 1);
8806 if (CreateNewWindow (kDocumentWindowClass,
8807 kWindowStandardDocumentAttributes
8808 /* | kWindowToolbarButtonAttribute */,
8809 &r, &mwp->mWP) != noErr)
8810 #else
8811 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
8812 #endif
8813 abort ();
8816 SetWRefCon (mwp->mWP, (long) mwp);
8817 /* so that update events can find this mac_output struct */
8818 mwp->mFP = fp; /* point back to emacs frame */
8820 SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
8821 UNBLOCK_INPUT;
8825 void
8826 make_mac_terminal_frame (struct frame *f)
8828 Lisp_Object frame;
8830 XSETFRAME (frame, f);
8832 f->output_method = output_mac;
8833 f->output_data.mac = (struct mac_output *)
8834 xmalloc (sizeof (struct mac_output));
8835 bzero (f->output_data.mac, sizeof (struct mac_output));
8837 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8839 FRAME_COLS (f) = 96;
8840 FRAME_LINES (f) = 4;
8842 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8843 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8845 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8847 f->output_data.mac->cursor_pixel = 0;
8848 f->output_data.mac->border_pixel = 0x00ff00;
8849 f->output_data.mac->mouse_pixel = 0xff00ff;
8850 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
8852 FRAME_FONTSET (f) = -1;
8853 f->output_data.mac->explicit_parent = 0;
8854 f->left_pos = 4;
8855 f->top_pos = 4;
8856 f->border_width = 0;
8858 f->internal_border_width = 0;
8860 f->auto_raise = 1;
8861 f->auto_lower = 1;
8863 f->new_text_cols = 0;
8864 f->new_text_lines = 0;
8866 make_mac_frame (f);
8868 x_make_gc (f);
8870 /* Need to be initialized for unshow_buffer in window.c. */
8871 selected_window = f->selected_window;
8873 Fmodify_frame_parameters (frame,
8874 Fcons (Fcons (Qfont,
8875 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
8876 Fmodify_frame_parameters (frame,
8877 Fcons (Fcons (Qforeground_color,
8878 build_string ("black")), Qnil));
8879 Fmodify_frame_parameters (frame,
8880 Fcons (Fcons (Qbackground_color,
8881 build_string ("white")), Qnil));
8883 ShowWindow (f->output_data.mac->mWP);
8887 /***********************************************************************
8888 Initialization
8889 ***********************************************************************/
8891 int mac_initialized = 0;
8893 void
8894 mac_initialize_display_info ()
8896 struct mac_display_info *dpyinfo = &one_mac_display_info;
8897 GDHandle main_device_handle;
8899 bzero (dpyinfo, sizeof (*dpyinfo));
8901 /* Put it on x_display_name_list. */
8902 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
8903 x_display_name_list);
8904 dpyinfo->name_list_element = XCAR (x_display_name_list);
8906 #if 0
8907 dpyinfo->mac_id_name
8908 = (char *) xmalloc (SCHARS (Vinvocation_name)
8909 + SCHARS (Vsystem_name)
8910 + 2);
8911 sprintf (dpyinfo->mac_id_name, "%s@%s",
8912 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8913 #else
8914 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
8915 strcpy (dpyinfo->mac_id_name, "Mac Display");
8916 #endif
8918 main_device_handle = LMGetMainDevice();
8920 dpyinfo->reference_count = 0;
8921 dpyinfo->resx = 75.0;
8922 dpyinfo->resy = 75.0;
8923 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
8924 #ifdef MAC_OSX
8925 /* HasDepth returns true if it is possible to have a 32 bit display,
8926 but this may not be what is actually used. Mac OSX can do better.
8927 CGMainDisplayID is only available on OSX 10.2 and higher, but the
8928 header for CGGetActiveDisplayList says that the first display returned
8929 is the active one, so we use that. */
8931 CGDirectDisplayID disp_id[1];
8932 CGDisplayCount disp_count;
8933 CGDisplayErr error_code;
8935 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
8936 if (error_code != 0)
8937 error ("No display found, CGGetActiveDisplayList error %d", error_code);
8939 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
8941 #else
8942 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
8943 if (HasDepth (main_device_handle, dpyinfo->n_planes,
8944 gdDevType, dpyinfo->color_p))
8945 break;
8946 #endif
8947 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8948 dpyinfo->width = (**main_device_handle).gdRect.right;
8949 dpyinfo->grabbed = 0;
8950 dpyinfo->root_window = NULL;
8951 dpyinfo->image_cache = make_image_cache ();
8953 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8954 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8955 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8956 dpyinfo->mouse_face_window = Qnil;
8957 dpyinfo->mouse_face_overlay = Qnil;
8958 dpyinfo->mouse_face_hidden = 0;
8961 struct mac_display_info *
8962 mac_term_init (display_name, xrm_option, resource_name)
8963 Lisp_Object display_name;
8964 char *xrm_option;
8965 char *resource_name;
8967 struct mac_display_info *dpyinfo;
8968 GDHandle main_device_handle;
8970 if (!mac_initialized)
8972 mac_initialize ();
8973 mac_initialized = 1;
8976 mac_initialize_display_info (display_name);
8978 dpyinfo = &one_mac_display_info;
8980 main_device_handle = LMGetMainDevice();
8982 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8983 dpyinfo->width = (**main_device_handle).gdRect.right;
8985 return dpyinfo;
8988 #ifdef MAC_OSX
8989 void
8990 mac_check_bundle()
8992 extern int inhibit_window_system;
8993 extern int noninteractive;
8994 CFBundleRef appsBundle;
8995 pid_t child;
8997 /* No need to test if already -nw*/
8998 if (inhibit_window_system || noninteractive)
8999 return;
9001 appsBundle = CFBundleGetMainBundle();
9002 if (appsBundle != NULL)
9004 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9005 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9006 /* We found the bundle identifier, now we know we are valid. */
9007 if (res != NULL)
9009 CFRelease(res);
9010 return;
9013 /* MAC_TODO: Have this start the bundled executable */
9015 /* For now, prevent the fatal error by bringing it up in the terminal */
9016 inhibit_window_system = 1;
9019 void
9020 MakeMeTheFrontProcess ()
9022 ProcessSerialNumber psn;
9023 OSErr err;
9025 err = GetCurrentProcess (&psn);
9026 if (err == noErr)
9027 (void) SetFrontProcess (&psn);
9030 /***** Code to handle C-g testing *****/
9032 /* Contains the Mac modifier formed from quit_char */
9033 static mac_quit_char_modifiers = 0;
9034 static mac_quit_char_keycode;
9035 extern int quit_char;
9037 static void
9038 mac_determine_quit_char_modifiers()
9040 /* Todo: Determine modifiers from quit_char. */
9041 UInt32 qc_modifiers = ctrl_modifier;
9043 /* Map modifiers */
9044 mac_quit_char_modifiers = 0;
9045 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9046 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9047 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9048 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9051 static void
9052 init_quit_char_handler ()
9054 /* TODO: Let this support keys other the 'g' */
9055 mac_quit_char_keycode = 5;
9056 /* Look at <architecture/adb_kb_map.h> for details */
9057 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9059 mac_determine_quit_char_modifiers();
9062 static Boolean
9063 quit_char_comp (EventRef inEvent, void *inCompData)
9065 if (GetEventClass(inEvent) != kEventClassKeyboard)
9066 return false;
9067 if (GetEventKind(inEvent) != kEventRawKeyDown)
9068 return false;
9070 UInt32 keyCode;
9071 UInt32 keyModifiers;
9072 GetEventParameter(inEvent, kEventParamKeyCode,
9073 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9074 if (keyCode != mac_quit_char_keycode)
9075 return false;
9076 GetEventParameter(inEvent, kEventParamKeyModifiers,
9077 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9078 if (keyModifiers != mac_quit_char_modifiers)
9079 return false;
9081 return true;
9084 void
9085 mac_check_for_quit_char ()
9087 EventRef event;
9088 static EMACS_TIME last_check_time = { 0, 0 };
9089 static EMACS_TIME one_second = { 1, 0 };
9090 EMACS_TIME now, t;
9092 /* If windows are not initialized, return immediately (keep it bouncin'). */
9093 if (!mac_quit_char_modifiers)
9094 return;
9096 /* Don't check if last check is less than a second ago. */
9097 EMACS_GET_TIME (now);
9098 EMACS_SUB_TIME (t, now, last_check_time);
9099 if (EMACS_TIME_LT (t, one_second))
9100 return;
9101 last_check_time = now;
9103 /* Redetermine modifiers because they are based on lisp variables */
9104 mac_determine_quit_char_modifiers ();
9106 /* Fill the queue with events */
9107 BLOCK_INPUT;
9108 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9109 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9110 NULL);
9111 UNBLOCK_INPUT;
9112 if (event)
9114 struct input_event e;
9116 /* Use an input_event to emulate what the interrupt handler does. */
9117 EVENT_INIT (e);
9118 e.kind = ASCII_KEYSTROKE_EVENT;
9119 e.code = quit_char;
9120 e.arg = Qnil;
9121 e.modifiers = NULL;
9122 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9123 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9124 /* Remove event from queue to prevent looping. */
9125 RemoveEventFromQueue (GetMainEventQueue (), event);
9126 ReleaseEvent (event);
9127 kbd_buffer_store_event (&e);
9131 #endif /* MAC_OSX */
9133 /* Set up use of X before we make the first connection. */
9135 extern frame_parm_handler mac_frame_parm_handlers[];
9137 static struct redisplay_interface x_redisplay_interface =
9139 mac_frame_parm_handlers,
9140 x_produce_glyphs,
9141 x_write_glyphs,
9142 x_insert_glyphs,
9143 x_clear_end_of_line,
9144 x_scroll_run,
9145 x_after_update_window_line,
9146 x_update_window_begin,
9147 x_update_window_end,
9148 x_cursor_to,
9149 x_flush,
9150 x_flush,
9151 x_clear_window_mouse_face,
9152 x_get_glyph_overhangs,
9153 x_fix_overlapping_area,
9154 x_draw_fringe_bitmap,
9155 0, /* define_fringe_bitmap */
9156 0, /* destroy_fringe_bitmap */
9157 mac_per_char_metric,
9158 mac_encode_char,
9159 NULL, /* mac_compute_glyph_string_overhangs */
9160 x_draw_glyph_string,
9161 mac_define_frame_cursor,
9162 mac_clear_frame_area,
9163 mac_draw_window_cursor,
9164 mac_draw_vertical_window_border,
9165 mac_shift_glyphs_for_insert
9168 void
9169 mac_initialize ()
9171 rif = &x_redisplay_interface;
9173 clear_frame_hook = x_clear_frame;
9174 ins_del_lines_hook = x_ins_del_lines;
9175 delete_glyphs_hook = x_delete_glyphs;
9176 ring_bell_hook = XTring_bell;
9177 reset_terminal_modes_hook = XTreset_terminal_modes;
9178 set_terminal_modes_hook = XTset_terminal_modes;
9179 update_begin_hook = x_update_begin;
9180 update_end_hook = x_update_end;
9181 set_terminal_window_hook = XTset_terminal_window;
9182 read_socket_hook = XTread_socket;
9183 frame_up_to_date_hook = XTframe_up_to_date;
9184 mouse_position_hook = XTmouse_position;
9185 frame_rehighlight_hook = XTframe_rehighlight;
9186 frame_raise_lower_hook = XTframe_raise_lower;
9188 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9189 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9190 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9191 judge_scroll_bars_hook = XTjudge_scroll_bars;
9193 scroll_region_ok = 1; /* we'll scroll partial frames */
9194 char_ins_del_ok = 1;
9195 line_ins_del_ok = 1; /* we'll just blt 'em */
9196 fast_clear_end_of_line = 1; /* X does this well */
9197 memory_below_frame = 0; /* we don't remember what scrolls
9198 off the bottom */
9199 baud_rate = 19200;
9201 x_noop_count = 0;
9202 last_tool_bar_item = -1;
9203 any_help_event_p = 0;
9205 /* Try to use interrupt input; if we can't, then start polling. */
9206 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9208 #ifdef USE_X_TOOLKIT
9209 XtToolkitInitialize ();
9210 Xt_app_con = XtCreateApplicationContext ();
9211 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9213 /* Install an asynchronous timer that processes Xt timeout events
9214 every 0.1s. This is necessary because some widget sets use
9215 timeouts internally, for example the LessTif menu bar, or the
9216 Xaw3d scroll bar. When Xt timouts aren't processed, these
9217 widgets don't behave normally. */
9219 EMACS_TIME interval;
9220 EMACS_SET_SECS_USECS (interval, 0, 100000);
9221 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9223 #endif
9225 #if USE_TOOLKIT_SCROLL_BARS
9226 xaw3d_arrow_scroll = False;
9227 xaw3d_pick_top = True;
9228 #endif
9230 #if 0
9231 /* Note that there is no real way portable across R3/R4 to get the
9232 original error handler. */
9233 XSetErrorHandler (x_error_handler);
9234 XSetIOErrorHandler (x_io_error_quitter);
9236 /* Disable Window Change signals; they are handled by X events. */
9237 #ifdef SIGWINCH
9238 signal (SIGWINCH, SIG_DFL);
9239 #endif /* ! defined (SIGWINCH) */
9241 signal (SIGPIPE, x_connection_signal);
9242 #endif
9244 BLOCK_INPUT;
9245 mac_initialize_display_info ();
9247 #if TARGET_API_MAC_CARBON
9248 init_required_apple_events ();
9250 init_mac_drag_n_drop ();
9252 #if USE_CARBON_EVENTS
9253 init_service_handler ();
9255 init_quit_char_handler ();
9256 #endif
9258 DisableMenuCommand (NULL, kHICommandQuit);
9260 if (!inhibit_window_system)
9261 MakeMeTheFrontProcess ();
9262 #endif
9263 UNBLOCK_INPUT;
9267 void
9268 syms_of_macterm ()
9270 #if 0
9271 staticpro (&x_error_message_string);
9272 x_error_message_string = Qnil;
9273 #endif
9275 Qmodifier_value = intern ("modifier-value");
9276 Qalt = intern ("alt");
9277 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9278 Qhyper = intern ("hyper");
9279 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9280 Qsuper = intern ("super");
9281 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9283 Fprovide (intern ("mac-carbon"), Qnil);
9285 staticpro (&Qreverse);
9286 Qreverse = intern ("reverse");
9288 staticpro (&x_display_name_list);
9289 x_display_name_list = Qnil;
9291 staticpro (&last_mouse_scroll_bar);
9292 last_mouse_scroll_bar = Qnil;
9294 staticpro (&Qvendor_specific_keysyms);
9295 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9297 staticpro (&last_mouse_press_frame);
9298 last_mouse_press_frame = Qnil;
9300 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9301 staticpro (&Qmac_ready_for_drag_n_drop);
9303 Qbig5 = intern ("big5");
9304 staticpro (&Qbig5);
9306 Qcn_gb = intern ("cn-gb");
9307 staticpro (&Qcn_gb);
9309 Qsjis = intern ("sjis");
9310 staticpro (&Qsjis);
9312 Qeuc_kr = intern ("euc-kr");
9313 staticpro (&Qeuc_kr);
9315 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9316 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9317 x_autoselect_window_p = 0;
9319 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9320 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9321 Vx_toolkit_scroll_bars = Qt;
9323 DEFVAR_BOOL ("x-use-underline-position-properties",
9324 &x_use_underline_position_properties,
9325 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9326 nil means ignore them. If you encounter fonts with bogus
9327 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9328 to 4.1, set this to nil. */);
9329 x_use_underline_position_properties = 0;
9331 staticpro (&last_mouse_motion_frame);
9332 last_mouse_motion_frame = Qnil;
9334 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9335 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9336 Otherwise the option key is used. */);
9337 Vmac_command_key_is_meta = Qt;
9339 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9340 doc: /* Modifier to use for the Mac alt/option key. The value can
9341 be alt, hyper, or super for the respective modifier. If the value is
9342 nil then the key will act as the normal Mac option modifier. */);
9343 Vmac_option_modifier = Qnil;
9345 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9346 doc: /* Non-nil means that the control and meta keys are reversed. This is
9347 useful for non-standard keyboard layouts. */);
9348 Vmac_reverse_ctrl_meta = Qnil;
9350 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9351 &Vmac_emulate_three_button_mouse,
9352 doc: /* t means that when the option-key is held down while pressing the
9353 mouse button, the click will register as mouse-2 and while the
9354 command-key is held down, the click will register as mouse-3.
9355 'reverse means that the the option-key will register for mouse-3
9356 and the command-key will register for mouse-2. nil means that
9357 not emulation should be done and the modifiers should be placed
9358 on the mouse-1 event. */);
9359 Vmac_emulate_three_button_mouse = Qnil;
9361 #if USE_CARBON_EVENTS
9362 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9363 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9364 the right click will be mouse-3.
9365 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9366 Vmac_wheel_button_is_mouse_2 = Qt;
9368 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9369 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9370 Toolbox for processing before Emacs sees it. */);
9371 Vmac_pass_command_to_system = Qt;
9373 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9374 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9375 Toolbox for processing before Emacs sees it. */);
9376 Vmac_pass_control_to_system = Qt;
9377 #endif
9379 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9380 doc: /* One of the Text Encoding Base constant values defined in the
9381 Basic Text Constants section of Inside Macintosh - Text Encoding
9382 Conversion Manager. Its value determines the encoding characters
9383 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9384 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9385 its default value, no conversion takes place. If it is set to
9386 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9387 characters typed on Mac keyboard are first converted into the
9388 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9389 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9390 command, this enables the Mac keyboard to be used to enter non-ASCII
9391 characters directly. */);
9392 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9395 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9396 (do not change this comment) */