(syms_of_macterm) <mac-allow-anti-aliasing>: Doc fix.
[emacs.git] / src / macterm.c
blobebebb129bb8304c997f5974179463190ed41f14f
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
31 #include "macterm.h"
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
37 #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>
72 #include <sys/param.h>
74 #include "keyboard.h"
75 #include "frame.h"
76 #include "dispextern.h"
77 #include "fontset.h"
78 #include "termhooks.h"
79 #include "termopts.h"
80 #include "termchar.h"
81 #include "gnu.h"
82 #include "disptab.h"
83 #include "buffer.h"
84 #include "window.h"
85 #include "intervals.h"
86 #include "composite.h"
87 #include "coding.h"
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
95 : controlKey)
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
100 /* Non-nil means Emacs uses toolkit scroll bars. */
102 Lisp_Object Vx_toolkit_scroll_bars;
104 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
105 Lisp_Object Vmac_use_core_graphics;
108 /* Non-zero means that a HELP_EVENT has been generated since Emacs
109 start. */
111 static int any_help_event_p;
113 /* Non-zero means autoselect window with the mouse cursor. */
115 int x_autoselect_window_p;
117 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
119 int x_use_underline_position_properties;
121 /* Non-zero means draw block and hollow cursor as wide as the glyph
122 under it. For example, if a block cursor is over a tab, it will be
123 drawn as wide as that tab on the display. */
126 /* This is a chain of structures for all the X displays currently in
127 use. */
129 struct x_display_info *x_display_list;
131 /* This is a list of cons cells, each of the form (NAME
132 . FONT-LIST-CACHE), one for each element of x_display_list and in
133 the same order. NAME is the name of the frame. FONT-LIST-CACHE
134 records previous values returned by x-list-fonts. */
136 Lisp_Object x_display_name_list;
138 /* This is display since Mac does not support multiple ones. */
139 struct mac_display_info one_mac_display_info;
141 /* Frame being updated by update_frame. This is declared in term.c.
142 This is set by update_begin and looked at by all the XT functions.
143 It is zero while not inside an update. In that case, the XT
144 functions assume that `selected_frame' is the frame to apply to. */
146 extern struct frame *updating_frame;
148 extern int waiting_for_input;
150 /* This is a frame waiting to be auto-raised, within XTread_socket. */
152 struct frame *pending_autoraise_frame;
154 /* Non-zero means user is interacting with a toolkit scroll bar. */
156 static int toolkit_scroll_bar_interaction;
158 /* Mouse movement.
160 Formerly, we used PointerMotionHintMask (in standard_event_mask)
161 so that we would have to call XQueryPointer after each MotionNotify
162 event to ask for another such event. However, this made mouse tracking
163 slow, and there was a bug that made it eventually stop.
165 Simply asking for MotionNotify all the time seems to work better.
167 In order to avoid asking for motion events and then throwing most
168 of them away or busy-polling the server for mouse positions, we ask
169 the server for pointer motion hints. This means that we get only
170 one event per group of mouse movements. "Groups" are delimited by
171 other kinds of events (focus changes and button clicks, for
172 example), or by XQueryPointer calls; when one of these happens, we
173 get another MotionNotify event the next time the mouse moves. This
174 is at least as efficient as getting motion events when mouse
175 tracking is on, and I suspect only negligibly worse when tracking
176 is off. */
178 /* Where the mouse was last time we reported a mouse event. */
180 static Rect last_mouse_glyph;
181 static Lisp_Object last_mouse_press_frame;
183 /* The scroll bar in which the last X motion event occurred.
185 If the last X motion event occurred in a scroll bar, we set this so
186 XTmouse_position can know whether to report a scroll bar motion or
187 an ordinary motion.
189 If the last X motion event didn't occur in a scroll bar, we set
190 this to Qnil, to tell XTmouse_position to return an ordinary motion
191 event. */
193 static Lisp_Object last_mouse_scroll_bar;
195 /* This is a hack. We would really prefer that XTmouse_position would
196 return the time associated with the position it returns, but there
197 doesn't seem to be any way to wrest the time-stamp from the server
198 along with the position query. So, we just keep track of the time
199 of the last movement we received, and return that in hopes that
200 it's somewhat accurate. */
202 static Time last_mouse_movement_time;
204 struct scroll_bar *tracked_scroll_bar = NULL;
206 /* Incremented by XTread_socket whenever it really tries to read
207 events. */
209 #ifdef __STDC__
210 static int volatile input_signal_count;
211 #else
212 static int input_signal_count;
213 #endif
215 /* Used locally within XTread_socket. */
217 static int x_noop_count;
219 /* Initial values of argv and argc. */
221 extern char **initial_argv;
222 extern int initial_argc;
224 extern Lisp_Object Vcommand_line_args, Vsystem_name;
226 /* Tells if a window manager is present or not. */
228 extern Lisp_Object Vx_no_window_manager;
230 extern int errno;
232 /* A mask of extra modifier bits to put into every keyboard char. */
234 extern int extra_keyboard_modifiers;
236 /* The keysyms to use for the various modifiers. */
238 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
240 static Lisp_Object Qvendor_specific_keysyms;
242 #if 0
243 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
244 #endif
246 extern int inhibit_window_system;
248 #if __MRC__
249 QDGlobals qd; /* QuickDraw global information structure. */
250 #endif
253 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
254 struct mac_display_info *mac_display_info_for_display (Display *);
255 static void x_update_window_end P_ ((struct window *, int, int));
256 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
257 static int x_io_error_quitter P_ ((Display *));
258 int x_catch_errors P_ ((Display *));
259 void x_uncatch_errors P_ ((Display *, int));
260 void x_lower_frame P_ ((struct frame *));
261 void x_scroll_bar_clear P_ ((struct frame *));
262 int x_had_errors_p P_ ((Display *));
263 void x_wm_set_size_hint P_ ((struct frame *, long, int));
264 void x_raise_frame P_ ((struct frame *));
265 void x_set_window_size P_ ((struct frame *, int, int, int));
266 void x_wm_set_window_state P_ ((struct frame *, int));
267 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
268 void mac_initialize P_ ((void));
269 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
270 static int x_compute_min_glyph_bounds P_ ((struct frame *));
271 static void x_update_end P_ ((struct frame *));
272 static void XTframe_up_to_date P_ ((struct frame *));
273 static void XTreassert_line_highlight P_ ((int, int));
274 static void x_change_line_highlight P_ ((int, int, int, int));
275 static void XTset_terminal_modes P_ ((void));
276 static void XTreset_terminal_modes P_ ((void));
277 static void x_clear_frame P_ ((void));
278 static void frame_highlight P_ ((struct frame *));
279 static void frame_unhighlight P_ ((struct frame *));
280 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
281 static void XTframe_rehighlight P_ ((struct frame *));
282 static void x_frame_rehighlight P_ ((struct x_display_info *));
283 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
284 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
285 enum text_cursor_kinds));
287 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
288 static void x_flush P_ ((struct frame *f));
289 static void x_update_begin P_ ((struct frame *));
290 static void x_update_window_begin P_ ((struct window *));
291 static void x_after_update_window_line P_ ((struct glyph_row *));
293 void activate_scroll_bars (FRAME_PTR);
294 void deactivate_scroll_bars (FRAME_PTR);
296 static int is_emacs_window (WindowPtr);
298 int x_bitmap_icon (struct frame *, Lisp_Object);
299 void x_make_frame_visible (struct frame *);
301 extern void window_scroll (Lisp_Object, int, int, int);
303 /* Defined in macmenu.h. */
304 extern void menubar_selection_callback (FRAME_PTR, int);
305 extern void set_frame_menubar (FRAME_PTR, int, int);
307 /* X display function emulation */
309 void
310 XFreePixmap (display, pixmap)
311 Display *display; /* not used */
312 Pixmap pixmap;
314 DisposeGWorld (pixmap);
318 /* Set foreground color for subsequent QuickDraw commands. Assume
319 graphic port has already been set. */
321 static void
322 mac_set_forecolor (unsigned long color)
324 RGBColor fg_color;
326 fg_color.red = RED16_FROM_ULONG (color);
327 fg_color.green = GREEN16_FROM_ULONG (color);
328 fg_color.blue = BLUE16_FROM_ULONG (color);
330 RGBForeColor (&fg_color);
334 /* Set background color for subsequent QuickDraw commands. Assume
335 graphic port has already been set. */
337 static void
338 mac_set_backcolor (unsigned long color)
340 RGBColor bg_color;
342 bg_color.red = RED16_FROM_ULONG (color);
343 bg_color.green = GREEN16_FROM_ULONG (color);
344 bg_color.blue = BLUE16_FROM_ULONG (color);
346 RGBBackColor (&bg_color);
349 /* Set foreground and background color for subsequent QuickDraw
350 commands. Assume that the graphic port has already been set. */
352 static void
353 mac_set_colors (GC gc)
355 mac_set_forecolor (gc->foreground);
356 mac_set_backcolor (gc->background);
359 /* Mac version of XDrawLine. */
361 static void
362 XDrawLine (display, w, gc, x1, y1, x2, y2)
363 Display *display;
364 WindowPtr w;
365 GC gc;
366 int x1, y1, x2, y2;
368 SetPortWindowPort (w);
370 mac_set_colors (gc);
372 MoveTo (x1, y1);
373 LineTo (x2, y2);
376 void
377 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
378 Display *display;
379 Pixmap p;
380 GC gc;
381 int x1, y1, x2, y2;
383 CGrafPtr old_port;
384 GDHandle old_gdh;
386 GetGWorld (&old_port, &old_gdh);
387 SetGWorld (p, NULL);
389 mac_set_colors (gc);
391 LockPixels (GetGWorldPixMap (p));
392 MoveTo (x1, y1);
393 LineTo (x2, y2);
394 UnlockPixels (GetGWorldPixMap (p));
396 SetGWorld (old_port, old_gdh);
399 /* Mac version of XClearArea. */
401 void
402 XClearArea (display, w, x, y, width, height, exposures)
403 Display *display;
404 WindowPtr w;
405 int x, y;
406 unsigned int width, height;
407 int exposures;
409 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
410 Rect r;
411 XGCValues xgc;
413 xgc.foreground = mwp->x_compatible.foreground_pixel;
414 xgc.background = mwp->x_compatible.background_pixel;
416 SetPortWindowPort (w);
418 mac_set_colors (&xgc);
419 SetRect (&r, x, y, x + width, y + height);
421 EraseRect (&r);
424 /* Mac version of XClearWindow. */
426 static void
427 XClearWindow (display, w)
428 Display *display;
429 WindowPtr w;
431 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
432 XGCValues xgc;
434 xgc.foreground = mwp->x_compatible.foreground_pixel;
435 xgc.background = mwp->x_compatible.background_pixel;
437 SetPortWindowPort (w);
439 mac_set_colors (&xgc);
441 #if TARGET_API_MAC_CARBON
443 Rect r;
445 GetWindowPortBounds (w, &r);
446 EraseRect (&r);
448 #else /* not TARGET_API_MAC_CARBON */
449 EraseRect (&(w->portRect));
450 #endif /* not TARGET_API_MAC_CARBON */
454 /* Mac replacement for XCopyArea. */
456 static void
457 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
458 Display *display;
459 WindowPtr w;
460 GC gc;
461 int x, y, width, height;
462 unsigned short *bits;
463 int overlay_p;
465 BitMap bitmap;
466 Rect r;
468 bitmap.rowBytes = sizeof(unsigned short);
469 bitmap.baseAddr = (char *)bits;
470 SetRect (&(bitmap.bounds), 0, 0, width, height);
472 SetPortWindowPort (w);
474 mac_set_colors (gc);
475 SetRect (&r, x, y, x + width, y + height);
477 #if TARGET_API_MAC_CARBON
478 LockPortBits (GetWindowPort (w));
479 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
480 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
481 UnlockPortBits (GetWindowPort (w));
482 #else /* not TARGET_API_MAC_CARBON */
483 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
484 overlay_p ? srcOr : srcCopy, 0);
485 #endif /* not TARGET_API_MAC_CARBON */
489 /* Mac replacement for XSetClipRectangles. */
491 static void
492 mac_set_clip_rectangle (display, w, r)
493 Display *display;
494 WindowPtr w;
495 Rect *r;
497 SetPortWindowPort (w);
499 ClipRect (r);
503 /* Mac replacement for XSetClipMask. */
505 static void
506 mac_reset_clipping (display, w)
507 Display *display;
508 WindowPtr w;
510 Rect r;
512 SetPortWindowPort (w);
514 SetRect (&r, -32767, -32767, 32767, 32767);
515 ClipRect (&r);
519 /* Mac replacement for XCreateBitmapFromBitmapData. */
521 static void
522 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
523 BitMap *bitmap;
524 char *bits;
525 int w, h;
527 static unsigned char swap_nibble[16]
528 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
529 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
530 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
531 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
532 int i, j, w1;
533 char *p;
535 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
536 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
537 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
538 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
539 for (i = 0; i < h; i++)
541 p = bitmap->baseAddr + i * bitmap->rowBytes;
542 for (j = 0; j < w1; j++)
544 /* Bitswap XBM bytes to match how Mac does things. */
545 unsigned char c = *bits++;
546 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
547 | (swap_nibble[(c>>4) & 0xf]));;
551 SetRect (&(bitmap->bounds), 0, 0, w, h);
555 static void
556 mac_free_bitmap (bitmap)
557 BitMap *bitmap;
559 xfree (bitmap->baseAddr);
563 Pixmap
564 XCreatePixmap (display, w, width, height, depth)
565 Display *display; /* not used */
566 WindowPtr w;
567 unsigned int width, height;
568 unsigned int depth;
570 Pixmap pixmap;
571 Rect r;
572 QDErr err;
574 SetPortWindowPort (w);
576 SetRect (&r, 0, 0, width, height);
577 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
578 if (err != noErr)
579 return NULL;
580 return pixmap;
584 Pixmap
585 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
586 Display *display; /* not used */
587 WindowPtr w;
588 char *data;
589 unsigned int width, height;
590 unsigned long fg, bg;
591 unsigned int depth; /* not used */
593 Pixmap pixmap;
594 BitMap bitmap;
595 CGrafPtr old_port;
596 GDHandle old_gdh;
598 pixmap = XCreatePixmap (display, w, width, height, depth);
599 if (pixmap == NULL)
600 return NULL;
602 GetGWorld (&old_port, &old_gdh);
603 SetGWorld (pixmap, NULL);
604 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
605 mac_set_forecolor (fg);
606 mac_set_backcolor (bg);
607 LockPixels (GetGWorldPixMap (pixmap));
608 #if TARGET_API_MAC_CARBON
609 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
610 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
611 #else /* not TARGET_API_MAC_CARBON */
612 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
613 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
614 #endif /* not TARGET_API_MAC_CARBON */
615 UnlockPixels (GetGWorldPixMap (pixmap));
616 SetGWorld (old_port, old_gdh);
617 mac_free_bitmap (&bitmap);
619 return pixmap;
623 /* Mac replacement for XFillRectangle. */
625 static void
626 XFillRectangle (display, w, gc, x, y, width, height)
627 Display *display;
628 WindowPtr w;
629 GC gc;
630 int x, y;
631 unsigned int width, height;
633 Rect r;
635 SetPortWindowPort (w);
637 mac_set_colors (gc);
638 SetRect (&r, x, y, x + width, y + height);
640 PaintRect (&r); /* using foreground color of gc */
644 #if 0 /* TODO: figure out if we need to do this on Mac. */
645 static void
646 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
647 Display *display;
648 Pixmap p;
649 GC gc;
650 int x, y;
651 unsigned int width, height;
653 CGrafPtr old_port;
654 GDHandle old_gdh;
655 Rect r;
657 GetGWorld (&old_port, &old_gdh);
658 SetGWorld (p, NULL);
659 mac_set_colors (gc);
660 SetRect (&r, x, y, x + width, y + height);
662 LockPixels (GetGWorldPixMap (p));
663 PaintRect (&r); /* using foreground color of gc */
664 UnlockPixels (GetGWorldPixMap (p));
666 SetGWorld (old_port, old_gdh);
668 #endif
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 #if 0 /* TODO: figure out if we need to do this on Mac. */
693 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
695 static void
696 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
697 Display *display;
698 Pixmap p;
699 GC gc;
700 int x, y;
701 unsigned int width, height;
703 CGrafPtr old_port;
704 GDHandle old_gdh;
705 Rect r;
707 GetGWorld (&old_port, &old_gdh);
708 SetGWorld (p, NULL);
709 mac_set_colors (gc);
710 SetRect (&r, x, y, x + width + 1, y + height + 1);
712 LockPixels (GetGWorldPixMap (p));
713 FrameRect (&r); /* using foreground color of gc */
714 UnlockPixels (GetGWorldPixMap (p));
716 SetGWorld (old_port, old_gdh);
718 #endif
721 static void
722 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
723 bytes_per_char)
724 Display *display;
725 WindowPtr w;
726 GC gc;
727 int x, y;
728 char *buf;
729 int nchars, mode, bytes_per_char;
731 SetPortWindowPort (w);
732 #ifdef MAC_OS_X_VERSION_10_2
733 UInt32 textFlags, savedFlags;
734 if (!NILP(Vmac_use_core_graphics)) {
735 textFlags = kQDUseCGTextRendering;
736 savedFlags = SwapQDTextFlags(textFlags);
738 #endif
740 mac_set_colors (gc);
742 TextFont (gc->font->mac_fontnum);
743 TextSize (gc->font->mac_fontsize);
744 TextFace (gc->font->mac_fontface);
745 TextMode (mode);
747 MoveTo (x, y);
748 DrawText (buf, 0, nchars * bytes_per_char);
749 #ifdef MAC_OS_X_VERSION_10_2
750 if (!NILP(Vmac_use_core_graphics))
751 SwapQDTextFlags(savedFlags);
752 #endif
756 /* Mac replacement for XDrawString. */
758 static void
759 XDrawString (display, w, gc, x, y, buf, nchars)
760 Display *display;
761 WindowPtr w;
762 GC gc;
763 int x, y;
764 char *buf;
765 int nchars;
767 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
771 /* Mac replacement for XDrawString16. */
773 static void
774 XDrawString16 (display, w, gc, x, y, buf, nchars)
775 Display *display;
776 WindowPtr w;
777 GC gc;
778 int x, y;
779 XChar2b *buf;
780 int nchars;
782 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
787 /* Mac replacement for XDrawImageString. */
789 static void
790 XDrawImageString (display, w, gc, x, y, buf, nchars)
791 Display *display;
792 WindowPtr w;
793 GC gc;
794 int x, y;
795 char *buf;
796 int nchars;
798 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
802 /* Mac replacement for XDrawString16. */
804 static void
805 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
806 Display *display;
807 WindowPtr w;
808 GC gc;
809 int x, y;
810 XChar2b *buf;
811 int nchars;
813 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
818 /* Mac replacement for XCopyArea: dest must be window. */
820 static void
821 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
822 dest_y)
823 Display *display;
824 Pixmap src;
825 WindowPtr dest;
826 GC gc;
827 int src_x, src_y;
828 unsigned int width, height;
829 int dest_x, dest_y;
831 Rect src_r, dest_r;
833 SetPortWindowPort (dest);
835 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
836 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
838 ForeColor (blackColor);
839 BackColor (whiteColor);
841 LockPixels (GetGWorldPixMap (src));
842 #if TARGET_API_MAC_CARBON
843 LockPortBits (GetWindowPort (dest));
844 CopyBits (GetPortBitMapForCopyBits (src),
845 GetPortBitMapForCopyBits (GetWindowPort (dest)),
846 &src_r, &dest_r, srcCopy, 0);
847 UnlockPortBits (GetWindowPort (dest));
848 #else /* not TARGET_API_MAC_CARBON */
849 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
850 &src_r, &dest_r, srcCopy, 0);
851 #endif /* not TARGET_API_MAC_CARBON */
852 UnlockPixels (GetGWorldPixMap (src));
856 static void
857 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
858 width, height, dest_x, dest_y)
859 Display *display;
860 Pixmap src, mask;
861 WindowPtr dest;
862 GC gc;
863 int src_x, src_y;
864 unsigned int width, height;
865 int dest_x, dest_y;
867 Rect src_r, dest_r;
869 SetPortWindowPort (dest);
871 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
872 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
874 ForeColor (blackColor);
875 BackColor (whiteColor);
877 LockPixels (GetGWorldPixMap (src));
878 LockPixels (GetGWorldPixMap (mask));
879 #if TARGET_API_MAC_CARBON
880 LockPortBits (GetWindowPort (dest));
881 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
882 GetPortBitMapForCopyBits (GetWindowPort (dest)),
883 &src_r, &src_r, &dest_r);
884 UnlockPortBits (GetWindowPort (dest));
885 #else /* not TARGET_API_MAC_CARBON */
886 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
887 &(dest->portBits), &src_r, &src_r, &dest_r);
888 #endif /* not TARGET_API_MAC_CARBON */
889 UnlockPixels (GetGWorldPixMap (mask));
890 UnlockPixels (GetGWorldPixMap (src));
894 #if 0
895 /* Convert a pair of local coordinates to global (screen) coordinates.
896 Assume graphic port has been properly set. */
897 static void
898 local_to_global_coord (short *h, short *v)
900 Point p;
902 p.h = *h;
903 p.v = *v;
905 LocalToGlobal (&p);
907 *h = p.h;
908 *v = p.v;
910 #endif
912 /* Mac replacement for XCopyArea: used only for scrolling. */
914 static void
915 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
916 Display *display;
917 WindowPtr w;
918 GC gc;
919 int src_x, src_y;
920 unsigned int width, height;
921 int dest_x, dest_y;
923 #if TARGET_API_MAC_CARBON
924 Rect src_r;
925 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
927 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
928 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
929 kScrollWindowNoOptions, dummy);
930 DisposeRgn (dummy);
931 #else /* not TARGET_API_MAC_CARBON */
932 Rect src_r, dest_r;
934 SetPort (w);
935 #if 0
936 mac_set_colors (gc);
937 #endif
939 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
940 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
942 #if 0
943 /* Need to use global coordinates and screenBits since src and dest
944 areas overlap in general. */
945 local_to_global_coord (&src_r.left, &src_r.top);
946 local_to_global_coord (&src_r.right, &src_r.bottom);
947 local_to_global_coord (&dest_r.left, &dest_r.top);
948 local_to_global_coord (&dest_r.right, &dest_r.bottom);
950 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
951 #else
952 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
953 color mapping in CopyBits. Otherwise, it will be slow. */
954 ForeColor (blackColor);
955 BackColor (whiteColor);
956 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
958 mac_set_colors (gc);
959 #endif
960 #endif /* not TARGET_API_MAC_CARBON */
964 #if 0 /* TODO: figure out if we need to do this on Mac. */
965 /* Mac replacement for XCopyArea: dest must be Pixmap. */
967 static void
968 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
969 dest_x, dest_y)
970 Display *display;
971 Pixmap src, dest;
972 GC gc;
973 int src_x, src_y;
974 unsigned int width, height;
975 int dest_x, dest_y;
977 CGrafPtr old_port;
978 GDHandle old_gdh;
979 Rect src_r, dest_r;
981 GetGWorld (&old_port, &old_gdh);
982 SetGWorld (dest, NULL);
983 ForeColor (blackColor);
984 BackColor (whiteColor);
986 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
987 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
989 LockPixels (GetGWorldPixMap (src));
990 LockPixels (GetGWorldPixMap (dest));
991 #if TARGET_API_MAC_CARBON
992 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
993 &src_r, &dest_r, srcCopy, 0);
994 #else /* not TARGET_API_MAC_CARBON */
995 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
996 &src_r, &dest_r, srcCopy, 0);
997 #endif /* not TARGET_API_MAC_CARBON */
998 UnlockPixels (GetGWorldPixMap (dest));
999 UnlockPixels (GetGWorldPixMap (src));
1001 SetGWorld (old_port, old_gdh);
1005 static void
1006 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
1007 width, height, dest_x, dest_y)
1008 Display *display;
1009 Pixmap src, mask, dest;
1010 GC gc;
1011 int src_x, src_y;
1012 unsigned int width, height;
1013 int dest_x, dest_y;
1015 CGrafPtr old_port;
1016 GDHandle old_gdh;
1017 Rect src_r, dest_r;
1019 GetGWorld (&old_port, &old_gdh);
1020 SetGWorld (dest, NULL);
1021 ForeColor (blackColor);
1022 BackColor (whiteColor);
1024 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1025 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1027 LockPixels (GetGWorldPixMap (src));
1028 LockPixels (GetGWorldPixMap (mask));
1029 LockPixels (GetGWorldPixMap (dest));
1030 #if TARGET_API_MAC_CARBON
1031 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1032 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1033 #else /* not TARGET_API_MAC_CARBON */
1034 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1035 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1036 #endif /* not TARGET_API_MAC_CARBON */
1037 UnlockPixels (GetGWorldPixMap (dest));
1038 UnlockPixels (GetGWorldPixMap (mask));
1039 UnlockPixels (GetGWorldPixMap (src));
1041 SetGWorld (old_port, old_gdh);
1043 #endif
1046 /* Mac replacement for XChangeGC. */
1048 static void
1049 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1050 XGCValues *xgcv)
1052 if (mask & GCForeground)
1053 gc->foreground = xgcv->foreground;
1054 if (mask & GCBackground)
1055 gc->background = xgcv->background;
1056 if (mask & GCFont)
1057 gc->font = xgcv->font;
1061 /* Mac replacement for XCreateGC. */
1063 XGCValues *
1064 XCreateGC (void * ignore, Window window, unsigned long mask,
1065 XGCValues *xgcv)
1067 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1068 bzero (gc, sizeof (XGCValues));
1070 XChangeGC (ignore, gc, mask, xgcv);
1072 return gc;
1076 /* Used in xfaces.c. */
1078 void
1079 XFreeGC (display, gc)
1080 Display *display;
1081 GC gc;
1083 xfree (gc);
1087 /* Mac replacement for XGetGCValues. */
1089 static void
1090 XGetGCValues (void* ignore, XGCValues *gc,
1091 unsigned long mask, XGCValues *xgcv)
1093 XChangeGC (ignore, xgcv, mask, gc);
1097 /* Mac replacement for XSetForeground. */
1099 void
1100 XSetForeground (display, gc, color)
1101 Display *display;
1102 GC gc;
1103 unsigned long color;
1105 gc->foreground = color;
1109 /* Mac replacement for XSetBackground. */
1111 void
1112 XSetBackground (display, gc, color)
1113 Display *display;
1114 GC gc;
1115 unsigned long color;
1117 gc->background = color;
1121 /* Mac replacement for XSetWindowBackground. */
1123 void
1124 XSetWindowBackground (display, w, color)
1125 Display *display;
1126 WindowPtr w;
1127 unsigned long color;
1129 #if !TARGET_API_MAC_CARBON
1130 AuxWinHandle aw_handle;
1131 CTabHandle ctab_handle;
1132 ColorSpecPtr ct_table;
1133 short ct_size;
1134 #endif
1135 RGBColor bg_color;
1137 bg_color.red = RED16_FROM_ULONG (color);
1138 bg_color.green = GREEN16_FROM_ULONG (color);
1139 bg_color.blue = BLUE16_FROM_ULONG (color);
1141 #if TARGET_API_MAC_CARBON
1142 SetWindowContentColor (w, &bg_color);
1143 #else
1144 if (GetAuxWin (w, &aw_handle))
1146 ctab_handle = (*aw_handle)->awCTable;
1147 HandToHand ((Handle *) &ctab_handle);
1148 ct_table = (*ctab_handle)->ctTable;
1149 ct_size = (*ctab_handle)->ctSize;
1150 while (ct_size > -1)
1152 if (ct_table->value == 0)
1154 ct_table->rgb = bg_color;
1155 CTabChanged (ctab_handle);
1156 SetWinColor (w, (WCTabHandle) ctab_handle);
1158 ct_size--;
1161 #endif
1165 /* Mac replacement for XSetFont. */
1167 static void
1168 XSetFont (display, gc, font)
1169 Display *display;
1170 GC gc;
1171 XFontStruct *font;
1173 gc->font = font;
1177 static void
1178 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1179 int *direction,int *font_ascent,
1180 int *font_descent, XCharStruct *cs)
1182 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1186 /* x_sync is a no-op on Mac. */
1187 void
1188 x_sync (f)
1189 void *f;
1194 /* Flush display of frame F, or of all frames if F is null. */
1196 static void
1197 x_flush (f)
1198 struct frame *f;
1200 #if TARGET_API_MAC_CARBON
1201 BLOCK_INPUT;
1202 if (f)
1203 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1204 else
1205 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1206 UNBLOCK_INPUT;
1207 #endif
1211 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1212 Calls to XFlush should be unnecessary because the X output buffer
1213 is flushed automatically as needed by calls to XPending,
1214 XNextEvent, or XWindowEvent according to the XFlush man page.
1215 XTread_socket calls XPending. Removing XFlush improves
1216 performance. */
1218 #define XFlush(DISPLAY) (void) 0
1221 /* Return the struct mac_display_info corresponding to DPY. There's
1222 only one. */
1224 struct mac_display_info *
1225 mac_display_info_for_display (dpy)
1226 Display *dpy;
1228 return &one_mac_display_info;
1233 /***********************************************************************
1234 Starting and ending an update
1235 ***********************************************************************/
1237 /* Start an update of frame F. This function is installed as a hook
1238 for update_begin, i.e. it is called when update_begin is called.
1239 This function is called prior to calls to x_update_window_begin for
1240 each window being updated. */
1242 static void
1243 x_update_begin (f)
1244 struct frame *f;
1246 #if TARGET_API_MAC_CARBON
1247 /* During update of a frame, availability of input events is
1248 periodically checked with ReceiveNextEvent if
1249 redisplay-dont-pause is nil. That normally flushes window buffer
1250 changes for every check, and thus screen update looks waving even
1251 if no input is available. So we disable screen updates during
1252 update of a frame. */
1253 BLOCK_INPUT;
1254 DisableScreenUpdates ();
1255 UNBLOCK_INPUT;
1256 #endif
1260 /* Start update of window W. Set the global variable updated_window
1261 to the window being updated and set output_cursor to the cursor
1262 position of W. */
1264 static void
1265 x_update_window_begin (w)
1266 struct window *w;
1268 struct frame *f = XFRAME (WINDOW_FRAME (w));
1269 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1271 updated_window = w;
1272 set_output_cursor (&w->cursor);
1274 BLOCK_INPUT;
1276 if (f == display_info->mouse_face_mouse_frame)
1278 /* Don't do highlighting for mouse motion during the update. */
1279 display_info->mouse_face_defer = 1;
1281 /* If F needs to be redrawn, simply forget about any prior mouse
1282 highlighting. */
1283 if (FRAME_GARBAGED_P (f))
1284 display_info->mouse_face_window = Qnil;
1286 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1287 their mouse_face_p flag set, which means that they are always
1288 unequal to rows in a desired matrix which never have that
1289 flag set. So, rows containing mouse-face glyphs are never
1290 scrolled, and we don't have to switch the mouse highlight off
1291 here to prevent it from being scrolled. */
1293 /* Can we tell that this update does not affect the window
1294 where the mouse highlight is? If so, no need to turn off.
1295 Likewise, don't do anything if the frame is garbaged;
1296 in that case, the frame's current matrix that we would use
1297 is all wrong, and we will redisplay that line anyway. */
1298 if (!NILP (display_info->mouse_face_window)
1299 && w == XWINDOW (display_info->mouse_face_window))
1301 int i;
1303 for (i = 0; i < w->desired_matrix->nrows; ++i)
1304 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1305 break;
1307 if (i < w->desired_matrix->nrows)
1308 clear_mouse_face (display_info);
1310 #endif /* 0 */
1313 UNBLOCK_INPUT;
1317 /* Draw a vertical window border from (x,y0) to (x,y1) */
1319 static void
1320 mac_draw_vertical_window_border (w, x, y0, y1)
1321 struct window *w;
1322 int x, y0, y1;
1324 struct frame *f = XFRAME (WINDOW_FRAME (w));
1326 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1327 f->output_data.mac->normal_gc, x, y0, x, y1);
1331 /* End update of window W (which is equal to updated_window).
1333 Draw vertical borders between horizontally adjacent windows, and
1334 display W's cursor if CURSOR_ON_P is non-zero.
1336 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1337 glyphs in mouse-face were overwritten. In that case we have to
1338 make sure that the mouse-highlight is properly redrawn.
1340 W may be a menu bar pseudo-window in case we don't have X toolkit
1341 support. Such windows don't have a cursor, so don't display it
1342 here. */
1344 static void
1345 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1346 struct window *w;
1347 int cursor_on_p, mouse_face_overwritten_p;
1349 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1351 if (!w->pseudo_window_p)
1353 BLOCK_INPUT;
1355 if (cursor_on_p)
1356 display_and_set_cursor (w, 1, output_cursor.hpos,
1357 output_cursor.vpos,
1358 output_cursor.x, output_cursor.y);
1360 if (draw_window_fringes (w, 1))
1361 x_draw_vertical_border (w);
1363 UNBLOCK_INPUT;
1366 /* If a row with mouse-face was overwritten, arrange for
1367 XTframe_up_to_date to redisplay the mouse highlight. */
1368 if (mouse_face_overwritten_p)
1370 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1371 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1372 dpyinfo->mouse_face_window = Qnil;
1375 #if 0
1376 /* Unhide the caret. This won't actually show the cursor, unless it
1377 was visible before the corresponding call to HideCaret in
1378 x_update_window_begin. */
1379 if (w32_use_visible_system_caret)
1380 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1381 #endif
1383 updated_window = NULL;
1387 /* End update of frame F. This function is installed as a hook in
1388 update_end. */
1390 static void
1391 x_update_end (f)
1392 struct frame *f;
1394 /* Mouse highlight may be displayed again. */
1395 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1397 BLOCK_INPUT;
1398 /* Reset the background color of Mac OS Window to that of the frame after
1399 update so that it is used by Mac Toolbox to clear the update region before
1400 an update event is generated. */
1401 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1403 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1405 #if TARGET_API_MAC_CARBON
1406 EnableScreenUpdates ();
1407 #endif
1408 XFlush (FRAME_MAC_DISPLAY (f));
1409 UNBLOCK_INPUT;
1413 /* This function is called from various places in xdisp.c whenever a
1414 complete update has been performed. The global variable
1415 updated_window is not available here. */
1417 static void
1418 XTframe_up_to_date (f)
1419 struct frame *f;
1421 if (FRAME_MAC_P (f))
1423 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1425 if (dpyinfo->mouse_face_deferred_gc
1426 || f == dpyinfo->mouse_face_mouse_frame)
1428 BLOCK_INPUT;
1429 if (dpyinfo->mouse_face_mouse_frame)
1430 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1431 dpyinfo->mouse_face_mouse_x,
1432 dpyinfo->mouse_face_mouse_y);
1433 dpyinfo->mouse_face_deferred_gc = 0;
1434 UNBLOCK_INPUT;
1440 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1441 arrow bitmaps, or clear the fringes if no bitmaps are required
1442 before DESIRED_ROW is made current. The window being updated is
1443 found in updated_window. This function is called from
1444 update_window_line only if it is known that there are differences
1445 between bitmaps to be drawn between current row and DESIRED_ROW. */
1447 static void
1448 x_after_update_window_line (desired_row)
1449 struct glyph_row *desired_row;
1451 struct window *w = updated_window;
1452 struct frame *f;
1453 int width, height;
1455 xassert (w);
1457 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1458 desired_row->redraw_fringe_bitmaps_p = 1;
1460 /* When a window has disappeared, make sure that no rest of
1461 full-width rows stays visible in the internal border. Could
1462 check here if updated_window is the leftmost/rightmost window,
1463 but I guess it's not worth doing since vertically split windows
1464 are almost never used, internal border is rarely set, and the
1465 overhead is very small. */
1466 if (windows_or_buffers_changed
1467 && desired_row->full_width_p
1468 && (f = XFRAME (w->frame),
1469 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1470 width != 0)
1471 && (height = desired_row->visible_height,
1472 height > 0))
1474 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1475 /* Internal border is drawn below the tool bar. */
1476 if (WINDOWP (f->tool_bar_window)
1477 && w == XWINDOW (f->tool_bar_window))
1478 y -= width;
1480 BLOCK_INPUT;
1482 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1483 0, y, width, height, 0);
1484 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1485 FRAME_PIXEL_WIDTH (f) - width, y,
1486 width, height, 0);
1488 UNBLOCK_INPUT;
1493 /* Draw the bitmap WHICH in one of the left or right fringes of
1494 window W. ROW is the glyph row for which to display the bitmap; it
1495 determines the vertical position at which the bitmap has to be
1496 drawn. */
1498 static void
1499 x_draw_fringe_bitmap (w, row, p)
1500 struct window *w;
1501 struct glyph_row *row;
1502 struct draw_fringe_bitmap_params *p;
1504 struct frame *f = XFRAME (WINDOW_FRAME (w));
1505 Display *display = FRAME_MAC_DISPLAY (f);
1506 WindowPtr window = FRAME_MAC_WINDOW (f);
1507 XGCValues gcv;
1508 GC gc = f->output_data.mac->normal_gc;
1509 struct face *face = p->face;
1510 int rowY;
1512 /* Must clip because of partially visible lines. */
1513 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1514 if (p->y < rowY)
1516 /* Adjust position of "bottom aligned" bitmap on partially
1517 visible last row. */
1518 int oldY = row->y;
1519 int oldVH = row->visible_height;
1520 row->visible_height = p->h;
1521 row->y -= rowY - p->y;
1522 x_clip_to_row (w, row, -1, gc);
1523 row->y = oldY;
1524 row->visible_height = oldVH;
1526 else
1527 x_clip_to_row (w, row, -1, gc);
1529 if (p->bx >= 0 && !p->overlay_p)
1531 XGCValues gcv;
1532 gcv.foreground = face->background;
1534 #if 0 /* MAC_TODO: stipple */
1535 /* In case the same realized face is used for fringes and
1536 for something displayed in the text (e.g. face `region' on
1537 mono-displays, the fill style may have been changed to
1538 FillSolid in x_draw_glyph_string_background. */
1539 if (face->stipple)
1540 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1541 else
1542 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1543 #endif
1545 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1546 &gcv,
1547 p->bx, p->by, p->nx, p->ny);
1549 #if 0 /* MAC_TODO: stipple */
1550 if (!face->stipple)
1551 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1552 #endif
1555 if (p->which)
1557 unsigned short *bits = p->bits + p->dh;
1559 gcv.foreground = (p->cursor_p
1560 ? (p->overlay_p ? face->background
1561 : f->output_data.mac->cursor_pixel)
1562 : face->foreground);
1563 gcv.background = face->background;
1565 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1566 p->wd, p->h, bits, p->overlay_p);
1569 mac_reset_clipping (display, window);
1573 /* This is called when starting Emacs and when restarting after
1574 suspend. When starting Emacs, no window is mapped. And nothing
1575 must be done to Emacs's own window if it is suspended (though that
1576 rarely happens). */
1578 static void
1579 XTset_terminal_modes ()
1583 /* This is called when exiting or suspending Emacs. Exiting will make
1584 the windows go away, and suspending requires no action. */
1586 static void
1587 XTreset_terminal_modes ()
1592 /***********************************************************************
1593 Display Iterator
1594 ***********************************************************************/
1596 /* Function prototypes of this page. */
1598 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1599 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1602 /* Return a pointer to per-char metric information in FONT of a
1603 character pointed by B which is a pointer to an XChar2b. */
1605 #define PER_CHAR_METRIC(font, b) \
1606 ((font)->per_char \
1607 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1608 + (((font)->min_byte1 || (font)->max_byte1) \
1609 ? (((b)->byte1 - (font)->min_byte1) \
1610 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1611 : 0)) \
1612 : &((font)->max_bounds))
1615 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1616 is not contained in the font. */
1618 static INLINE XCharStruct *
1619 x_per_char_metric (font, char2b)
1620 XFontStruct *font;
1621 XChar2b *char2b;
1623 /* The result metric information. */
1624 XCharStruct *pcm = NULL;
1626 xassert (font && char2b);
1628 if (font->per_char != NULL)
1630 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1632 /* min_char_or_byte2 specifies the linear character index
1633 corresponding to the first element of the per_char array,
1634 max_char_or_byte2 is the index of the last character. A
1635 character with non-zero CHAR2B->byte1 is not in the font.
1636 A character with byte2 less than min_char_or_byte2 or
1637 greater max_char_or_byte2 is not in the font. */
1638 if (char2b->byte1 == 0
1639 && char2b->byte2 >= font->min_char_or_byte2
1640 && char2b->byte2 <= font->max_char_or_byte2)
1641 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1643 else
1645 /* If either min_byte1 or max_byte1 are nonzero, both
1646 min_char_or_byte2 and max_char_or_byte2 are less than
1647 256, and the 2-byte character index values corresponding
1648 to the per_char array element N (counting from 0) are:
1650 byte1 = N/D + min_byte1
1651 byte2 = N\D + min_char_or_byte2
1653 where:
1655 D = max_char_or_byte2 - min_char_or_byte2 + 1
1656 / = integer division
1657 \ = integer modulus */
1658 if (char2b->byte1 >= font->min_byte1
1659 && char2b->byte1 <= font->max_byte1
1660 && char2b->byte2 >= font->min_char_or_byte2
1661 && char2b->byte2 <= font->max_char_or_byte2)
1663 pcm = (font->per_char
1664 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1665 * (char2b->byte1 - font->min_byte1))
1666 + (char2b->byte2 - font->min_char_or_byte2));
1670 else
1672 /* If the per_char pointer is null, all glyphs between the first
1673 and last character indexes inclusive have the same
1674 information, as given by both min_bounds and max_bounds. */
1675 if (char2b->byte2 >= font->min_char_or_byte2
1676 && char2b->byte2 <= font->max_char_or_byte2)
1677 pcm = &font->max_bounds;
1680 return ((pcm == NULL
1681 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1682 ? NULL : pcm);
1685 /* RIF:
1688 static XCharStruct *
1689 mac_per_char_metric (font, char2b, font_type)
1690 XFontStruct *font;
1691 XChar2b *char2b;
1692 int font_type;
1694 return x_per_char_metric (font, char2b);
1697 /* RIF:
1698 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1699 the two-byte form of C. Encoding is returned in *CHAR2B. */
1701 static int
1702 mac_encode_char (c, char2b, font_info, two_byte_p)
1703 int c;
1704 XChar2b *char2b;
1705 struct font_info *font_info;
1706 int *two_byte_p;
1708 int charset = CHAR_CHARSET (c);
1709 XFontStruct *font = font_info->font;
1711 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1712 This may be either a program in a special encoder language or a
1713 fixed encoding. */
1714 if (font_info->font_encoder)
1716 /* It's a program. */
1717 struct ccl_program *ccl = font_info->font_encoder;
1719 if (CHARSET_DIMENSION (charset) == 1)
1721 ccl->reg[0] = charset;
1722 ccl->reg[1] = char2b->byte2;
1724 else
1726 ccl->reg[0] = charset;
1727 ccl->reg[1] = char2b->byte1;
1728 ccl->reg[2] = char2b->byte2;
1731 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1733 /* We assume that MSBs are appropriately set/reset by CCL
1734 program. */
1735 if (font->max_byte1 == 0) /* 1-byte font */
1736 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1737 else
1738 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1740 else if (font_info->encoding[charset])
1742 /* Fixed encoding scheme. See fontset.h for the meaning of the
1743 encoding numbers. */
1744 int enc = font_info->encoding[charset];
1746 if ((enc == 1 || enc == 2)
1747 && CHARSET_DIMENSION (charset) == 2)
1748 char2b->byte1 |= 0x80;
1750 if (enc == 1 || enc == 3)
1751 char2b->byte2 |= 0x80;
1753 if (enc == 4)
1755 int sjis1, sjis2;
1757 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1758 char2b->byte1 = sjis1;
1759 char2b->byte2 = sjis2;
1763 if (two_byte_p)
1764 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1766 return FONT_TYPE_UNKNOWN;
1771 /***********************************************************************
1772 Glyph display
1773 ***********************************************************************/
1776 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1777 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1778 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1779 int));
1780 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1781 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1782 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1783 static void x_draw_glyph_string P_ ((struct glyph_string *));
1784 static void x_set_cursor_gc P_ ((struct glyph_string *));
1785 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1786 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1787 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1788 unsigned long *, double, int));*/
1789 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1790 double, int, unsigned long));
1791 static void x_setup_relief_colors P_ ((struct glyph_string *));
1792 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1793 static void x_draw_image_relief P_ ((struct glyph_string *));
1794 static void x_draw_image_foreground P_ ((struct glyph_string *));
1795 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1796 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1797 int, int, int));
1798 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1799 int, int, int, int, int, int,
1800 Rect *));
1801 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1802 int, int, int, Rect *));
1804 #if GLYPH_DEBUG
1805 static void x_check_font P_ ((struct frame *, XFontStruct *));
1806 #endif
1809 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1810 face. */
1812 static void
1813 x_set_cursor_gc (s)
1814 struct glyph_string *s;
1816 if (s->font == FRAME_FONT (s->f)
1817 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1818 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1819 && !s->cmp)
1820 s->gc = s->f->output_data.mac->cursor_gc;
1821 else
1823 /* Cursor on non-default face: must merge. */
1824 XGCValues xgcv;
1825 unsigned long mask;
1827 xgcv.background = s->f->output_data.mac->cursor_pixel;
1828 xgcv.foreground = s->face->background;
1830 /* If the glyph would be invisible, try a different foreground. */
1831 if (xgcv.foreground == xgcv.background)
1832 xgcv.foreground = s->face->foreground;
1833 if (xgcv.foreground == xgcv.background)
1834 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1835 if (xgcv.foreground == xgcv.background)
1836 xgcv.foreground = s->face->foreground;
1838 /* Make sure the cursor is distinct from text in this face. */
1839 if (xgcv.background == s->face->background
1840 && xgcv.foreground == s->face->foreground)
1842 xgcv.background = s->face->foreground;
1843 xgcv.foreground = s->face->background;
1846 IF_DEBUG (x_check_font (s->f, s->font));
1847 xgcv.font = s->font;
1848 mask = GCForeground | GCBackground | GCFont;
1850 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1851 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1852 mask, &xgcv);
1853 else
1854 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1855 = XCreateGC (s->display, s->window, mask, &xgcv);
1857 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1862 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1864 static void
1865 x_set_mouse_face_gc (s)
1866 struct glyph_string *s;
1868 int face_id;
1869 struct face *face;
1871 /* What face has to be used last for the mouse face? */
1872 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1873 face = FACE_FROM_ID (s->f, face_id);
1874 if (face == NULL)
1875 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1877 if (s->first_glyph->type == CHAR_GLYPH)
1878 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1879 else
1880 face_id = FACE_FOR_CHAR (s->f, face, 0);
1881 s->face = FACE_FROM_ID (s->f, face_id);
1882 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1884 /* If font in this face is same as S->font, use it. */
1885 if (s->font == s->face->font)
1886 s->gc = s->face->gc;
1887 else
1889 /* Otherwise construct scratch_cursor_gc with values from FACE
1890 but font FONT. */
1891 XGCValues xgcv;
1892 unsigned long mask;
1894 xgcv.background = s->face->background;
1895 xgcv.foreground = s->face->foreground;
1896 IF_DEBUG (x_check_font (s->f, s->font));
1897 xgcv.font = s->font;
1898 mask = GCForeground | GCBackground | GCFont;
1900 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1901 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1902 mask, &xgcv);
1903 else
1904 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1905 = XCreateGC (s->display, s->window, mask, &xgcv);
1907 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1910 xassert (s->gc != 0);
1914 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1915 Faces to use in the mode line have already been computed when the
1916 matrix was built, so there isn't much to do, here. */
1918 static INLINE void
1919 x_set_mode_line_face_gc (s)
1920 struct glyph_string *s;
1922 s->gc = s->face->gc;
1926 /* Set S->gc of glyph string S for drawing that glyph string. Set
1927 S->stippled_p to a non-zero value if the face of S has a stipple
1928 pattern. */
1930 static INLINE void
1931 x_set_glyph_string_gc (s)
1932 struct glyph_string *s;
1934 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1936 if (s->hl == DRAW_NORMAL_TEXT)
1938 s->gc = s->face->gc;
1939 s->stippled_p = s->face->stipple != 0;
1941 else if (s->hl == DRAW_INVERSE_VIDEO)
1943 x_set_mode_line_face_gc (s);
1944 s->stippled_p = s->face->stipple != 0;
1946 else if (s->hl == DRAW_CURSOR)
1948 x_set_cursor_gc (s);
1949 s->stippled_p = 0;
1951 else if (s->hl == DRAW_MOUSE_FACE)
1953 x_set_mouse_face_gc (s);
1954 s->stippled_p = s->face->stipple != 0;
1956 else if (s->hl == DRAW_IMAGE_RAISED
1957 || s->hl == DRAW_IMAGE_SUNKEN)
1959 s->gc = s->face->gc;
1960 s->stippled_p = s->face->stipple != 0;
1962 else
1964 s->gc = s->face->gc;
1965 s->stippled_p = s->face->stipple != 0;
1968 /* GC must have been set. */
1969 xassert (s->gc != 0);
1973 /* Set clipping for output of glyph string S. S may be part of a mode
1974 line or menu if we don't have X toolkit support. */
1976 static INLINE void
1977 x_set_glyph_string_clipping (s)
1978 struct glyph_string *s;
1980 Rect r;
1981 get_glyph_string_clip_rect (s, &r);
1982 mac_set_clip_rectangle (s->display, s->window, &r);
1986 /* RIF:
1987 Compute left and right overhang of glyph string S. If S is a glyph
1988 string for a composition, assume overhangs don't exist. */
1990 static void
1991 mac_compute_glyph_string_overhangs (s)
1992 struct glyph_string *s;
1994 #if 0
1995 /* MAC_TODO: XTextExtents16 does nothing yet... */
1997 if (s->cmp == NULL
1998 && s->first_glyph->type == CHAR_GLYPH)
2000 XCharStruct cs;
2001 int direction, font_ascent, font_descent;
2002 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2003 &font_ascent, &font_descent, &cs);
2004 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2005 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2007 #endif
2011 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2013 static INLINE void
2014 x_clear_glyph_string_rect (s, x, y, w, h)
2015 struct glyph_string *s;
2016 int x, y, w, h;
2018 XGCValues xgcv;
2020 xgcv.foreground = s->gc->background;
2021 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
2025 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2026 on Mac OS X because:
2027 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2028 into an offscreen graphics world first. So performance gain
2029 cannot be expected.)
2030 - It lowers rendering quality.
2031 - Some fonts leave garbage on cursor movement. */
2033 /* Draw the background of glyph_string S. If S->background_filled_p
2034 is non-zero don't draw it. FORCE_P non-zero means draw the
2035 background even if it wouldn't be drawn normally. This is used
2036 when a string preceding S draws into the background of S, or S
2037 contains the first component of a composition. */
2039 static void
2040 x_draw_glyph_string_background (s, force_p)
2041 struct glyph_string *s;
2042 int force_p;
2044 /* Nothing to do if background has already been drawn or if it
2045 shouldn't be drawn in the first place. */
2046 if (!s->background_filled_p)
2048 int box_line_width = max (s->face->box_line_width, 0);
2050 #if 0 /* MAC_TODO: stipple */
2051 if (s->stippled_p)
2053 /* Fill background with a stipple pattern. */
2054 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2055 XFillRectangle (s->display, s->window, s->gc, s->x,
2056 s->y + box_line_width,
2057 s->background_width,
2058 s->height - 2 * box_line_width);
2059 XSetFillStyle (s->display, s->gc, FillSolid);
2060 s->background_filled_p = 1;
2062 else
2063 #endif
2064 #ifdef MAC_OS8
2065 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2066 || s->font_not_found_p
2067 || s->extends_to_end_of_line_p
2068 || force_p)
2069 #endif
2071 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2072 s->background_width,
2073 s->height - 2 * box_line_width);
2074 s->background_filled_p = 1;
2080 /* Draw the foreground of glyph string S. */
2082 static void
2083 x_draw_glyph_string_foreground (s)
2084 struct glyph_string *s;
2086 int i, x;
2088 /* If first glyph of S has a left box line, start drawing the text
2089 of S to the right of that box line. */
2090 if (s->face->box != FACE_NO_BOX
2091 && s->first_glyph->left_box_line_p)
2092 x = s->x + abs (s->face->box_line_width);
2093 else
2094 x = s->x;
2096 /* Draw characters of S as rectangles if S's font could not be
2097 loaded. */
2098 if (s->font_not_found_p)
2100 for (i = 0; i < s->nchars; ++i)
2102 struct glyph *g = s->first_glyph + i;
2103 mac_draw_rectangle (s->display, s->window,
2104 s->gc, x, s->y, g->pixel_width - 1,
2105 s->height - 1);
2106 x += g->pixel_width;
2109 else
2111 char *char1b = (char *) s->char2b;
2112 int boff = s->font_info->baseline_offset;
2114 if (s->font_info->vertical_centering)
2115 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2117 /* If we can use 8-bit functions, condense S->char2b. */
2118 if (!s->two_byte_p)
2119 for (i = 0; i < s->nchars; ++i)
2120 char1b[i] = s->char2b[i].byte2;
2122 #ifdef MAC_OS8
2123 /* Draw text with XDrawString if background has already been
2124 filled. Otherwise, use XDrawImageString. (Note that
2125 XDrawImageString is usually faster than XDrawString.) Always
2126 use XDrawImageString when drawing the cursor so that there is
2127 no chance that characters under a box cursor are invisible. */
2128 if (s->for_overlaps_p
2129 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2130 #endif
2132 /* Draw characters with 16-bit or 8-bit functions. */
2133 if (s->two_byte_p)
2134 XDrawString16 (s->display, s->window, s->gc, x,
2135 s->ybase - boff, s->char2b, s->nchars);
2136 else
2137 XDrawString (s->display, s->window, s->gc, x,
2138 s->ybase - boff, char1b, s->nchars);
2140 #ifdef MAC_OS8
2141 else
2143 if (s->two_byte_p)
2144 XDrawImageString16 (s->display, s->window, s->gc, x,
2145 s->ybase - boff, s->char2b, s->nchars);
2146 else
2147 XDrawImageString (s->display, s->window, s->gc, x,
2148 s->ybase - boff, char1b, s->nchars);
2150 #endif
2154 /* Draw the foreground of composite glyph string S. */
2156 static void
2157 x_draw_composite_glyph_string_foreground (s)
2158 struct glyph_string *s;
2160 int i, x;
2162 /* If first glyph of S has a left box line, start drawing the text
2163 of S to the right of that box line. */
2164 if (s->face->box != FACE_NO_BOX
2165 && s->first_glyph->left_box_line_p)
2166 x = s->x + abs (s->face->box_line_width);
2167 else
2168 x = s->x;
2170 /* S is a glyph string for a composition. S->gidx is the index of
2171 the first character drawn for glyphs of this composition.
2172 S->gidx == 0 means we are drawing the very first character of
2173 this composition. */
2175 /* Draw a rectangle for the composition if the font for the very
2176 first character of the composition could not be loaded. */
2177 if (s->font_not_found_p)
2179 if (s->gidx == 0)
2180 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2181 s->width - 1, s->height - 1);
2183 else
2185 for (i = 0; i < s->nchars; i++, ++s->gidx)
2186 XDrawString16 (s->display, s->window, s->gc,
2187 x + s->cmp->offsets[s->gidx * 2],
2188 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2189 s->char2b + i, 1);
2194 #ifdef USE_X_TOOLKIT
2196 static struct frame *x_frame_of_widget P_ ((Widget));
2199 /* Return the frame on which widget WIDGET is used.. Abort if frame
2200 cannot be determined. */
2202 static struct frame *
2203 x_frame_of_widget (widget)
2204 Widget widget;
2206 struct x_display_info *dpyinfo;
2207 Lisp_Object tail;
2208 struct frame *f;
2210 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2212 /* Find the top-level shell of the widget. Note that this function
2213 can be called when the widget is not yet realized, so XtWindow
2214 (widget) == 0. That's the reason we can't simply use
2215 x_any_window_to_frame. */
2216 while (!XtIsTopLevelShell (widget))
2217 widget = XtParent (widget);
2219 /* Look for a frame with that top-level widget. Allocate the color
2220 on that frame to get the right gamma correction value. */
2221 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2222 if (GC_FRAMEP (XCAR (tail))
2223 && (f = XFRAME (XCAR (tail)),
2224 (f->output_data.nothing != 1
2225 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2226 && f->output_data.x->widget == widget)
2227 return f;
2229 abort ();
2233 /* Allocate the color COLOR->pixel on the screen and display of
2234 widget WIDGET in colormap CMAP. If an exact match cannot be
2235 allocated, try the nearest color available. Value is non-zero
2236 if successful. This is called from lwlib. */
2239 x_alloc_nearest_color_for_widget (widget, cmap, color)
2240 Widget widget;
2241 Colormap cmap;
2242 XColor *color;
2244 struct frame *f = x_frame_of_widget (widget);
2245 return x_alloc_nearest_color (f, cmap, color);
2249 #endif /* USE_X_TOOLKIT */
2251 #if 0 /* MAC_TODO */
2253 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2254 CMAP. If an exact match can't be allocated, try the nearest color
2255 available. Value is non-zero if successful. Set *COLOR to the
2256 color allocated. */
2259 x_alloc_nearest_color (f, cmap, color)
2260 struct frame *f;
2261 Colormap cmap;
2262 XColor *color;
2264 Display *display = FRAME_X_DISPLAY (f);
2265 Screen *screen = FRAME_X_SCREEN (f);
2266 int rc;
2268 gamma_correct (f, color);
2269 rc = XAllocColor (display, cmap, color);
2270 if (rc == 0)
2272 /* If we got to this point, the colormap is full, so we're going
2273 to try to get the next closest color. The algorithm used is
2274 a least-squares matching, which is what X uses for closest
2275 color matching with StaticColor visuals. */
2276 int nearest, i;
2277 unsigned long nearest_delta = ~0;
2278 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2279 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2281 for (i = 0; i < ncells; ++i)
2282 cells[i].pixel = i;
2283 XQueryColors (display, cmap, cells, ncells);
2285 for (nearest = i = 0; i < ncells; ++i)
2287 long dred = (color->red >> 8) - (cells[i].red >> 8);
2288 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2289 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2290 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2292 if (delta < nearest_delta)
2294 nearest = i;
2295 nearest_delta = delta;
2299 color->red = cells[nearest].red;
2300 color->green = cells[nearest].green;
2301 color->blue = cells[nearest].blue;
2302 rc = XAllocColor (display, cmap, color);
2305 #ifdef DEBUG_X_COLORS
2306 if (rc)
2307 register_color (color->pixel);
2308 #endif /* DEBUG_X_COLORS */
2310 return rc;
2314 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2315 It's necessary to do this instead of just using PIXEL directly to
2316 get color reference counts right. */
2318 unsigned long
2319 x_copy_color (f, pixel)
2320 struct frame *f;
2321 unsigned long pixel;
2323 XColor color;
2325 color.pixel = pixel;
2326 BLOCK_INPUT;
2327 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2328 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2329 UNBLOCK_INPUT;
2330 #ifdef DEBUG_X_COLORS
2331 register_color (pixel);
2332 #endif
2333 return color.pixel;
2337 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2338 It's necessary to do this instead of just using PIXEL directly to
2339 get color reference counts right. */
2341 unsigned long
2342 x_copy_dpy_color (dpy, cmap, pixel)
2343 Display *dpy;
2344 Colormap cmap;
2345 unsigned long pixel;
2347 XColor color;
2349 color.pixel = pixel;
2350 BLOCK_INPUT;
2351 XQueryColor (dpy, cmap, &color);
2352 XAllocColor (dpy, cmap, &color);
2353 UNBLOCK_INPUT;
2354 #ifdef DEBUG_X_COLORS
2355 register_color (pixel);
2356 #endif
2357 return color.pixel;
2360 #endif /* MAC_TODO */
2363 /* Brightness beyond which a color won't have its highlight brightness
2364 boosted.
2366 Nominally, highlight colors for `3d' faces are calculated by
2367 brightening an object's color by a constant scale factor, but this
2368 doesn't yield good results for dark colors, so for colors who's
2369 brightness is less than this value (on a scale of 0-255) have to
2370 use an additional additive factor.
2372 The value here is set so that the default menu-bar/mode-line color
2373 (grey75) will not have its highlights changed at all. */
2374 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2377 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2378 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2379 If this produces the same color as COLOR, try a color where all RGB
2380 values have DELTA added. Return the allocated color in *COLOR.
2381 DISPLAY is the X display, CMAP is the colormap to operate on.
2382 Value is non-zero if successful. */
2384 static int
2385 mac_alloc_lighter_color (f, color, factor, delta)
2386 struct frame *f;
2387 unsigned long *color;
2388 double factor;
2389 int delta;
2391 unsigned long new;
2392 long bright;
2394 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2395 delta /= 256;
2397 /* Change RGB values by specified FACTOR. Avoid overflow! */
2398 xassert (factor >= 0);
2399 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2400 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2401 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2403 /* Calculate brightness of COLOR. */
2404 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2405 + BLUE_FROM_ULONG (*color)) / 6;
2407 /* We only boost colors that are darker than
2408 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2409 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2410 /* Make an additive adjustment to NEW, because it's dark enough so
2411 that scaling by FACTOR alone isn't enough. */
2413 /* How far below the limit this color is (0 - 1, 1 being darker). */
2414 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2415 /* The additive adjustment. */
2416 int min_delta = delta * dimness * factor / 2;
2418 if (factor < 1)
2419 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2420 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2421 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2422 else
2423 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2424 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2425 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2428 if (new == *color)
2429 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2430 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2431 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2433 /* MAC_TODO: Map to palette and retry with delta if same? */
2434 /* MAC_TODO: Free colors (if using palette)? */
2436 if (new == *color)
2437 return 0;
2439 *color = new;
2441 return 1;
2445 /* Set up the foreground color for drawing relief lines of glyph
2446 string S. RELIEF is a pointer to a struct relief containing the GC
2447 with which lines will be drawn. Use a color that is FACTOR or
2448 DELTA lighter or darker than the relief's background which is found
2449 in S->f->output_data.x->relief_background. If such a color cannot
2450 be allocated, use DEFAULT_PIXEL, instead. */
2452 static void
2453 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2454 struct frame *f;
2455 struct relief *relief;
2456 double factor;
2457 int delta;
2458 unsigned long default_pixel;
2460 XGCValues xgcv;
2461 struct mac_output *di = f->output_data.mac;
2462 unsigned long mask = GCForeground;
2463 unsigned long pixel;
2464 unsigned long background = di->relief_background;
2465 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2467 /* MAC_TODO: Free colors (if using palette)? */
2469 /* Allocate new color. */
2470 xgcv.foreground = default_pixel;
2471 pixel = background;
2472 if (dpyinfo->n_planes != 1
2473 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2475 relief->allocated_p = 1;
2476 xgcv.foreground = relief->pixel = pixel;
2479 if (relief->gc == 0)
2481 #if 0 /* MAC_TODO: stipple */
2482 xgcv.stipple = dpyinfo->gray;
2483 mask |= GCStipple;
2484 #endif
2485 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2487 else
2488 XChangeGC (NULL, relief->gc, mask, &xgcv);
2492 /* Set up colors for the relief lines around glyph string S. */
2494 static void
2495 x_setup_relief_colors (s)
2496 struct glyph_string *s;
2498 struct mac_output *di = s->f->output_data.mac;
2499 unsigned long color;
2501 if (s->face->use_box_color_for_shadows_p)
2502 color = s->face->box_color;
2503 else if (s->first_glyph->type == IMAGE_GLYPH
2504 && s->img->pixmap
2505 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2506 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2507 else
2509 XGCValues xgcv;
2511 /* Get the background color of the face. */
2512 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2513 color = xgcv.background;
2516 if (di->white_relief.gc == 0
2517 || color != di->relief_background)
2519 di->relief_background = color;
2520 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2521 WHITE_PIX_DEFAULT (s->f));
2522 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2523 BLACK_PIX_DEFAULT (s->f));
2528 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2529 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2530 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2531 relief. LEFT_P non-zero means draw a relief on the left side of
2532 the rectangle. RIGHT_P non-zero means draw a relief on the right
2533 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2534 when drawing. */
2536 static void
2537 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2538 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2539 struct frame *f;
2540 int left_x, top_y, right_x, bottom_y, width;
2541 int top_p, bot_p, left_p, right_p, raised_p;
2542 Rect *clip_rect;
2544 Display *dpy = FRAME_MAC_DISPLAY (f);
2545 Window window = FRAME_MAC_WINDOW (f);
2546 int i;
2547 GC gc;
2549 if (raised_p)
2550 gc = f->output_data.mac->white_relief.gc;
2551 else
2552 gc = f->output_data.mac->black_relief.gc;
2553 mac_set_clip_rectangle (dpy, window, clip_rect);
2555 /* Top. */
2556 if (top_p)
2557 for (i = 0; i < width; ++i)
2558 XDrawLine (dpy, window, gc,
2559 left_x + i * left_p, top_y + i,
2560 right_x - i * right_p, top_y + i);
2562 /* Left. */
2563 if (left_p)
2564 for (i = 0; i < width; ++i)
2565 XDrawLine (dpy, window, gc,
2566 left_x + i, top_y + i, left_x + i, bottom_y - i);
2568 mac_reset_clipping (dpy, window);
2569 if (raised_p)
2570 gc = f->output_data.mac->black_relief.gc;
2571 else
2572 gc = f->output_data.mac->white_relief.gc;
2573 mac_set_clip_rectangle (dpy, window,
2574 clip_rect);
2576 /* Bottom. */
2577 if (bot_p)
2578 for (i = 0; i < width; ++i)
2579 XDrawLine (dpy, window, gc,
2580 left_x + i * left_p, bottom_y - i,
2581 right_x - i * right_p, bottom_y - i);
2583 /* Right. */
2584 if (right_p)
2585 for (i = 0; i < width; ++i)
2586 XDrawLine (dpy, window, gc,
2587 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2589 mac_reset_clipping (dpy, window);
2593 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2594 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2595 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2596 left side of the rectangle. RIGHT_P non-zero means draw a line
2597 on the right side of the rectangle. CLIP_RECT is the clipping
2598 rectangle to use when drawing. */
2600 static void
2601 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2602 left_p, right_p, clip_rect)
2603 struct glyph_string *s;
2604 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2605 Rect *clip_rect;
2607 XGCValues xgcv;
2609 xgcv.foreground = s->face->box_color;
2610 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2612 /* Top. */
2613 XFillRectangle (s->display, s->window, &xgcv,
2614 left_x, top_y, right_x - left_x + 1, width);
2616 /* Left. */
2617 if (left_p)
2618 XFillRectangle (s->display, s->window, &xgcv,
2619 left_x, top_y, width, bottom_y - top_y + 1);
2621 /* Bottom. */
2622 XFillRectangle (s->display, s->window, &xgcv,
2623 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2625 /* Right. */
2626 if (right_p)
2627 XFillRectangle (s->display, s->window, &xgcv,
2628 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2630 mac_reset_clipping (s->display, s->window);
2634 /* Draw a box around glyph string S. */
2636 static void
2637 x_draw_glyph_string_box (s)
2638 struct glyph_string *s;
2640 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2641 int left_p, right_p;
2642 struct glyph *last_glyph;
2643 Rect clip_rect;
2645 last_x = window_box_right (s->w, s->area);
2646 if (s->row->full_width_p
2647 && !s->w->pseudo_window_p)
2649 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2650 if (s->area != RIGHT_MARGIN_AREA
2651 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2652 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2655 /* The glyph that may have a right box line. */
2656 last_glyph = (s->cmp || s->img
2657 ? s->first_glyph
2658 : s->first_glyph + s->nchars - 1);
2660 width = abs (s->face->box_line_width);
2661 raised_p = s->face->box == FACE_RAISED_BOX;
2662 left_x = s->x;
2663 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2664 ? last_x - 1
2665 : min (last_x, s->x + s->background_width) - 1);
2666 top_y = s->y;
2667 bottom_y = top_y + s->height - 1;
2669 left_p = (s->first_glyph->left_box_line_p
2670 || (s->hl == DRAW_MOUSE_FACE
2671 && (s->prev == NULL
2672 || s->prev->hl != s->hl)));
2673 right_p = (last_glyph->right_box_line_p
2674 || (s->hl == DRAW_MOUSE_FACE
2675 && (s->next == NULL
2676 || s->next->hl != s->hl)));
2678 get_glyph_string_clip_rect (s, &clip_rect);
2680 if (s->face->box == FACE_SIMPLE_BOX)
2681 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2682 left_p, right_p, &clip_rect);
2683 else
2685 x_setup_relief_colors (s);
2686 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2687 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2692 /* Draw foreground of image glyph string S. */
2694 static void
2695 x_draw_image_foreground (s)
2696 struct glyph_string *s;
2698 int x = s->x;
2699 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2701 /* If first glyph of S has a left box line, start drawing it to the
2702 right of that line. */
2703 if (s->face->box != FACE_NO_BOX
2704 && s->first_glyph->left_box_line_p
2705 && s->slice.x == 0)
2706 x += abs (s->face->box_line_width);
2708 /* If there is a margin around the image, adjust x- and y-position
2709 by that margin. */
2710 if (s->slice.x == 0)
2711 x += s->img->hmargin;
2712 if (s->slice.y == 0)
2713 y += s->img->vmargin;
2715 if (s->img->pixmap)
2717 x_set_glyph_string_clipping (s);
2719 if (s->img->mask)
2720 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2721 s->window, s->gc, s->slice.x, s->slice.y,
2722 s->slice.width, s->slice.height, x, y);
2723 else
2725 mac_copy_area (s->display, s->img->pixmap,
2726 s->window, s->gc, s->slice.x, s->slice.y,
2727 s->slice.width, s->slice.height, x, y);
2729 /* When the image has a mask, we can expect that at
2730 least part of a mouse highlight or a block cursor will
2731 be visible. If the image doesn't have a mask, make
2732 a block cursor visible by drawing a rectangle around
2733 the image. I believe it's looking better if we do
2734 nothing here for mouse-face. */
2735 if (s->hl == DRAW_CURSOR)
2737 int r = s->img->relief;
2738 if (r < 0) r = -r;
2739 mac_draw_rectangle (s->display, s->window, s->gc,
2740 x - r, y - r,
2741 s->slice.width + r*2 - 1,
2742 s->slice.height + r*2 - 1);
2746 else
2747 /* Draw a rectangle if image could not be loaded. */
2748 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2749 s->slice.width - 1, s->slice.height - 1);
2753 /* Draw a relief around the image glyph string S. */
2755 static void
2756 x_draw_image_relief (s)
2757 struct glyph_string *s;
2759 int x0, y0, x1, y1, thick, raised_p;
2760 Rect r;
2761 int x = s->x;
2762 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2764 /* If first glyph of S has a left box line, start drawing it to the
2765 right of that line. */
2766 if (s->face->box != FACE_NO_BOX
2767 && s->first_glyph->left_box_line_p
2768 && s->slice.x == 0)
2769 x += abs (s->face->box_line_width);
2771 /* If there is a margin around the image, adjust x- and y-position
2772 by that margin. */
2773 if (s->slice.x == 0)
2774 x += s->img->hmargin;
2775 if (s->slice.y == 0)
2776 y += s->img->vmargin;
2778 if (s->hl == DRAW_IMAGE_SUNKEN
2779 || s->hl == DRAW_IMAGE_RAISED)
2781 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2782 raised_p = s->hl == DRAW_IMAGE_RAISED;
2784 else
2786 thick = abs (s->img->relief);
2787 raised_p = s->img->relief > 0;
2790 x0 = x - thick;
2791 y0 = y - thick;
2792 x1 = x + s->slice.width + thick - 1;
2793 y1 = y + s->slice.height + thick - 1;
2795 x_setup_relief_colors (s);
2796 get_glyph_string_clip_rect (s, &r);
2797 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2798 s->slice.y == 0,
2799 s->slice.y + s->slice.height == s->img->height,
2800 s->slice.x == 0,
2801 s->slice.x + s->slice.width == s->img->width,
2802 &r);
2806 #if 0 /* TODO: figure out if we need to do this on Mac. */
2807 /* Draw the foreground of image glyph string S to PIXMAP. */
2809 static void
2810 x_draw_image_foreground_1 (s, pixmap)
2811 struct glyph_string *s;
2812 Pixmap pixmap;
2814 int x = 0;
2815 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2817 /* If first glyph of S has a left box line, start drawing it to the
2818 right of that line. */
2819 if (s->face->box != FACE_NO_BOX
2820 && s->first_glyph->left_box_line_p
2821 && s->slice.x == 0)
2822 x += abs (s->face->box_line_width);
2824 /* If there is a margin around the image, adjust x- and y-position
2825 by that margin. */
2826 if (s->slice.x == 0)
2827 x += s->img->hmargin;
2828 if (s->slice.y == 0)
2829 y += s->img->vmargin;
2831 if (s->img->pixmap)
2833 if (s->img->mask)
2834 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2835 s->img->mask, pixmap, s->gc,
2836 s->slice.x, s->slice.y,
2837 s->slice.width, s->slice.height,
2838 x, y);
2839 else
2841 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2842 s->slice.x, s->slice.y,
2843 s->slice.width, s->slice.height,
2844 x, y);
2846 /* When the image has a mask, we can expect that at
2847 least part of a mouse highlight or a block cursor will
2848 be visible. If the image doesn't have a mask, make
2849 a block cursor visible by drawing a rectangle around
2850 the image. I believe it's looking better if we do
2851 nothing here for mouse-face. */
2852 if (s->hl == DRAW_CURSOR)
2854 int r = s->img->relief;
2855 if (r < 0) r = -r;
2856 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2857 s->slice.width + r*2 - 1,
2858 s->slice.height + r*2 - 1);
2862 else
2863 /* Draw a rectangle if image could not be loaded. */
2864 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2865 s->slice.width - 1, s->slice.height - 1);
2867 #endif
2870 /* Draw part of the background of glyph string S. X, Y, W, and H
2871 give the rectangle to draw. */
2873 static void
2874 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2875 struct glyph_string *s;
2876 int x, y, w, h;
2878 #if 0 /* MAC_TODO: stipple */
2879 if (s->stippled_p)
2881 /* Fill background with a stipple pattern. */
2882 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2883 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2884 XSetFillStyle (s->display, s->gc, FillSolid);
2886 else
2887 #endif /* MAC_TODO */
2888 x_clear_glyph_string_rect (s, x, y, w, h);
2892 /* Draw image glyph string S.
2894 s->y
2895 s->x +-------------------------
2896 | s->face->box
2898 | +-------------------------
2899 | | s->img->margin
2901 | | +-------------------
2902 | | | the image
2906 static void
2907 x_draw_image_glyph_string (s)
2908 struct glyph_string *s;
2910 int x, y;
2911 int box_line_hwidth = abs (s->face->box_line_width);
2912 int box_line_vwidth = max (s->face->box_line_width, 0);
2913 int height;
2914 Pixmap pixmap = 0;
2916 height = s->height - 2 * box_line_vwidth;
2919 /* Fill background with face under the image. Do it only if row is
2920 taller than image or if image has a clip mask to reduce
2921 flickering. */
2922 s->stippled_p = s->face->stipple != 0;
2923 if (height > s->slice.height
2924 || s->img->hmargin
2925 || s->img->vmargin
2926 || s->img->mask
2927 || s->img->pixmap == 0
2928 || s->width != s->background_width)
2930 x = s->x;
2931 if (s->first_glyph->left_box_line_p
2932 && s->slice.x == 0)
2933 x += box_line_hwidth;
2935 y = s->y;
2936 if (s->slice.y == 0)
2937 y += box_line_vwidth;
2939 #if 0 /* TODO: figure out if we need to do this on Mac. */
2940 if (s->img->mask)
2942 /* Create a pixmap as large as the glyph string. Fill it
2943 with the background color. Copy the image to it, using
2944 its mask. Copy the temporary pixmap to the display. */
2945 int depth = one_mac_display_info.n_planes;
2947 /* Create a pixmap as large as the glyph string. */
2948 pixmap = XCreatePixmap (s->display, s->window,
2949 s->background_width,
2950 s->height, depth);
2952 /* Fill the pixmap with the background color/stipple. */
2953 #if 0 /* TODO: stipple */
2954 if (s->stippled_p)
2956 /* Fill background with a stipple pattern. */
2957 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2958 XFillRectangle (s->display, pixmap, s->gc,
2959 0, 0, s->background_width, s->height);
2960 XSetFillStyle (s->display, s->gc, FillSolid);
2962 else
2963 #endif
2965 XGCValues xgcv;
2966 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2967 &xgcv);
2968 XSetForeground (s->display, s->gc, xgcv.background);
2969 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2970 0, 0, s->background_width,
2971 s->height);
2972 XSetForeground (s->display, s->gc, xgcv.foreground);
2975 else
2976 #endif
2977 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2979 s->background_filled_p = 1;
2982 /* Draw the foreground. */
2983 #if 0 /* TODO: figure out if we need to do this on Mac. */
2984 if (pixmap != 0)
2986 x_draw_image_foreground_1 (s, pixmap);
2987 x_set_glyph_string_clipping (s);
2988 mac_copy_area (s->display, pixmap, s->window, s->gc,
2989 0, 0, s->background_width, s->height, s->x, s->y);
2990 mac_reset_clipping (s->display, s->window);
2991 XFreePixmap (s->display, pixmap);
2993 else
2994 #endif
2995 x_draw_image_foreground (s);
2997 /* If we must draw a relief around the image, do it. */
2998 if (s->img->relief
2999 || s->hl == DRAW_IMAGE_RAISED
3000 || s->hl == DRAW_IMAGE_SUNKEN)
3001 x_draw_image_relief (s);
3005 /* Draw stretch glyph string S. */
3007 static void
3008 x_draw_stretch_glyph_string (s)
3009 struct glyph_string *s;
3011 xassert (s->first_glyph->type == STRETCH_GLYPH);
3012 s->stippled_p = s->face->stipple != 0;
3014 if (s->hl == DRAW_CURSOR
3015 && !x_stretch_cursor_p)
3017 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3018 as wide as the stretch glyph. */
3019 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
3021 /* Draw cursor. */
3022 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3024 /* Clear rest using the GC of the original non-cursor face. */
3025 if (width < s->background_width)
3027 int x = s->x + width, y = s->y;
3028 int w = s->background_width - width, h = s->height;
3029 Rect r;
3030 GC gc;
3032 if (s->row->mouse_face_p
3033 && cursor_in_mouse_face_p (s->w))
3035 x_set_mouse_face_gc (s);
3036 gc = s->gc;
3038 else
3039 gc = s->face->gc;
3041 get_glyph_string_clip_rect (s, &r);
3042 mac_set_clip_rectangle (s->display, s->window, &r);
3044 #if 0 /* MAC_TODO: stipple */
3045 if (s->face->stipple)
3047 /* Fill background with a stipple pattern. */
3048 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3049 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3050 XSetFillStyle (s->display, gc, FillSolid);
3052 else
3053 #endif /* MAC_TODO */
3055 XGCValues xgcv;
3056 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3057 XSetForeground (s->display, gc, xgcv.background);
3058 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3059 XSetForeground (s->display, gc, xgcv.foreground);
3062 mac_reset_clipping (s->display, s->window);
3065 else if (!s->background_filled_p)
3066 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3067 s->height);
3069 s->background_filled_p = 1;
3073 /* Draw glyph string S. */
3075 static void
3076 x_draw_glyph_string (s)
3077 struct glyph_string *s;
3079 int relief_drawn_p = 0;
3081 /* If S draws into the background of its successor, draw the
3082 background of the successor first so that S can draw into it.
3083 This makes S->next use XDrawString instead of XDrawImageString. */
3084 if (s->next && s->right_overhang && !s->for_overlaps_p)
3086 xassert (s->next->img == NULL);
3087 x_set_glyph_string_gc (s->next);
3088 x_set_glyph_string_clipping (s->next);
3089 x_draw_glyph_string_background (s->next, 1);
3092 /* Set up S->gc, set clipping and draw S. */
3093 x_set_glyph_string_gc (s);
3095 /* Draw relief (if any) in advance for char/composition so that the
3096 glyph string can be drawn over it. */
3097 if (!s->for_overlaps_p
3098 && s->face->box != FACE_NO_BOX
3099 && (s->first_glyph->type == CHAR_GLYPH
3100 || s->first_glyph->type == COMPOSITE_GLYPH))
3103 x_set_glyph_string_clipping (s);
3104 x_draw_glyph_string_background (s, 1);
3105 x_draw_glyph_string_box (s);
3106 x_set_glyph_string_clipping (s);
3107 relief_drawn_p = 1;
3109 else
3110 x_set_glyph_string_clipping (s);
3112 switch (s->first_glyph->type)
3114 case IMAGE_GLYPH:
3115 x_draw_image_glyph_string (s);
3116 break;
3118 case STRETCH_GLYPH:
3119 x_draw_stretch_glyph_string (s);
3120 break;
3122 case CHAR_GLYPH:
3123 if (s->for_overlaps_p)
3124 s->background_filled_p = 1;
3125 else
3126 x_draw_glyph_string_background (s, 0);
3127 x_draw_glyph_string_foreground (s);
3128 break;
3130 case COMPOSITE_GLYPH:
3131 if (s->for_overlaps_p || s->gidx > 0)
3132 s->background_filled_p = 1;
3133 else
3134 x_draw_glyph_string_background (s, 1);
3135 x_draw_composite_glyph_string_foreground (s);
3136 break;
3138 default:
3139 abort ();
3142 if (!s->for_overlaps_p)
3144 /* Draw underline. */
3145 if (s->face->underline_p)
3147 unsigned long h = 1;
3148 unsigned long dy = s->height - h;
3150 if (s->face->underline_defaulted_p)
3151 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3152 s->width, h);
3153 else
3155 XGCValues xgcv;
3156 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3157 XSetForeground (s->display, s->gc, s->face->underline_color);
3158 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3159 s->width, h);
3160 XSetForeground (s->display, s->gc, xgcv.foreground);
3164 /* Draw overline. */
3165 if (s->face->overline_p)
3167 unsigned long dy = 0, h = 1;
3169 if (s->face->overline_color_defaulted_p)
3170 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3171 s->width, h);
3172 else
3174 XGCValues xgcv;
3175 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3176 XSetForeground (s->display, s->gc, s->face->overline_color);
3177 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3178 s->width, h);
3179 XSetForeground (s->display, s->gc, xgcv.foreground);
3183 /* Draw strike-through. */
3184 if (s->face->strike_through_p)
3186 unsigned long h = 1;
3187 unsigned long dy = (s->height - h) / 2;
3189 if (s->face->strike_through_color_defaulted_p)
3190 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3191 s->width, h);
3192 else
3194 XGCValues xgcv;
3195 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3196 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3197 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3198 s->width, h);
3199 XSetForeground (s->display, s->gc, xgcv.foreground);
3203 /* Draw relief if not yet drawn. */
3204 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3205 x_draw_glyph_string_box (s);
3208 /* Reset clipping. */
3209 mac_reset_clipping (s->display, s->window);
3212 /* Shift display to make room for inserted glyphs. */
3214 void
3215 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3216 struct frame *f;
3217 int x, y, width, height, shift_by;
3219 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3220 f->output_data.mac->normal_gc,
3221 x, y, width, height,
3222 x + shift_by, y);
3225 /* Delete N glyphs at the nominal cursor position. Not implemented
3226 for X frames. */
3228 static void
3229 x_delete_glyphs (n)
3230 register int n;
3232 abort ();
3236 /* Clear entire frame. If updating_frame is non-null, clear that
3237 frame. Otherwise clear the selected frame. */
3239 static void
3240 x_clear_frame ()
3242 struct frame *f;
3244 if (updating_frame)
3245 f = updating_frame;
3246 else
3247 f = SELECTED_FRAME ();
3249 /* Clearing the frame will erase any cursor, so mark them all as no
3250 longer visible. */
3251 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3252 output_cursor.hpos = output_cursor.vpos = 0;
3253 output_cursor.x = -1;
3255 /* We don't set the output cursor here because there will always
3256 follow an explicit cursor_to. */
3257 BLOCK_INPUT;
3258 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3260 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3261 /* We have to clear the scroll bars, too. If we have changed
3262 colors or something like that, then they should be notified. */
3263 x_scroll_bar_clear (f);
3264 #endif
3266 XFlush (FRAME_MAC_DISPLAY (f));
3267 UNBLOCK_INPUT;
3272 /* Invert the middle quarter of the frame for .15 sec. */
3274 /* We use the select system call to do the waiting, so we have to make
3275 sure it's available. If it isn't, we just won't do visual bells. */
3277 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3280 /* Subtract the `struct timeval' values X and Y, storing the result in
3281 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3283 static int
3284 timeval_subtract (result, x, y)
3285 struct timeval *result, x, y;
3287 /* Perform the carry for the later subtraction by updating y. This
3288 is safer because on some systems the tv_sec member is unsigned. */
3289 if (x.tv_usec < y.tv_usec)
3291 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3292 y.tv_usec -= 1000000 * nsec;
3293 y.tv_sec += nsec;
3296 if (x.tv_usec - y.tv_usec > 1000000)
3298 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3299 y.tv_usec += 1000000 * nsec;
3300 y.tv_sec -= nsec;
3303 /* Compute the time remaining to wait. tv_usec is certainly
3304 positive. */
3305 result->tv_sec = x.tv_sec - y.tv_sec;
3306 result->tv_usec = x.tv_usec - y.tv_usec;
3308 /* Return indication of whether the result should be considered
3309 negative. */
3310 return x.tv_sec < y.tv_sec;
3313 void
3314 XTflash (f)
3315 struct frame *f;
3317 BLOCK_INPUT;
3319 FlashMenuBar (0);
3322 struct timeval wakeup;
3324 EMACS_GET_TIME (wakeup);
3326 /* Compute time to wait until, propagating carry from usecs. */
3327 wakeup.tv_usec += 150000;
3328 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3329 wakeup.tv_usec %= 1000000;
3331 /* Keep waiting until past the time wakeup. */
3332 while (1)
3334 struct timeval timeout;
3336 EMACS_GET_TIME (timeout);
3338 /* In effect, timeout = wakeup - timeout.
3339 Break if result would be negative. */
3340 if (timeval_subtract (&timeout, wakeup, timeout))
3341 break;
3343 /* Try to wait that long--but we might wake up sooner. */
3344 select (0, NULL, NULL, NULL, &timeout);
3348 FlashMenuBar (0);
3350 UNBLOCK_INPUT;
3353 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3356 /* Make audible bell. */
3358 void
3359 XTring_bell ()
3361 struct frame *f = SELECTED_FRAME ();
3363 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3364 if (visible_bell)
3365 XTflash (f);
3366 else
3367 #endif
3369 BLOCK_INPUT;
3370 SysBeep (1);
3371 XFlush (FRAME_MAC_DISPLAY (f));
3372 UNBLOCK_INPUT;
3378 /* Specify how many text lines, from the top of the window,
3379 should be affected by insert-lines and delete-lines operations.
3380 This, and those operations, are used only within an update
3381 that is bounded by calls to x_update_begin and x_update_end. */
3383 static void
3384 XTset_terminal_window (n)
3385 register int n;
3387 /* This function intentionally left blank. */
3392 /***********************************************************************
3393 Line Dance
3394 ***********************************************************************/
3396 /* Perform an insert-lines or delete-lines operation, inserting N
3397 lines or deleting -N lines at vertical position VPOS. */
3399 static void
3400 x_ins_del_lines (vpos, n)
3401 int vpos, n;
3403 abort ();
3407 /* Scroll part of the display as described by RUN. */
3409 static void
3410 x_scroll_run (w, run)
3411 struct window *w;
3412 struct run *run;
3414 struct frame *f = XFRAME (w->frame);
3415 int x, y, width, height, from_y, to_y, bottom_y;
3417 /* Get frame-relative bounding box of the text display area of W,
3418 without mode lines. Include in this box the left and right
3419 fringe of W. */
3420 window_box (w, -1, &x, &y, &width, &height);
3422 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3423 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3424 bottom_y = y + height;
3426 if (to_y < from_y)
3428 /* Scrolling up. Make sure we don't copy part of the mode
3429 line at the bottom. */
3430 if (from_y + run->height > bottom_y)
3431 height = bottom_y - from_y;
3432 else
3433 height = run->height;
3435 else
3437 /* Scolling down. Make sure we don't copy over the mode line.
3438 at the bottom. */
3439 if (to_y + run->height > bottom_y)
3440 height = bottom_y - to_y;
3441 else
3442 height = run->height;
3445 BLOCK_INPUT;
3447 /* Cursor off. Will be switched on again in x_update_window_end. */
3448 updated_window = w;
3449 x_clear_cursor (w);
3451 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3452 f->output_data.mac->normal_gc,
3453 x, from_y,
3454 width, height,
3455 x, to_y);
3457 UNBLOCK_INPUT;
3462 /***********************************************************************
3463 Exposure Events
3464 ***********************************************************************/
3467 static void
3468 frame_highlight (f)
3469 struct frame *f;
3471 x_update_cursor (f, 1);
3474 static void
3475 frame_unhighlight (f)
3476 struct frame *f;
3478 x_update_cursor (f, 1);
3481 /* The focus has changed. Update the frames as necessary to reflect
3482 the new situation. Note that we can't change the selected frame
3483 here, because the Lisp code we are interrupting might become confused.
3484 Each event gets marked with the frame in which it occurred, so the
3485 Lisp code can tell when the switch took place by examining the events. */
3487 static void
3488 x_new_focus_frame (dpyinfo, frame)
3489 struct x_display_info *dpyinfo;
3490 struct frame *frame;
3492 struct frame *old_focus = dpyinfo->x_focus_frame;
3494 if (frame != dpyinfo->x_focus_frame)
3496 /* Set this before calling other routines, so that they see
3497 the correct value of x_focus_frame. */
3498 dpyinfo->x_focus_frame = frame;
3500 if (old_focus && old_focus->auto_lower)
3501 x_lower_frame (old_focus);
3503 #if 0
3504 selected_frame = frame;
3505 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3506 selected_frame);
3507 Fselect_window (selected_frame->selected_window, Qnil);
3508 choose_minibuf_frame ();
3509 #endif /* ! 0 */
3511 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3512 pending_autoraise_frame = dpyinfo->x_focus_frame;
3513 else
3514 pending_autoraise_frame = 0;
3517 x_frame_rehighlight (dpyinfo);
3520 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3522 void
3523 x_mouse_leave (dpyinfo)
3524 struct x_display_info *dpyinfo;
3526 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3529 /* The focus has changed, or we have redirected a frame's focus to
3530 another frame (this happens when a frame uses a surrogate
3531 mini-buffer frame). Shift the highlight as appropriate.
3533 The FRAME argument doesn't necessarily have anything to do with which
3534 frame is being highlighted or un-highlighted; we only use it to find
3535 the appropriate X display info. */
3537 static void
3538 XTframe_rehighlight (frame)
3539 struct frame *frame;
3541 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3544 static void
3545 x_frame_rehighlight (dpyinfo)
3546 struct x_display_info *dpyinfo;
3548 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3550 if (dpyinfo->x_focus_frame)
3552 dpyinfo->x_highlight_frame
3553 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3554 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3555 : dpyinfo->x_focus_frame);
3556 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3558 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3559 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3562 else
3563 dpyinfo->x_highlight_frame = 0;
3565 if (dpyinfo->x_highlight_frame != old_highlight)
3567 if (old_highlight)
3568 frame_unhighlight (old_highlight);
3569 if (dpyinfo->x_highlight_frame)
3570 frame_highlight (dpyinfo->x_highlight_frame);
3576 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3578 #if 0 /* MAC_TODO */
3579 /* Initialize mode_switch_bit and modifier_meaning. */
3580 static void
3581 x_find_modifier_meanings (dpyinfo)
3582 struct x_display_info *dpyinfo;
3584 int min_code, max_code;
3585 KeySym *syms;
3586 int syms_per_code;
3587 XModifierKeymap *mods;
3589 dpyinfo->meta_mod_mask = 0;
3590 dpyinfo->shift_lock_mask = 0;
3591 dpyinfo->alt_mod_mask = 0;
3592 dpyinfo->super_mod_mask = 0;
3593 dpyinfo->hyper_mod_mask = 0;
3595 #ifdef HAVE_X11R4
3596 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3597 #else
3598 min_code = dpyinfo->display->min_keycode;
3599 max_code = dpyinfo->display->max_keycode;
3600 #endif
3602 syms = XGetKeyboardMapping (dpyinfo->display,
3603 min_code, max_code - min_code + 1,
3604 &syms_per_code);
3605 mods = XGetModifierMapping (dpyinfo->display);
3607 /* Scan the modifier table to see which modifier bits the Meta and
3608 Alt keysyms are on. */
3610 int row, col; /* The row and column in the modifier table. */
3612 for (row = 3; row < 8; row++)
3613 for (col = 0; col < mods->max_keypermod; col++)
3615 KeyCode code
3616 = mods->modifiermap[(row * mods->max_keypermod) + col];
3618 /* Zeroes are used for filler. Skip them. */
3619 if (code == 0)
3620 continue;
3622 /* Are any of this keycode's keysyms a meta key? */
3624 int code_col;
3626 for (code_col = 0; code_col < syms_per_code; code_col++)
3628 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3630 switch (sym)
3632 case XK_Meta_L:
3633 case XK_Meta_R:
3634 dpyinfo->meta_mod_mask |= (1 << row);
3635 break;
3637 case XK_Alt_L:
3638 case XK_Alt_R:
3639 dpyinfo->alt_mod_mask |= (1 << row);
3640 break;
3642 case XK_Hyper_L:
3643 case XK_Hyper_R:
3644 dpyinfo->hyper_mod_mask |= (1 << row);
3645 break;
3647 case XK_Super_L:
3648 case XK_Super_R:
3649 dpyinfo->super_mod_mask |= (1 << row);
3650 break;
3652 case XK_Shift_Lock:
3653 /* Ignore this if it's not on the lock modifier. */
3654 if ((1 << row) == LockMask)
3655 dpyinfo->shift_lock_mask = LockMask;
3656 break;
3663 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3664 if (! dpyinfo->meta_mod_mask)
3666 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3667 dpyinfo->alt_mod_mask = 0;
3670 /* If some keys are both alt and meta,
3671 make them just meta, not alt. */
3672 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3674 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3677 XFree ((char *) syms);
3678 XFreeModifiermap (mods);
3681 #endif /* MAC_TODO */
3683 /* Convert between the modifier bits X uses and the modifier bits
3684 Emacs uses. */
3686 static unsigned int
3687 x_mac_to_emacs_modifiers (dpyinfo, state)
3688 struct x_display_info *dpyinfo;
3689 unsigned short state;
3691 return (((state & shiftKey) ? shift_modifier : 0)
3692 | ((state & controlKey) ? ctrl_modifier : 0)
3693 | ((state & cmdKey) ? meta_modifier : 0)
3694 | ((state & optionKey) ? alt_modifier : 0));
3697 #if 0 /* MAC_TODO */
3698 static unsigned short
3699 x_emacs_to_x_modifiers (dpyinfo, state)
3700 struct x_display_info *dpyinfo;
3701 unsigned int state;
3703 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3704 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3705 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3706 | ((state & shift_modifier) ? ShiftMask : 0)
3707 | ((state & ctrl_modifier) ? ControlMask : 0)
3708 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3710 #endif /* MAC_TODO */
3712 /* Convert a keysym to its name. */
3714 char *
3715 x_get_keysym_name (keysym)
3716 int keysym;
3718 char *value;
3720 BLOCK_INPUT;
3721 #if 0
3722 value = XKeysymToString (keysym);
3723 #else
3724 value = 0;
3725 #endif
3726 UNBLOCK_INPUT;
3728 return value;
3733 #if 0
3734 /* Mouse clicks and mouse movement. Rah. */
3736 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3738 If the event is a button press, then note that we have grabbed
3739 the mouse. */
3741 static Lisp_Object
3742 construct_mouse_click (result, event, f)
3743 struct input_event *result;
3744 EventRecord *event;
3745 struct frame *f;
3747 Point mouseLoc;
3749 result->kind = MOUSE_CLICK_EVENT;
3750 result->code = 0; /* only one mouse button */
3751 result->timestamp = event->when;
3752 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3754 mouseLoc = event->where;
3756 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3758 GlobalToLocal (&mouseLoc);
3759 XSETINT (result->x, mouseLoc.h);
3760 XSETINT (result->y, mouseLoc.v);
3762 XSETFRAME (result->frame_or_window, f);
3764 result->arg = Qnil;
3765 return Qnil;
3767 #endif
3770 /* Function to report a mouse movement to the mainstream Emacs code.
3771 The input handler calls this.
3773 We have received a mouse movement event, which is given in *event.
3774 If the mouse is over a different glyph than it was last time, tell
3775 the mainstream emacs code by setting mouse_moved. If not, ask for
3776 another motion event, so we can check again the next time it moves. */
3778 static Point last_mouse_motion_position;
3779 static Lisp_Object last_mouse_motion_frame;
3781 static void
3782 note_mouse_movement (frame, pos)
3783 FRAME_PTR frame;
3784 Point *pos;
3786 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3787 #if TARGET_API_MAC_CARBON
3788 Rect r;
3789 #endif
3791 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3792 last_mouse_motion_position = *pos;
3793 XSETFRAME (last_mouse_motion_frame, frame);
3795 #if TARGET_API_MAC_CARBON
3796 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3797 #else
3798 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3799 #endif
3801 if (frame == dpyinfo->mouse_face_mouse_frame)
3802 /* This case corresponds to LeaveNotify in X11. */
3804 /* If we move outside the frame, then we're certainly no
3805 longer on any text in the frame. */
3806 clear_mouse_face (dpyinfo);
3807 dpyinfo->mouse_face_mouse_frame = 0;
3808 if (!dpyinfo->grabbed)
3809 rif->define_frame_cursor (frame,
3810 frame->output_data.mac->nontext_cursor);
3813 /* Has the mouse moved off the glyph it was on at the last sighting? */
3814 else if (pos->h < last_mouse_glyph.left
3815 || pos->h >= last_mouse_glyph.right
3816 || pos->v < last_mouse_glyph.top
3817 || pos->v >= last_mouse_glyph.bottom)
3819 frame->mouse_moved = 1;
3820 last_mouse_scroll_bar = Qnil;
3821 note_mouse_highlight (frame, pos->h, pos->v);
3825 /* This is used for debugging, to turn off note_mouse_highlight. */
3827 int disable_mouse_highlight;
3831 /************************************************************************
3832 Mouse Face
3833 ************************************************************************/
3835 static struct scroll_bar *x_window_to_scroll_bar ();
3836 static void x_scroll_bar_report_motion ();
3837 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3840 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3842 static void
3843 redo_mouse_highlight ()
3845 if (!NILP (last_mouse_motion_frame)
3846 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3847 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3848 last_mouse_motion_position.h,
3849 last_mouse_motion_position.v);
3853 /* Try to determine frame pixel position and size of the glyph under
3854 frame pixel coordinates X/Y on frame F . Return the position and
3855 size in *RECT. Value is non-zero if we could compute these
3856 values. */
3858 static int
3859 glyph_rect (f, x, y, rect)
3860 struct frame *f;
3861 int x, y;
3862 Rect *rect;
3864 Lisp_Object window;
3866 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3868 if (!NILP (window))
3870 struct window *w = XWINDOW (window);
3871 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3872 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3874 for (; r < end && r->enabled_p; ++r)
3875 if (r->y <= y && r->y + r->height > y)
3877 /* Found the row at y. */
3878 struct glyph *g = r->glyphs[TEXT_AREA];
3879 struct glyph *end = g + r->used[TEXT_AREA];
3880 int gx;
3882 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3883 rect->bottom = rect->top + r->height;
3885 if (x < r->x)
3887 /* x is to the left of the first glyph in the row. */
3888 /* Shouldn't this be a pixel value?
3889 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3890 ++KFS */
3891 rect->left = WINDOW_LEFT_EDGE_COL (w);
3892 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3893 return 1;
3896 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3897 if (gx <= x && gx + g->pixel_width > x)
3899 /* x is on a glyph. */
3900 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3901 rect->right = rect->left + g->pixel_width;
3902 return 1;
3905 /* x is to the right of the last glyph in the row. */
3906 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3907 /* Shouldn't this be a pixel value?
3908 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3909 ++KFS */
3910 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3911 return 1;
3915 /* The y is not on any row. */
3916 return 0;
3919 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3921 /* Record the position of the mouse in last_mouse_glyph. */
3922 static void
3923 remember_mouse_glyph (f1, gx, gy)
3924 struct frame * f1;
3925 int gx, gy;
3927 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3929 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3930 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3932 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3933 round down even for negative values. */
3934 if (gx < 0)
3935 gx -= width - 1;
3936 if (gy < 0)
3937 gy -= height - 1;
3938 #if 0
3939 /* This was the original code from XTmouse_position, but it seems
3940 to give the position of the glyph diagonally next to the one
3941 the mouse is over. */
3942 gx = (gx + width - 1) / width * width;
3943 gy = (gy + height - 1) / height * height;
3944 #else
3945 gx = gx / width * width;
3946 gy = gy / height * height;
3947 #endif
3949 last_mouse_glyph.left = gx;
3950 last_mouse_glyph.top = gy;
3951 last_mouse_glyph.right = gx + width;
3952 last_mouse_glyph.bottom = gy + height;
3957 static WindowPtr
3958 front_emacs_window ()
3960 #if TARGET_API_MAC_CARBON
3961 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3963 while (wp && !is_emacs_window (wp))
3964 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3965 #else
3966 WindowPtr wp = FrontWindow ();
3968 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3969 wp = GetNextWindow (wp);
3970 #endif
3972 return wp;
3975 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3977 /* Return the current position of the mouse.
3978 *fp should be a frame which indicates which display to ask about.
3980 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3981 and *part to the frame, window, and scroll bar part that the mouse
3982 is over. Set *x and *y to the portion and whole of the mouse's
3983 position on the scroll bar.
3985 If the mouse movement started elsewhere, set *fp to the frame the
3986 mouse is on, *bar_window to nil, and *x and *y to the character cell
3987 the mouse is over.
3989 Set *time to the server time-stamp for the time at which the mouse
3990 was at this position.
3992 Don't store anything if we don't have a valid set of values to report.
3994 This clears the mouse_moved flag, so we can wait for the next mouse
3995 movement. */
3997 static void
3998 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3999 FRAME_PTR *fp;
4000 int insist;
4001 Lisp_Object *bar_window;
4002 enum scroll_bar_part *part;
4003 Lisp_Object *x, *y;
4004 unsigned long *time;
4006 Point mouse_pos;
4007 int ignore1, ignore2;
4008 WindowPtr wp = front_emacs_window ();
4009 struct frame *f;
4010 Lisp_Object frame, tail;
4012 if (is_emacs_window(wp))
4013 f = mac_window_to_frame (wp);
4015 BLOCK_INPUT;
4017 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4018 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4019 else
4021 /* Clear the mouse-moved flag for every frame on this display. */
4022 FOR_EACH_FRAME (tail, frame)
4023 XFRAME (frame)->mouse_moved = 0;
4025 last_mouse_scroll_bar = Qnil;
4027 SetPortWindowPort (wp);
4029 GetMouse (&mouse_pos);
4031 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
4032 &last_mouse_glyph, insist);
4034 *bar_window = Qnil;
4035 *part = scroll_bar_handle;
4036 *fp = f;
4037 XSETINT (*x, mouse_pos.h);
4038 XSETINT (*y, mouse_pos.v);
4039 *time = last_mouse_movement_time;
4042 UNBLOCK_INPUT;
4046 /***********************************************************************
4047 Tool-bars
4048 ***********************************************************************/
4050 /* Handle mouse button event on the tool-bar of frame F, at
4051 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4052 or ButtonRelase. */
4054 static void
4055 mac_handle_tool_bar_click (f, button_event)
4056 struct frame *f;
4057 EventRecord *button_event;
4059 int x = button_event->where.h;
4060 int y = button_event->where.v;
4062 if (button_event->what == mouseDown)
4063 handle_tool_bar_click (f, x, y, 1, 0);
4064 else
4065 handle_tool_bar_click (f, x, y, 0,
4066 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
4067 button_event->modifiers));
4071 /************************************************************************
4072 Scroll bars, general
4073 ************************************************************************/
4075 /* Create a scroll bar and return the scroll bar vector for it. W is
4076 the Emacs window on which to create the scroll bar. TOP, LEFT,
4077 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4078 scroll bar. */
4080 static struct scroll_bar *
4081 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4082 struct window *w;
4083 int top, left, width, height, disp_top, disp_height;
4085 struct frame *f = XFRAME (w->frame);
4086 struct scroll_bar *bar
4087 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4088 Rect r;
4089 ControlHandle ch;
4091 BLOCK_INPUT;
4093 r.left = left;
4094 r.top = disp_top;
4095 r.right = left + width;
4096 r.bottom = disp_top + disp_height;
4098 #if TARGET_API_MAC_CARBON
4099 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4100 kControlScrollBarProc, 0L);
4101 #else
4102 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4103 0L);
4104 #endif
4105 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4106 SetControlReference (ch, (long) bar);
4108 XSETWINDOW (bar->window, w);
4109 XSETINT (bar->top, top);
4110 XSETINT (bar->left, left);
4111 XSETINT (bar->width, width);
4112 XSETINT (bar->height, height);
4113 XSETINT (bar->start, 0);
4114 XSETINT (bar->end, 0);
4115 bar->dragging = Qnil;
4117 /* Add bar to its frame's list of scroll bars. */
4118 bar->next = FRAME_SCROLL_BARS (f);
4119 bar->prev = Qnil;
4120 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4121 if (!NILP (bar->next))
4122 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4124 UNBLOCK_INPUT;
4125 return bar;
4129 /* Draw BAR's handle in the proper position.
4131 If the handle is already drawn from START to END, don't bother
4132 redrawing it, unless REBUILD is non-zero; in that case, always
4133 redraw it. (REBUILD is handy for drawing the handle after expose
4134 events.)
4136 Normally, we want to constrain the start and end of the handle to
4137 fit inside its rectangle, but if the user is dragging the scroll
4138 bar handle, we want to let them drag it down all the way, so that
4139 the bar's top is as far down as it goes; otherwise, there's no way
4140 to move to the very end of the buffer. */
4142 static void
4143 x_scroll_bar_set_handle (bar, start, end, rebuild)
4144 struct scroll_bar *bar;
4145 int start, end;
4146 int rebuild;
4148 int dragging = ! NILP (bar->dragging);
4149 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4150 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4151 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4152 int length = end - start;
4154 /* If the display is already accurate, do nothing. */
4155 if (! rebuild
4156 && start == XINT (bar->start)
4157 && end == XINT (bar->end))
4158 return;
4160 BLOCK_INPUT;
4162 /* Make sure the values are reasonable, and try to preserve the
4163 distance between start and end. */
4164 if (start < 0)
4165 start = 0;
4166 else if (start > top_range)
4167 start = top_range;
4168 end = start + length;
4170 if (end < start)
4171 end = start;
4172 else if (end > top_range && ! dragging)
4173 end = top_range;
4175 /* Store the adjusted setting in the scroll bar. */
4176 XSETINT (bar->start, start);
4177 XSETINT (bar->end, end);
4179 /* Clip the end position, just for display. */
4180 if (end > top_range)
4181 end = top_range;
4183 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4184 top positions, to make sure the handle is always at least that
4185 many pixels tall. */
4186 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4188 SetControlMinimum (ch, 0);
4189 /* Don't inadvertently activate deactivated scroll bars */
4190 if (GetControlMaximum (ch) != -1)
4191 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4192 - (end - start));
4193 SetControlValue (ch, start);
4194 #if TARGET_API_MAC_CARBON
4195 SetControlViewSize (ch, end - start);
4196 #endif
4198 UNBLOCK_INPUT;
4202 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4203 nil. */
4205 static void
4206 x_scroll_bar_remove (bar)
4207 struct scroll_bar *bar;
4209 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4211 BLOCK_INPUT;
4213 /* Destroy the Mac scroll bar control */
4214 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4216 /* Disassociate this scroll bar from its window. */
4217 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4219 UNBLOCK_INPUT;
4222 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4223 that we are displaying PORTION characters out of a total of WHOLE
4224 characters, starting at POSITION. If WINDOW has no scroll bar,
4225 create one. */
4226 static void
4227 XTset_vertical_scroll_bar (w, portion, whole, position)
4228 struct window *w;
4229 int portion, whole, position;
4231 struct frame *f = XFRAME (w->frame);
4232 struct scroll_bar *bar;
4233 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4234 int window_y, window_height;
4236 /* Get window dimensions. */
4237 window_box (w, -1, 0, &window_y, 0, &window_height);
4238 top = window_y;
4239 #ifdef MAC_OSX
4240 width = 16;
4241 #else
4242 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4243 #endif
4244 height = window_height;
4246 /* Compute the left edge of the scroll bar area. */
4247 left = WINDOW_SCROLL_BAR_AREA_X (w);
4249 /* Compute the width of the scroll bar which might be less than
4250 the width of the area reserved for the scroll bar. */
4251 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4252 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4253 else
4254 sb_width = width;
4256 /* Compute the left edge of the scroll bar. */
4257 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4258 sb_left = left + width - sb_width - (width - sb_width) / 2;
4259 else
4260 sb_left = left + (width - sb_width) / 2;
4262 /* Adjustments according to Inside Macintosh to make it look nice */
4263 disp_top = top;
4264 disp_height = height;
4265 if (disp_top == 0)
4267 disp_top = -1;
4268 disp_height++;
4270 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4272 disp_top++;
4273 disp_height--;
4276 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4277 sb_left++;
4279 /* Does the scroll bar exist yet? */
4280 if (NILP (w->vertical_scroll_bar))
4282 BLOCK_INPUT;
4283 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4284 left, top, width, height, 0);
4285 UNBLOCK_INPUT;
4286 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4287 disp_height);
4288 XSETVECTOR (w->vertical_scroll_bar, bar);
4290 else
4292 /* It may just need to be moved and resized. */
4293 ControlHandle ch;
4295 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4296 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4298 BLOCK_INPUT;
4300 /* If already correctly positioned, do nothing. */
4301 if (XINT (bar->left) == sb_left
4302 && XINT (bar->top) == top
4303 && XINT (bar->width) == sb_width
4304 && XINT (bar->height) == height)
4305 Draw1Control (ch);
4306 else
4308 /* Clear areas not covered by the scroll bar because it's not as
4309 wide as the area reserved for it . This makes sure a
4310 previous mode line display is cleared after C-x 2 C-x 1, for
4311 example. */
4312 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4313 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4314 left, top, area_width, height, 0);
4316 #if 0
4317 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4318 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4319 sb_left - 1, top, 1, height, 0);
4320 #endif
4322 HideControl (ch);
4323 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4324 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4325 disp_height);
4326 ShowControl (ch);
4328 /* Remember new settings. */
4329 XSETINT (bar->left, sb_left);
4330 XSETINT (bar->top, top);
4331 XSETINT (bar->width, sb_width);
4332 XSETINT (bar->height, height);
4335 UNBLOCK_INPUT;
4338 /* Set the scroll bar's current state, unless we're currently being
4339 dragged. */
4340 if (NILP (bar->dragging))
4342 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4344 if (whole == 0)
4345 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4346 else
4348 int start = ((double) position * top_range) / whole;
4349 int end = ((double) (position + portion) * top_range) / whole;
4350 x_scroll_bar_set_handle (bar, start, end, 0);
4356 /* The following three hooks are used when we're doing a thorough
4357 redisplay of the frame. We don't explicitly know which scroll bars
4358 are going to be deleted, because keeping track of when windows go
4359 away is a real pain - "Can you say set-window-configuration, boys
4360 and girls?" Instead, we just assert at the beginning of redisplay
4361 that *all* scroll bars are to be removed, and then save a scroll bar
4362 from the fiery pit when we actually redisplay its window. */
4364 /* Arrange for all scroll bars on FRAME to be removed at the next call
4365 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4366 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4368 static void
4369 XTcondemn_scroll_bars (frame)
4370 FRAME_PTR frame;
4372 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4373 while (! NILP (FRAME_SCROLL_BARS (frame)))
4375 Lisp_Object bar;
4376 bar = FRAME_SCROLL_BARS (frame);
4377 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4378 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4379 XSCROLL_BAR (bar)->prev = Qnil;
4380 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4381 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4382 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4387 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4388 Note that WINDOW isn't necessarily condemned at all. */
4390 static void
4391 XTredeem_scroll_bar (window)
4392 struct window *window;
4394 struct scroll_bar *bar;
4396 /* We can't redeem this window's scroll bar if it doesn't have one. */
4397 if (NILP (window->vertical_scroll_bar))
4398 abort ();
4400 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4402 /* Unlink it from the condemned list. */
4404 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4406 if (NILP (bar->prev))
4408 /* If the prev pointer is nil, it must be the first in one of
4409 the lists. */
4410 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4411 /* It's not condemned. Everything's fine. */
4412 return;
4413 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4414 window->vertical_scroll_bar))
4415 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4416 else
4417 /* If its prev pointer is nil, it must be at the front of
4418 one or the other! */
4419 abort ();
4421 else
4422 XSCROLL_BAR (bar->prev)->next = bar->next;
4424 if (! NILP (bar->next))
4425 XSCROLL_BAR (bar->next)->prev = bar->prev;
4427 bar->next = FRAME_SCROLL_BARS (f);
4428 bar->prev = Qnil;
4429 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4430 if (! NILP (bar->next))
4431 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4435 /* Remove all scroll bars on FRAME that haven't been saved since the
4436 last call to `*condemn_scroll_bars_hook'. */
4438 static void
4439 XTjudge_scroll_bars (f)
4440 FRAME_PTR f;
4442 Lisp_Object bar, next;
4444 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4446 /* Clear out the condemned list now so we won't try to process any
4447 more events on the hapless scroll bars. */
4448 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4450 for (; ! NILP (bar); bar = next)
4452 struct scroll_bar *b = XSCROLL_BAR (bar);
4454 x_scroll_bar_remove (b);
4456 next = b->next;
4457 b->next = b->prev = Qnil;
4460 /* Now there should be no references to the condemned scroll bars,
4461 and they should get garbage-collected. */
4465 void
4466 activate_scroll_bars (frame)
4467 FRAME_PTR frame;
4469 Lisp_Object bar;
4470 ControlHandle ch;
4472 bar = FRAME_SCROLL_BARS (frame);
4473 while (! NILP (bar))
4475 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4476 #if 1 /* TARGET_API_MAC_CARBON */
4477 ActivateControl (ch);
4478 #else
4479 SetControlMaximum (ch,
4480 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4481 XINT (XSCROLL_BAR (bar)
4482 ->height)) - 1);
4483 #endif
4484 bar = XSCROLL_BAR (bar)->next;
4489 void
4490 deactivate_scroll_bars (frame)
4491 FRAME_PTR frame;
4493 Lisp_Object bar;
4494 ControlHandle ch;
4496 bar = FRAME_SCROLL_BARS (frame);
4497 while (! NILP (bar))
4499 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4500 #if 1 /* TARGET_API_MAC_CARBON */
4501 DeactivateControl (ch);
4502 #else
4503 SetControlMaximum (ch, -1);
4504 #endif
4505 bar = XSCROLL_BAR (bar)->next;
4509 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4510 is set to something other than NO_EVENT, it is enqueued.
4512 This may be called from a signal handler, so we have to ignore GC
4513 mark bits. */
4515 static void
4516 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4517 struct scroll_bar *bar;
4518 int part_code;
4519 EventRecord *er;
4520 struct input_event *bufp;
4522 int win_y, top_range;
4524 if (! GC_WINDOWP (bar->window))
4525 abort ();
4527 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4528 bufp->frame_or_window = bar->window;
4529 bufp->arg = Qnil;
4531 bar->dragging = Qnil;
4533 switch (part_code)
4535 case kControlUpButtonPart:
4536 bufp->part = scroll_bar_up_arrow;
4537 break;
4538 case kControlDownButtonPart:
4539 bufp->part = scroll_bar_down_arrow;
4540 break;
4541 case kControlPageUpPart:
4542 bufp->part = scroll_bar_above_handle;
4543 break;
4544 case kControlPageDownPart:
4545 bufp->part = scroll_bar_below_handle;
4546 break;
4547 #if TARGET_API_MAC_CARBON
4548 default:
4549 #else
4550 case kControlIndicatorPart:
4551 #endif
4552 if (er->what == mouseDown)
4553 bar->dragging = make_number (0);
4554 XSETVECTOR (last_mouse_scroll_bar, bar);
4555 bufp->part = scroll_bar_handle;
4556 break;
4559 win_y = XINT (bufp->y) - XINT (bar->top);
4560 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4562 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4564 win_y -= 24;
4566 if (! NILP (bar->dragging))
4567 win_y -= XINT (bar->dragging);
4569 if (win_y < 0)
4570 win_y = 0;
4571 if (win_y > top_range)
4572 win_y = top_range;
4574 XSETINT (bufp->x, win_y);
4575 XSETINT (bufp->y, top_range);
4579 /* Handle some mouse motion while someone is dragging the scroll bar.
4581 This may be called from a signal handler, so we have to ignore GC
4582 mark bits. */
4584 static void
4585 x_scroll_bar_note_movement (bar, y_pos, t)
4586 struct scroll_bar *bar;
4587 int y_pos;
4588 Time t;
4590 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4592 last_mouse_movement_time = t;
4594 f->mouse_moved = 1;
4595 XSETVECTOR (last_mouse_scroll_bar, bar);
4597 /* If we're dragging the bar, display it. */
4598 if (! GC_NILP (bar->dragging))
4600 /* Where should the handle be now? */
4601 int new_start = y_pos - 24;
4603 if (new_start != XINT (bar->start))
4605 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4607 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4613 /* Return information to the user about the current position of the
4614 mouse on the scroll bar. */
4616 static void
4617 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4618 FRAME_PTR *fp;
4619 Lisp_Object *bar_window;
4620 enum scroll_bar_part *part;
4621 Lisp_Object *x, *y;
4622 unsigned long *time;
4624 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4625 WindowPtr wp = front_emacs_window ();
4626 Point mouse_pos;
4627 struct frame *f = mac_window_to_frame (wp);
4628 int win_y, top_range;
4630 SetPortWindowPort (wp);
4632 GetMouse (&mouse_pos);
4634 win_y = mouse_pos.v - XINT (bar->top);
4635 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4637 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4639 win_y -= 24;
4641 if (! NILP (bar->dragging))
4642 win_y -= XINT (bar->dragging);
4644 if (win_y < 0)
4645 win_y = 0;
4646 if (win_y > top_range)
4647 win_y = top_range;
4649 *fp = f;
4650 *bar_window = bar->window;
4652 if (! NILP (bar->dragging))
4653 *part = scroll_bar_handle;
4654 else if (win_y < XINT (bar->start))
4655 *part = scroll_bar_above_handle;
4656 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4657 *part = scroll_bar_handle;
4658 else
4659 *part = scroll_bar_below_handle;
4661 XSETINT (*x, win_y);
4662 XSETINT (*y, top_range);
4664 f->mouse_moved = 0;
4665 last_mouse_scroll_bar = Qnil;
4667 *time = last_mouse_movement_time;
4670 /***********************************************************************
4671 Text Cursor
4672 ***********************************************************************/
4674 /* Set clipping for output in glyph row ROW. W is the window in which
4675 we operate. GC is the graphics context to set clipping in.
4677 ROW may be a text row or, e.g., a mode line. Text rows must be
4678 clipped to the interior of the window dedicated to text display,
4679 mode lines must be clipped to the whole window. */
4681 static void
4682 x_clip_to_row (w, row, area, gc)
4683 struct window *w;
4684 struct glyph_row *row;
4685 int area;
4686 GC gc;
4688 struct frame *f = XFRAME (WINDOW_FRAME (w));
4689 Rect clip_rect;
4690 int window_x, window_y, window_width;
4692 window_box (w, area, &window_x, &window_y, &window_width, 0);
4694 clip_rect.left = window_x;
4695 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4696 clip_rect.top = max (clip_rect.top, window_y);
4697 clip_rect.right = clip_rect.left + window_width;
4698 clip_rect.bottom = clip_rect.top + row->visible_height;
4700 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4704 /* Draw a hollow box cursor on window W in glyph row ROW. */
4706 static void
4707 x_draw_hollow_cursor (w, row)
4708 struct window *w;
4709 struct glyph_row *row;
4711 struct frame *f = XFRAME (WINDOW_FRAME (w));
4712 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4713 Display *dpy = FRAME_MAC_DISPLAY (f);
4714 int x, y, wd, h;
4715 XGCValues xgcv;
4716 struct glyph *cursor_glyph;
4717 GC gc;
4719 /* Get the glyph the cursor is on. If we can't tell because
4720 the current matrix is invalid or such, give up. */
4721 cursor_glyph = get_phys_cursor_glyph (w);
4722 if (cursor_glyph == NULL)
4723 return;
4725 /* Compute the width of the rectangle to draw. If on a stretch
4726 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4727 rectangle as wide as the glyph, but use a canonical character
4728 width instead. */
4729 wd = cursor_glyph->pixel_width - 1;
4730 if (cursor_glyph->type == STRETCH_GLYPH
4731 && !x_stretch_cursor_p)
4732 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4733 w->phys_cursor_width = wd;
4735 /* Compute frame-relative coordinates from window-relative
4736 coordinates. */
4737 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4738 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4740 /* Compute the proper height and ascent of the rectangle, based
4741 on the actual glyph. Using the full height of the row looks
4742 bad when there are tall images on that row. */
4743 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4744 cursor_glyph->ascent + cursor_glyph->descent);
4745 if (h < row->height)
4746 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4747 h--;
4749 /* The foreground of cursor_gc is typically the same as the normal
4750 background color, which can cause the cursor box to be invisible. */
4751 xgcv.foreground = f->output_data.mac->cursor_pixel;
4752 if (dpyinfo->scratch_cursor_gc)
4753 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4754 else
4755 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4756 GCForeground, &xgcv);
4757 gc = dpyinfo->scratch_cursor_gc;
4759 /* Set clipping, draw the rectangle, and reset clipping again. */
4760 x_clip_to_row (w, row, TEXT_AREA, gc);
4761 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4762 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4766 /* Draw a bar cursor on window W in glyph row ROW.
4768 Implementation note: One would like to draw a bar cursor with an
4769 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4770 Unfortunately, I didn't find a font yet that has this property set.
4771 --gerd. */
4773 static void
4774 x_draw_bar_cursor (w, row, width, kind)
4775 struct window *w;
4776 struct glyph_row *row;
4777 int width;
4778 enum text_cursor_kinds kind;
4780 struct frame *f = XFRAME (w->frame);
4781 struct glyph *cursor_glyph;
4783 /* If cursor is out of bounds, don't draw garbage. This can happen
4784 in mini-buffer windows when switching between echo area glyphs
4785 and mini-buffer. */
4786 cursor_glyph = get_phys_cursor_glyph (w);
4787 if (cursor_glyph == NULL)
4788 return;
4790 /* If on an image, draw like a normal cursor. That's usually better
4791 visible than drawing a bar, esp. if the image is large so that
4792 the bar might not be in the window. */
4793 if (cursor_glyph->type == IMAGE_GLYPH)
4795 struct glyph_row *row;
4796 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4797 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4799 else
4801 Display *dpy = FRAME_MAC_DISPLAY (f);
4802 Window window = FRAME_MAC_WINDOW (f);
4803 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4804 unsigned long mask = GCForeground | GCBackground;
4805 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4806 XGCValues xgcv;
4808 /* If the glyph's background equals the color we normally draw
4809 the bar cursor in, the bar cursor in its normal color is
4810 invisible. Use the glyph's foreground color instead in this
4811 case, on the assumption that the glyph's colors are chosen so
4812 that the glyph is legible. */
4813 if (face->background == f->output_data.mac->cursor_pixel)
4814 xgcv.background = xgcv.foreground = face->foreground;
4815 else
4816 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4818 if (gc)
4819 XChangeGC (dpy, gc, mask, &xgcv);
4820 else
4822 gc = XCreateGC (dpy, window, mask, &xgcv);
4823 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4826 if (width < 0)
4827 width = FRAME_CURSOR_WIDTH (f);
4828 width = min (cursor_glyph->pixel_width, width);
4830 w->phys_cursor_width = width;
4831 x_clip_to_row (w, row, TEXT_AREA, gc);
4833 if (kind == BAR_CURSOR)
4834 XFillRectangle (dpy, window, gc,
4835 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4836 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4837 width, row->height);
4838 else
4839 XFillRectangle (dpy, window, gc,
4840 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4841 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4842 row->height - width),
4843 cursor_glyph->pixel_width,
4844 width);
4846 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4851 /* RIF: Define cursor CURSOR on frame F. */
4853 static void
4854 mac_define_frame_cursor (f, cursor)
4855 struct frame *f;
4856 Cursor cursor;
4858 #if TARGET_API_MAC_CARBON
4859 SetThemeCursor (cursor);
4860 #else
4861 SetCursor (*cursor);
4862 #endif
4866 /* RIF: Clear area on frame F. */
4868 static void
4869 mac_clear_frame_area (f, x, y, width, height)
4870 struct frame *f;
4871 int x, y, width, height;
4873 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4874 x, y, width, height, 0);
4878 /* RIF: Draw cursor on window W. */
4880 static void
4881 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4882 struct window *w;
4883 struct glyph_row *glyph_row;
4884 int x, y;
4885 int cursor_type, cursor_width;
4886 int on_p, active_p;
4888 if (on_p)
4890 w->phys_cursor_type = cursor_type;
4891 w->phys_cursor_on_p = 1;
4893 if (glyph_row->exact_window_width_line_p
4894 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4896 glyph_row->cursor_in_fringe_p = 1;
4897 draw_fringe_bitmap (w, glyph_row, 0);
4899 else
4900 switch (cursor_type)
4902 case HOLLOW_BOX_CURSOR:
4903 x_draw_hollow_cursor (w, glyph_row);
4904 break;
4906 case FILLED_BOX_CURSOR:
4907 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4908 break;
4910 case BAR_CURSOR:
4911 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4912 break;
4914 case HBAR_CURSOR:
4915 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4916 break;
4918 case NO_CURSOR:
4919 w->phys_cursor_width = 0;
4920 break;
4922 default:
4923 abort ();
4929 /* Icons. */
4931 #if 0 /* MAC_TODO: no icon support yet. */
4933 x_bitmap_icon (f, icon)
4934 struct frame *f;
4935 Lisp_Object icon;
4937 HANDLE hicon;
4939 if (FRAME_W32_WINDOW (f) == 0)
4940 return 1;
4942 if (NILP (icon))
4943 hicon = LoadIcon (hinst, EMACS_CLASS);
4944 else if (STRINGP (icon))
4945 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4946 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4947 else if (SYMBOLP (icon))
4949 LPCTSTR name;
4951 if (EQ (icon, intern ("application")))
4952 name = (LPCTSTR) IDI_APPLICATION;
4953 else if (EQ (icon, intern ("hand")))
4954 name = (LPCTSTR) IDI_HAND;
4955 else if (EQ (icon, intern ("question")))
4956 name = (LPCTSTR) IDI_QUESTION;
4957 else if (EQ (icon, intern ("exclamation")))
4958 name = (LPCTSTR) IDI_EXCLAMATION;
4959 else if (EQ (icon, intern ("asterisk")))
4960 name = (LPCTSTR) IDI_ASTERISK;
4961 else if (EQ (icon, intern ("winlogo")))
4962 name = (LPCTSTR) IDI_WINLOGO;
4963 else
4964 return 1;
4966 hicon = LoadIcon (NULL, name);
4968 else
4969 return 1;
4971 if (hicon == NULL)
4972 return 1;
4974 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4975 (LPARAM) hicon);
4977 return 0;
4979 #endif /* MAC_TODO */
4981 /************************************************************************
4982 Handling X errors
4983 ************************************************************************/
4985 /* Display Error Handling functions not used on W32. Listing them here
4986 helps diff stay in step when comparing w32term.c with xterm.c.
4988 x_error_catcher (display, error)
4989 x_catch_errors (dpy)
4990 x_catch_errors_unwind (old_val)
4991 x_check_errors (dpy, format)
4992 x_had_errors_p (dpy)
4993 x_clear_errors (dpy)
4994 x_uncatch_errors (dpy, count)
4995 x_trace_wire ()
4996 x_connection_signal (signalnum)
4997 x_connection_closed (dpy, error_message)
4998 x_error_quitter (display, error)
4999 x_error_handler (display, error)
5000 x_io_error_quitter (display)
5005 /* Changing the font of the frame. */
5007 /* Give frame F the font named FONTNAME as its default font, and
5008 return the full name of that font. FONTNAME may be a wildcard
5009 pattern; in that case, we choose some font that fits the pattern.
5010 The return value shows which font we chose. */
5012 Lisp_Object
5013 x_new_font (f, fontname)
5014 struct frame *f;
5015 register char *fontname;
5017 struct font_info *fontp
5018 = FS_LOAD_FONT (f, 0, fontname, -1);
5020 if (!fontp)
5021 return Qnil;
5023 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5024 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5025 FRAME_FONTSET (f) = -1;
5027 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5028 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5029 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5031 compute_fringe_widths (f, 1);
5033 /* Compute the scroll bar width in character columns. */
5034 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5036 int wid = FRAME_COLUMN_WIDTH (f);
5037 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5038 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5040 else
5042 int wid = FRAME_COLUMN_WIDTH (f);
5043 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5046 /* Now make the frame display the given font. */
5047 if (FRAME_MAC_WINDOW (f) != 0)
5049 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5050 FRAME_FONT (f));
5051 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5052 FRAME_FONT (f));
5053 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5054 FRAME_FONT (f));
5056 /* Don't change the size of a tip frame; there's no point in
5057 doing it because it's done in Fx_show_tip, and it leads to
5058 problems because the tip frame has no widget. */
5059 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5060 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5063 return build_string (fontp->full_name);
5066 /* Give frame F the fontset named FONTSETNAME as its default font, and
5067 return the full name of that fontset. FONTSETNAME may be a wildcard
5068 pattern; in that case, we choose some fontset that fits the pattern.
5069 The return value shows which fontset we chose. */
5071 Lisp_Object
5072 x_new_fontset (f, fontsetname)
5073 struct frame *f;
5074 char *fontsetname;
5076 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5077 Lisp_Object result;
5079 if (fontset < 0)
5080 return Qnil;
5082 if (FRAME_FONTSET (f) == fontset)
5083 /* This fontset is already set in frame F. There's nothing more
5084 to do. */
5085 return fontset_name (fontset);
5087 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5089 if (!STRINGP (result))
5090 /* Can't load ASCII font. */
5091 return Qnil;
5093 /* Since x_new_font doesn't update any fontset information, do it now. */
5094 FRAME_FONTSET(f) = fontset;
5096 return build_string (fontsetname);
5100 /***********************************************************************
5101 TODO: W32 Input Methods
5102 ***********************************************************************/
5103 /* Listing missing functions from xterm.c helps diff stay in step.
5105 xim_destroy_callback (xim, client_data, call_data)
5106 xim_open_dpy (dpyinfo, resource_name)
5107 struct xim_inst_t
5108 xim_instantiate_callback (display, client_data, call_data)
5109 xim_initialize (dpyinfo, resource_name)
5110 xim_close_dpy (dpyinfo)
5115 void
5116 mac_get_window_bounds (f, inner, outer)
5117 struct frame *f;
5118 Rect *inner, *outer;
5120 #if TARGET_API_MAC_CARBON
5121 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5122 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5123 #else /* not TARGET_API_MAC_CARBON */
5124 RgnHandle region = NewRgn ();
5126 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5127 *inner = (*region)->rgnBBox;
5128 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5129 *outer = (*region)->rgnBBox;
5130 DisposeRgn (region);
5131 #endif /* not TARGET_API_MAC_CARBON */
5135 /* Calculate the absolute position in frame F
5136 from its current recorded position values and gravity. */
5138 void
5139 x_calc_absolute_position (f)
5140 struct frame *f;
5142 int width_diff = 0, height_diff = 0;
5143 int flags = f->size_hint_flags;
5144 Rect inner, outer;
5146 /* We have nothing to do if the current position
5147 is already for the top-left corner. */
5148 if (! ((flags & XNegative) || (flags & YNegative)))
5149 return;
5151 /* Find the offsets of the outside upper-left corner of
5152 the inner window, with respect to the outer window. */
5153 mac_get_window_bounds (f, &inner, &outer);
5155 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5156 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5158 /* Treat negative positions as relative to the leftmost bottommost
5159 position that fits on the screen. */
5160 if (flags & XNegative)
5161 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5162 - width_diff
5163 - FRAME_PIXEL_WIDTH (f)
5164 + f->left_pos);
5166 if (flags & YNegative)
5167 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5168 - height_diff
5169 - FRAME_PIXEL_HEIGHT (f)
5170 + f->top_pos);
5172 /* The left_pos and top_pos
5173 are now relative to the top and left screen edges,
5174 so the flags should correspond. */
5175 f->size_hint_flags &= ~ (XNegative | YNegative);
5178 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5179 to really change the position, and 0 when calling from
5180 x_make_frame_visible (in that case, XOFF and YOFF are the current
5181 position values). It is -1 when calling from x_set_frame_parameters,
5182 which means, do adjust for borders but don't change the gravity. */
5184 void
5185 x_set_offset (f, xoff, yoff, change_gravity)
5186 struct frame *f;
5187 register int xoff, yoff;
5188 int change_gravity;
5190 if (change_gravity > 0)
5192 f->top_pos = yoff;
5193 f->left_pos = xoff;
5194 f->size_hint_flags &= ~ (XNegative | YNegative);
5195 if (xoff < 0)
5196 f->size_hint_flags |= XNegative;
5197 if (yoff < 0)
5198 f->size_hint_flags |= YNegative;
5199 f->win_gravity = NorthWestGravity;
5201 x_calc_absolute_position (f);
5203 BLOCK_INPUT;
5204 x_wm_set_size_hint (f, (long) 0, 0);
5206 #if TARGET_API_MAC_CARBON
5207 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5208 /* If the title bar is completely outside the screen, adjust the
5209 position. */
5210 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5211 kWindowConstrainMoveRegardlessOfFit
5212 | kWindowConstrainAllowPartial, NULL, NULL);
5213 x_real_positions (f, &f->left_pos, &f->top_pos);
5214 #else
5216 Rect inner, outer, screen_rect, dummy;
5217 RgnHandle region = NewRgn ();
5219 mac_get_window_bounds (f, &inner, &outer);
5220 f->x_pixels_diff = inner.left - outer.left;
5221 f->y_pixels_diff = inner.top - outer.top;
5222 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5223 f->top_pos + f->y_pixels_diff, false);
5225 /* If the title bar is completely outside the screen, adjust the
5226 position. The variable `outer' holds the title bar rectangle.
5227 The variable `inner' holds slightly smaller one than `outer',
5228 so that the calculation of overlapping may not become too
5229 strict. */
5230 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5231 outer = (*region)->rgnBBox;
5232 DisposeRgn (region);
5233 inner = outer;
5234 InsetRect (&inner, 8, 8);
5235 screen_rect = qd.screenBits.bounds;
5236 screen_rect.top += GetMBarHeight ();
5238 if (!SectRect (&inner, &screen_rect, &dummy))
5240 if (inner.right <= screen_rect.left)
5241 f->left_pos = screen_rect.left;
5242 else if (inner.left >= screen_rect.right)
5243 f->left_pos = screen_rect.right - (outer.right - outer.left);
5245 if (inner.bottom <= screen_rect.top)
5246 f->top_pos = screen_rect.top;
5247 else if (inner.top >= screen_rect.bottom)
5248 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5250 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5251 f->top_pos + f->y_pixels_diff, false);
5254 #endif
5256 UNBLOCK_INPUT;
5259 /* Call this to change the size of frame F's x-window.
5260 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5261 for this size change and subsequent size changes.
5262 Otherwise we leave the window gravity unchanged. */
5264 void
5265 x_set_window_size (f, change_gravity, cols, rows)
5266 struct frame *f;
5267 int change_gravity;
5268 int cols, rows;
5270 int pixelwidth, pixelheight;
5272 BLOCK_INPUT;
5274 check_frame_size (f, &rows, &cols);
5275 f->scroll_bar_actual_width
5276 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5278 compute_fringe_widths (f, 0);
5280 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5281 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5283 f->win_gravity = NorthWestGravity;
5284 x_wm_set_size_hint (f, (long) 0, 0);
5286 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5288 /* Now, strictly speaking, we can't be sure that this is accurate,
5289 but the window manager will get around to dealing with the size
5290 change request eventually, and we'll hear how it went when the
5291 ConfigureNotify event gets here.
5293 We could just not bother storing any of this information here,
5294 and let the ConfigureNotify event set everything up, but that
5295 might be kind of confusing to the Lisp code, since size changes
5296 wouldn't be reported in the frame parameters until some random
5297 point in the future when the ConfigureNotify event arrives.
5299 We pass 1 for DELAY since we can't run Lisp code inside of
5300 a BLOCK_INPUT. */
5301 change_frame_size (f, rows, cols, 0, 1, 0);
5302 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5303 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5305 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5306 receive in the ConfigureNotify event; if we get what we asked
5307 for, then the event won't cause the screen to become garbaged, so
5308 we have to make sure to do it here. */
5309 SET_FRAME_GARBAGED (f);
5311 XFlush (FRAME_X_DISPLAY (f));
5313 /* If cursor was outside the new size, mark it as off. */
5314 mark_window_cursors_off (XWINDOW (f->root_window));
5316 /* Clear out any recollection of where the mouse highlighting was,
5317 since it might be in a place that's outside the new frame size.
5318 Actually checking whether it is outside is a pain in the neck,
5319 so don't try--just let the highlighting be done afresh with new size. */
5320 cancel_mouse_face (f);
5322 UNBLOCK_INPUT;
5325 /* Mouse warping. */
5327 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5329 void
5330 x_set_mouse_position (f, x, y)
5331 struct frame *f;
5332 int x, y;
5334 int pix_x, pix_y;
5336 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5337 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5339 if (pix_x < 0) pix_x = 0;
5340 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5342 if (pix_y < 0) pix_y = 0;
5343 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5345 x_set_mouse_pixel_position (f, pix_x, pix_y);
5348 void
5349 x_set_mouse_pixel_position (f, pix_x, pix_y)
5350 struct frame *f;
5351 int pix_x, pix_y;
5353 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5354 BLOCK_INPUT;
5356 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5357 0, 0, 0, 0, pix_x, pix_y);
5358 UNBLOCK_INPUT;
5359 #endif
5363 /* focus shifting, raising and lowering. */
5365 void
5366 x_focus_on_frame (f)
5367 struct frame *f;
5369 #if 0 /* This proves to be unpleasant. */
5370 x_raise_frame (f);
5371 #endif
5372 #if 0
5373 /* I don't think that the ICCCM allows programs to do things like this
5374 without the interaction of the window manager. Whatever you end up
5375 doing with this code, do it to x_unfocus_frame too. */
5376 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5377 RevertToPointerRoot, CurrentTime);
5378 #endif /* ! 0 */
5381 void
5382 x_unfocus_frame (f)
5383 struct frame *f;
5387 /* Raise frame F. */
5388 void
5389 x_raise_frame (f)
5390 struct frame *f;
5392 if (f->async_visible)
5394 BLOCK_INPUT;
5395 SelectWindow (FRAME_MAC_WINDOW (f));
5396 UNBLOCK_INPUT;
5400 /* Lower frame F. */
5401 void
5402 x_lower_frame (f)
5403 struct frame *f;
5405 if (f->async_visible)
5407 BLOCK_INPUT;
5408 SendBehind (FRAME_MAC_WINDOW (f), nil);
5409 UNBLOCK_INPUT;
5413 static void
5414 XTframe_raise_lower (f, raise_flag)
5415 FRAME_PTR f;
5416 int raise_flag;
5418 if (raise_flag)
5419 x_raise_frame (f);
5420 else
5421 x_lower_frame (f);
5424 /* Change of visibility. */
5426 /* This tries to wait until the frame is really visible.
5427 However, if the window manager asks the user where to position
5428 the frame, this will return before the user finishes doing that.
5429 The frame will not actually be visible at that time,
5430 but it will become visible later when the window manager
5431 finishes with it. */
5433 void
5434 x_make_frame_visible (f)
5435 struct frame *f;
5437 Lisp_Object type;
5438 int original_top, original_left;
5440 BLOCK_INPUT;
5442 if (! FRAME_VISIBLE_P (f))
5444 /* We test FRAME_GARBAGED_P here to make sure we don't
5445 call x_set_offset a second time
5446 if we get to x_make_frame_visible a second time
5447 before the window gets really visible. */
5448 if (! FRAME_ICONIFIED_P (f)
5449 && ! f->output_data.mac->asked_for_visible)
5450 x_set_offset (f, f->left_pos, f->top_pos, 0);
5452 f->output_data.mac->asked_for_visible = 1;
5454 #if TARGET_API_MAC_CARBON
5455 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5457 struct frame *sf = SELECTED_FRAME ();
5458 if (!FRAME_MAC_P (sf))
5459 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5460 kWindowCenterOnMainScreen);
5461 else
5462 RepositionWindow (FRAME_MAC_WINDOW (f),
5463 FRAME_MAC_WINDOW (sf),
5464 #ifdef MAC_OS_X_VERSION_10_2
5465 kWindowCascadeStartAtParentWindowScreen
5466 #else
5467 kWindowCascadeOnParentWindowScreen
5468 #endif
5470 x_real_positions (f, &f->left_pos, &f->top_pos);
5472 #endif
5473 ShowWindow (FRAME_MAC_WINDOW (f));
5476 XFlush (FRAME_MAC_DISPLAY (f));
5478 /* Synchronize to ensure Emacs knows the frame is visible
5479 before we do anything else. We do this loop with input not blocked
5480 so that incoming events are handled. */
5482 Lisp_Object frame;
5483 int count;
5485 /* This must come after we set COUNT. */
5486 UNBLOCK_INPUT;
5488 XSETFRAME (frame, f);
5490 /* Wait until the frame is visible. Process X events until a
5491 MapNotify event has been seen, or until we think we won't get a
5492 MapNotify at all.. */
5493 for (count = input_signal_count + 10;
5494 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5496 /* Force processing of queued events. */
5497 x_sync (f);
5499 /* Machines that do polling rather than SIGIO have been
5500 observed to go into a busy-wait here. So we'll fake an
5501 alarm signal to let the handler know that there's something
5502 to be read. We used to raise a real alarm, but it seems
5503 that the handler isn't always enabled here. This is
5504 probably a bug. */
5505 if (input_polling_used ())
5507 /* It could be confusing if a real alarm arrives while
5508 processing the fake one. Turn it off and let the
5509 handler reset it. */
5510 extern void poll_for_input_1 P_ ((void));
5511 int old_poll_suppress_count = poll_suppress_count;
5512 poll_suppress_count = 1;
5513 poll_for_input_1 ();
5514 poll_suppress_count = old_poll_suppress_count;
5517 /* See if a MapNotify event has been processed. */
5518 FRAME_SAMPLE_VISIBILITY (f);
5523 /* Change from mapped state to withdrawn state. */
5525 /* Make the frame visible (mapped and not iconified). */
5527 void
5528 x_make_frame_invisible (f)
5529 struct frame *f;
5531 /* Don't keep the highlight on an invisible frame. */
5532 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5533 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5535 BLOCK_INPUT;
5537 HideWindow (FRAME_MAC_WINDOW (f));
5539 /* We can't distinguish this from iconification
5540 just by the event that we get from the server.
5541 So we can't win using the usual strategy of letting
5542 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5543 and synchronize with the server to make sure we agree. */
5544 f->visible = 0;
5545 FRAME_ICONIFIED_P (f) = 0;
5546 f->async_visible = 0;
5547 f->async_iconified = 0;
5549 UNBLOCK_INPUT;
5552 /* Change window state from mapped to iconified. */
5554 void
5555 x_iconify_frame (f)
5556 struct frame *f;
5558 /* Don't keep the highlight on an invisible frame. */
5559 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5560 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5562 #if 0
5563 /* Review: Since window is still visible in dock, still allow updates? */
5564 if (f->async_iconified)
5565 return;
5566 #endif
5568 BLOCK_INPUT;
5570 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5572 UNBLOCK_INPUT;
5576 /* Free X resources of frame F. */
5578 void
5579 x_free_frame_resources (f)
5580 struct frame *f;
5582 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5583 WindowPtr wp = FRAME_MAC_WINDOW (f);
5585 BLOCK_INPUT;
5587 DisposeWindow (wp);
5588 if (wp == tip_window)
5589 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5590 closed' event. So we reset tip_window here. */
5591 tip_window = NULL;
5593 free_frame_menubar (f);
5595 if (FRAME_FACE_CACHE (f))
5596 free_frame_faces (f);
5598 x_free_gcs (f);
5600 if (FRAME_SIZE_HINTS (f))
5601 xfree (FRAME_SIZE_HINTS (f));
5603 xfree (f->output_data.mac);
5604 f->output_data.mac = NULL;
5606 if (f == dpyinfo->x_focus_frame)
5607 dpyinfo->x_focus_frame = 0;
5608 if (f == dpyinfo->x_focus_event_frame)
5609 dpyinfo->x_focus_event_frame = 0;
5610 if (f == dpyinfo->x_highlight_frame)
5611 dpyinfo->x_highlight_frame = 0;
5613 if (f == dpyinfo->mouse_face_mouse_frame)
5615 dpyinfo->mouse_face_beg_row
5616 = dpyinfo->mouse_face_beg_col = -1;
5617 dpyinfo->mouse_face_end_row
5618 = dpyinfo->mouse_face_end_col = -1;
5619 dpyinfo->mouse_face_window = Qnil;
5620 dpyinfo->mouse_face_deferred_gc = 0;
5621 dpyinfo->mouse_face_mouse_frame = 0;
5624 UNBLOCK_INPUT;
5628 /* Destroy the X window of frame F. */
5630 void
5631 x_destroy_window (f)
5632 struct frame *f;
5634 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5636 x_free_frame_resources (f);
5638 dpyinfo->reference_count--;
5642 /* Setting window manager hints. */
5644 /* Set the normal size hints for the window manager, for frame F.
5645 FLAGS is the flags word to use--or 0 meaning preserve the flags
5646 that the window now has.
5647 If USER_POSITION is nonzero, we set the USPosition
5648 flag (this is useful when FLAGS is 0). */
5649 void
5650 x_wm_set_size_hint (f, flags, user_position)
5651 struct frame *f;
5652 long flags;
5653 int user_position;
5655 int base_width, base_height, width_inc, height_inc;
5656 int min_rows = 0, min_cols = 0;
5657 XSizeHints *size_hints;
5659 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5660 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5661 width_inc = FRAME_COLUMN_WIDTH (f);
5662 height_inc = FRAME_LINE_HEIGHT (f);
5664 check_frame_size (f, &min_rows, &min_cols);
5666 size_hints = FRAME_SIZE_HINTS (f);
5667 if (size_hints == NULL)
5669 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
5670 bzero (size_hints, sizeof (XSizeHints));
5673 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
5674 size_hints->width_inc = width_inc;
5675 size_hints->height_inc = height_inc;
5676 size_hints->min_width = base_width + min_cols * width_inc;
5677 size_hints->min_height = base_height + min_rows * height_inc;
5678 size_hints->base_width = base_width;
5679 size_hints->base_height = base_height;
5681 if (flags)
5682 size_hints->flags = flags;
5683 else if (user_position)
5685 size_hints->flags &= ~ PPosition;
5686 size_hints->flags |= USPosition;
5690 #if 0 /* MAC_TODO: hide application instead of iconify? */
5691 /* Used for IconicState or NormalState */
5693 void
5694 x_wm_set_window_state (f, state)
5695 struct frame *f;
5696 int state;
5698 #ifdef USE_X_TOOLKIT
5699 Arg al[1];
5701 XtSetArg (al[0], XtNinitialState, state);
5702 XtSetValues (f->output_data.x->widget, al, 1);
5703 #else /* not USE_X_TOOLKIT */
5704 Window window = FRAME_X_WINDOW (f);
5706 f->output_data.x->wm_hints.flags |= StateHint;
5707 f->output_data.x->wm_hints.initial_state = state;
5709 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5710 #endif /* not USE_X_TOOLKIT */
5713 void
5714 x_wm_set_icon_pixmap (f, pixmap_id)
5715 struct frame *f;
5716 int pixmap_id;
5718 Pixmap icon_pixmap;
5720 #ifndef USE_X_TOOLKIT
5721 Window window = FRAME_X_WINDOW (f);
5722 #endif
5724 if (pixmap_id > 0)
5726 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5727 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5729 else
5731 /* It seems there is no way to turn off use of an icon pixmap.
5732 The following line does it, only if no icon has yet been created,
5733 for some window managers. But with mwm it crashes.
5734 Some people say it should clear the IconPixmapHint bit in this case,
5735 but that doesn't work, and the X consortium said it isn't the
5736 right thing at all. Since there is no way to win,
5737 best to explicitly give up. */
5738 #if 0
5739 f->output_data.x->wm_hints.icon_pixmap = None;
5740 #else
5741 return;
5742 #endif
5745 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5748 Arg al[1];
5749 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5750 XtSetValues (f->output_data.x->widget, al, 1);
5753 #else /* not USE_X_TOOLKIT */
5755 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5756 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5758 #endif /* not USE_X_TOOLKIT */
5761 #endif /* MAC_TODO */
5763 void
5764 x_wm_set_icon_position (f, icon_x, icon_y)
5765 struct frame *f;
5766 int icon_x, icon_y;
5768 #if 0 /* MAC_TODO: no icons on Mac */
5769 #ifdef USE_X_TOOLKIT
5770 Window window = XtWindow (f->output_data.x->widget);
5771 #else
5772 Window window = FRAME_X_WINDOW (f);
5773 #endif
5775 f->output_data.x->wm_hints.flags |= IconPositionHint;
5776 f->output_data.x->wm_hints.icon_x = icon_x;
5777 f->output_data.x->wm_hints.icon_y = icon_y;
5779 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5780 #endif /* MAC_TODO */
5784 /***********************************************************************
5785 Fonts
5786 ***********************************************************************/
5788 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5790 struct font_info *
5791 x_get_font_info (f, font_idx)
5792 FRAME_PTR f;
5793 int font_idx;
5795 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5798 /* the global font name table */
5799 char **font_name_table = NULL;
5800 int font_name_table_size = 0;
5801 int font_name_count = 0;
5803 #if 0
5804 /* compare two strings ignoring case */
5805 static int
5806 stricmp (const char *s, const char *t)
5808 for ( ; tolower (*s) == tolower (*t); s++, t++)
5809 if (*s == '\0')
5810 return 0;
5811 return tolower (*s) - tolower (*t);
5814 /* compare two strings ignoring case and handling wildcard */
5815 static int
5816 wildstrieq (char *s1, char *s2)
5818 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5819 return true;
5821 return stricmp (s1, s2) == 0;
5824 /* Assume parameter 1 is fully qualified, no wildcards. */
5825 static int
5826 mac_font_pattern_match (fontname, pattern)
5827 char * fontname;
5828 char * pattern;
5830 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5831 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5832 char *ptr;
5834 /* Copy fontname so we can modify it during comparison. */
5835 strcpy (font_name_copy, fontname);
5837 ptr = regex;
5838 *ptr++ = '^';
5840 /* Turn pattern into a regexp and do a regexp match. */
5841 for (; *pattern; pattern++)
5843 if (*pattern == '?')
5844 *ptr++ = '.';
5845 else if (*pattern == '*')
5847 *ptr++ = '.';
5848 *ptr++ = '*';
5850 else
5851 *ptr++ = *pattern;
5853 *ptr = '$';
5854 *(ptr + 1) = '\0';
5856 return (fast_c_string_match_ignore_case (build_string (regex),
5857 font_name_copy) >= 0);
5860 /* Two font specs are considered to match if their foundry, family,
5861 weight, slant, and charset match. */
5862 static int
5863 mac_font_match (char *mf, char *xf)
5865 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5866 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5868 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5869 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5870 return mac_font_pattern_match (mf, xf);
5872 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5873 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5874 return mac_font_pattern_match (mf, xf);
5876 return (wildstrieq (m_foundry, x_foundry)
5877 && wildstrieq (m_family, x_family)
5878 && wildstrieq (m_weight, x_weight)
5879 && wildstrieq (m_slant, x_slant)
5880 && wildstrieq (m_charset, x_charset))
5881 || mac_font_pattern_match (mf, xf);
5883 #endif
5885 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5887 static void
5888 decode_mac_font_name (name, size, scriptcode)
5889 char *name;
5890 int size;
5891 #if TARGET_API_MAC_CARBON
5892 int scriptcode;
5893 #else
5894 short scriptcode;
5895 #endif
5897 Lisp_Object coding_system;
5898 struct coding_system coding;
5899 char *buf;
5901 switch (scriptcode)
5903 case smTradChinese:
5904 coding_system = Qbig5;
5905 break;
5906 case smSimpChinese:
5907 coding_system = Qcn_gb;
5908 break;
5909 case smJapanese:
5910 coding_system = Qsjis;
5911 break;
5912 case smKorean:
5913 coding_system = Qeuc_kr;
5914 break;
5915 default:
5916 return;
5919 setup_coding_system (coding_system, &coding);
5920 coding.src_multibyte = 0;
5921 coding.dst_multibyte = 1;
5922 coding.mode |= CODING_MODE_LAST_BLOCK;
5923 coding.composing = COMPOSITION_DISABLED;
5924 buf = (char *) alloca (size);
5926 decode_coding (&coding, name, buf, strlen (name), size - 1);
5927 bcopy (buf, name, coding.produced);
5928 name[coding.produced] = '\0';
5932 static char *
5933 mac_to_x_fontname (name, size, style, scriptcode)
5934 char *name;
5935 int size;
5936 Style style;
5937 #if TARGET_API_MAC_CARBON
5938 int scriptcode;
5939 #else
5940 short scriptcode;
5941 #endif
5943 char foundry[32], family[32], cs[32];
5944 char xf[256], *result, *p;
5946 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5948 strcpy(foundry, "Apple");
5949 strcpy(family, name);
5951 switch (scriptcode)
5953 case smTradChinese: /* == kTextEncodingMacChineseTrad */
5954 strcpy(cs, "big5-0");
5955 break;
5956 case smSimpChinese: /* == kTextEncodingMacChineseSimp */
5957 strcpy(cs, "gb2312.1980-0");
5958 break;
5959 case smJapanese: /* == kTextEncodingMacJapanese */
5960 strcpy(cs, "jisx0208.1983-sjis");
5961 break;
5962 case -smJapanese:
5963 /* Each Apple Japanese font is entered into the font table
5964 twice: once as a jisx0208.1983-sjis font and once as a
5965 jisx0201.1976-0 font. The latter can be used to display
5966 the ascii charset and katakana-jisx0201 charset. A
5967 negative script code signals that the name of this latter
5968 font is being built. */
5969 strcpy(cs, "jisx0201.1976-0");
5970 break;
5971 case smKorean: /* == kTextEncodingMacKorean */
5972 strcpy(cs, "ksc5601.1989-0");
5973 break;
5974 #if TARGET_API_MAC_CARBON
5975 case kTextEncodingMacCyrillic:
5976 strcpy(cs, "mac-cyrillic");
5977 break;
5978 case kTextEncodingMacCentralEurRoman:
5979 strcpy(cs, "mac-centraleurroman");
5980 break;
5981 case kTextEncodingMacSymbol:
5982 case kTextEncodingMacDingbats:
5983 strcpy(cs, "adobe-fontspecific");
5984 break;
5985 #endif
5986 default:
5987 strcpy(cs, "mac-roman");
5988 break;
5992 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5993 foundry, family, style & bold ? "bold" : "medium",
5994 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5996 result = (char *) xmalloc (strlen (xf) + 1);
5997 strcpy (result, xf);
5998 for (p = result; *p; p++)
5999 *p = tolower(*p);
6000 return result;
6004 /* Convert an X font spec to the corresponding mac font name, which
6005 can then be passed to GetFNum after conversion to a Pascal string.
6006 For ordinary Mac fonts, this should just be their names, like
6007 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6008 collection contain their charset designation in their names, like
6009 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6010 names are handled accordingly. */
6011 static void
6012 x_font_name_to_mac_font_name (char *xf, char *mf)
6014 char foundry[32], family[32], weight[20], slant[2], cs[32];
6015 Lisp_Object coding_system = Qnil;
6016 struct coding_system coding;
6018 strcpy (mf, "");
6020 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6021 foundry, family, weight, slant, cs) != 5 &&
6022 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6023 foundry, family, weight, slant, cs) != 5)
6024 return;
6026 if (strcmp (cs, "big5-0") == 0)
6027 coding_system = Qbig5;
6028 else if (strcmp (cs, "gb2312.1980-0") == 0)
6029 coding_system = Qcn_gb;
6030 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
6031 || strcmp (cs, "jisx0201.1976-0") == 0)
6032 coding_system = Qsjis;
6033 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6034 coding_system = Qeuc_kr;
6035 else if (strcmp (cs, "mac-roman") == 0
6036 || strcmp (cs, "mac-cyrillic") == 0
6037 || strcmp (cs, "mac-centraleurroman") == 0
6038 || strcmp (cs, "adobe-fontspecific") == 0)
6039 strcpy (mf, family);
6040 else
6041 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6043 if (!NILP (coding_system))
6045 setup_coding_system (coding_system, &coding);
6046 coding.src_multibyte = 1;
6047 coding.dst_multibyte = 1;
6048 coding.mode |= CODING_MODE_LAST_BLOCK;
6049 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6050 mf[coding.produced] = '\0';
6055 static void
6056 add_font_name_table_entry (char *font_name)
6058 if (font_name_table_size == 0)
6060 font_name_table_size = 16;
6061 font_name_table = (char **)
6062 xmalloc (font_name_table_size * sizeof (char *));
6064 else if (font_name_count + 1 >= font_name_table_size)
6066 font_name_table_size += 16;
6067 font_name_table = (char **)
6068 xrealloc (font_name_table,
6069 font_name_table_size * sizeof (char *));
6072 font_name_table[font_name_count++] = font_name;
6075 /* Sets up the table font_name_table to contain the list of all fonts
6076 in the system the first time the table is used so that the Resource
6077 Manager need not be accessed every time this information is
6078 needed. */
6080 static void
6081 init_font_name_table ()
6083 #if TARGET_API_MAC_CARBON
6084 SInt32 sv;
6086 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6088 FMFontFamilyIterator ffi;
6089 FMFontFamilyInstanceIterator ffii;
6090 FMFontFamily ff;
6092 /* Create a dummy instance iterator here to avoid creating and
6093 destroying it in the loop. */
6094 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6095 return;
6096 /* Create an iterator to enumerate the font families. */
6097 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6098 != noErr)
6100 FMDisposeFontFamilyInstanceIterator (&ffii);
6101 return;
6104 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6106 Str255 name;
6107 FMFont font;
6108 FMFontStyle style;
6109 FMFontSize size;
6110 TextEncoding encoding;
6111 TextEncodingBase sc;
6113 if (FMGetFontFamilyName (ff, name) != noErr)
6114 break;
6115 p2cstr (name);
6116 if (*name == '.')
6117 continue;
6119 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6120 break;
6121 sc = GetTextEncodingBase (encoding);
6122 decode_mac_font_name (name, sizeof (name), sc);
6124 /* Point the instance iterator at the current font family. */
6125 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6126 break;
6128 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6129 == noErr)
6131 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6132 contained in Apple Japanese (SJIS) font. */
6133 again:
6134 if (size == 0)
6136 add_font_name_table_entry (mac_to_x_fontname (name, size,
6137 style, sc));
6138 add_font_name_table_entry (mac_to_x_fontname (name, size,
6139 italic, sc));
6140 add_font_name_table_entry (mac_to_x_fontname (name, size,
6141 bold, sc));
6142 add_font_name_table_entry (mac_to_x_fontname (name, size,
6143 italic | bold,
6144 sc));
6146 else
6147 add_font_name_table_entry (mac_to_x_fontname (name, size,
6148 style, sc));
6149 if (sc == smJapanese)
6151 sc = -smJapanese;
6152 goto again;
6154 else if (sc == -smJapanese)
6155 sc = smJapanese;
6159 /* Dispose of the iterators. */
6160 FMDisposeFontFamilyIterator (&ffi);
6161 FMDisposeFontFamilyInstanceIterator (&ffii);
6163 else
6165 #endif /* TARGET_API_MAC_CARBON */
6166 GrafPtr port;
6167 SInt16 fontnum, old_fontnum;
6168 int num_mac_fonts = CountResources('FOND');
6169 int i, j;
6170 Handle font_handle, font_handle_2;
6171 short id, scriptcode;
6172 ResType type;
6173 Str32 name;
6174 struct FontAssoc *fat;
6175 struct AsscEntry *assc_entry;
6177 GetPort (&port); /* save the current font number used */
6178 #if TARGET_API_MAC_CARBON
6179 old_fontnum = GetPortTextFont (port);
6180 #else
6181 old_fontnum = port->txFont;
6182 #endif
6184 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6186 font_handle = GetIndResource ('FOND', i);
6187 if (!font_handle)
6188 continue;
6190 GetResInfo (font_handle, &id, &type, name);
6191 GetFNum (name, &fontnum);
6192 p2cstr (name);
6193 if (fontnum == 0)
6194 continue;
6196 TextFont (fontnum);
6197 scriptcode = FontToScript (fontnum);
6198 decode_mac_font_name (name, sizeof (name), scriptcode);
6201 HLock (font_handle);
6203 if (GetResourceSizeOnDisk (font_handle)
6204 >= sizeof (struct FamRec))
6206 fat = (struct FontAssoc *) (*font_handle
6207 + sizeof (struct FamRec));
6208 assc_entry
6209 = (struct AsscEntry *) (*font_handle
6210 + sizeof (struct FamRec)
6211 + sizeof (struct FontAssoc));
6213 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6215 if (font_name_table_size == 0)
6217 font_name_table_size = 16;
6218 font_name_table = (char **)
6219 xmalloc (font_name_table_size * sizeof (char *));
6221 else if (font_name_count >= font_name_table_size)
6223 font_name_table_size += 16;
6224 font_name_table = (char **)
6225 xrealloc (font_name_table,
6226 font_name_table_size * sizeof (char *));
6228 font_name_table[font_name_count++]
6229 = mac_to_x_fontname (name,
6230 assc_entry->fontSize,
6231 assc_entry->fontStyle,
6232 scriptcode);
6233 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6234 parts are contained in Apple Japanese (SJIS)
6235 font. */
6236 if (smJapanese == scriptcode)
6238 font_name_table[font_name_count++]
6239 = mac_to_x_fontname (name,
6240 assc_entry->fontSize,
6241 assc_entry->fontStyle,
6242 -smJapanese);
6247 HUnlock (font_handle);
6248 font_handle_2 = GetNextFOND (font_handle);
6249 ReleaseResource (font_handle);
6250 font_handle = font_handle_2;
6252 while (ResError () == noErr && font_handle);
6255 TextFont (old_fontnum);
6256 #if TARGET_API_MAC_CARBON
6258 #endif /* TARGET_API_MAC_CARBON */
6262 void
6263 mac_clear_font_name_table ()
6265 int i;
6267 for (i = 0; i < font_name_count; i++)
6268 xfree (font_name_table[i]);
6269 xfree (font_name_table);
6270 font_name_table = NULL;
6271 font_name_table_size = font_name_count = 0;
6275 enum xlfd_scalable_field_index
6277 XLFD_SCL_PIXEL_SIZE,
6278 XLFD_SCL_POINT_SIZE,
6279 XLFD_SCL_AVGWIDTH,
6280 XLFD_SCL_LAST
6283 static int xlfd_scalable_fields[] =
6285 6, /* PIXEL_SIZE */
6286 7, /* POINT_SIZE */
6287 11, /* AVGWIDTH */
6291 static Lisp_Object
6292 mac_c_string_match (regexp, string, nonspecial, exact)
6293 Lisp_Object regexp;
6294 const char *string, *nonspecial;
6295 int exact;
6297 if (exact)
6299 if (strcmp (string, nonspecial) == 0)
6300 return build_string (string);
6302 else if (strstr (string, nonspecial))
6304 Lisp_Object str = build_string (string);
6306 if (fast_string_match (regexp, str) >= 0)
6307 return str;
6310 return Qnil;
6313 static Lisp_Object
6314 mac_do_list_fonts (pattern, maxnames)
6315 char *pattern;
6316 int maxnames;
6318 int i, n_fonts = 0;
6319 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6320 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6321 char scaled[256];
6322 char *ptr;
6323 int scl_val[XLFD_SCL_LAST], *field, *val;
6324 char *longest_start, *cur_start, *nonspecial;
6325 int longest_len, exact;
6327 if (font_name_table == NULL) /* Initialize when first used. */
6328 init_font_name_table ();
6330 for (i = 0; i < XLFD_SCL_LAST; i++)
6331 scl_val[i] = -1;
6333 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6334 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6335 fonts are scaled according to the specified size. */
6336 ptr = pattern;
6337 i = 0;
6338 field = xlfd_scalable_fields;
6339 val = scl_val;
6340 if (*ptr == '-')
6343 ptr++;
6344 if (i == *field)
6346 if ('1' <= *ptr && *ptr <= '9')
6348 *val = *ptr++ - '0';
6349 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6350 *val = *val * 10 + *ptr++ - '0';
6351 if (*ptr != '-')
6352 *val = -1;
6354 field++;
6355 val++;
6357 ptr = strchr (ptr, '-');
6358 i++;
6360 while (ptr && i < 14);
6362 if (i == 14 && ptr == NULL)
6364 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6366 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6367 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6369 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6371 scl_val[XLFD_SCL_POINT_SIZE] =
6372 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6374 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6376 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6377 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6380 else
6381 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6383 ptr = regex;
6384 *ptr++ = '^';
6386 longest_start = cur_start = ptr;
6387 longest_len = 0;
6388 exact = 1;
6390 /* Turn pattern into a regexp and do a regexp match. Also find the
6391 longest substring containing no special characters. */
6392 for (; *pattern; pattern++)
6394 if (*pattern == '?' || *pattern == '*')
6396 if (ptr - cur_start > longest_len)
6398 longest_start = cur_start;
6399 longest_len = ptr - cur_start;
6401 exact = 0;
6403 if (*pattern == '?')
6404 *ptr++ = '.';
6405 else /* if (*pattern == '*') */
6407 *ptr++ = '.';
6408 *ptr++ = '*';
6410 cur_start = ptr;
6412 else
6413 *ptr++ = tolower (*pattern);
6416 if (ptr - cur_start > longest_len)
6418 longest_start = cur_start;
6419 longest_len = ptr - cur_start;
6422 *ptr = '$';
6423 *(ptr + 1) = '\0';
6425 nonspecial = xmalloc (longest_len + 1);
6426 strncpy (nonspecial, longest_start, longest_len);
6427 nonspecial[longest_len] = '\0';
6429 pattern_regex = build_string (regex);
6431 for (i = 0; i < font_name_count; i++)
6433 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6434 nonspecial, exact);
6435 if (!NILP (fontname))
6437 font_list = Fcons (fontname, font_list);
6438 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6439 break;
6441 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6442 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6444 int former_len = ptr - font_name_table[i];
6446 memcpy (scaled, font_name_table[i], former_len);
6447 sprintf (scaled + former_len,
6448 "-%d-%d-75-75-m-%d-%s",
6449 scl_val[XLFD_SCL_PIXEL_SIZE],
6450 scl_val[XLFD_SCL_POINT_SIZE],
6451 scl_val[XLFD_SCL_AVGWIDTH],
6452 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6453 fontname = mac_c_string_match (pattern_regex, scaled,
6454 nonspecial, exact);
6455 if (!NILP (fontname))
6457 font_list = Fcons (fontname, font_list);
6458 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6459 break;
6464 xfree (nonspecial);
6466 return font_list;
6469 /* Return a list of at most MAXNAMES font specs matching the one in
6470 PATTERN. Cache matching fonts for patterns in
6471 dpyinfo->name_list_element to avoid looking them up again by
6472 calling mac_font_pattern_match (slow). Return as many matching
6473 fonts as possible if MAXNAMES = -1. */
6475 Lisp_Object
6476 x_list_fonts (struct frame *f,
6477 Lisp_Object pattern,
6478 int size,
6479 int maxnames)
6481 Lisp_Object newlist = Qnil, tem, key;
6482 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6484 if (dpyinfo)
6486 tem = XCDR (dpyinfo->name_list_element);
6487 key = Fcons (pattern, make_number (maxnames));
6489 newlist = Fassoc (key, tem);
6490 if (!NILP (newlist))
6492 newlist = Fcdr_safe (newlist);
6493 goto label_cached;
6497 BLOCK_INPUT;
6498 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6499 UNBLOCK_INPUT;
6501 /* MAC_TODO: add code for matching outline fonts here */
6503 if (dpyinfo)
6505 XSETCDR (dpyinfo->name_list_element,
6506 Fcons (Fcons (key, newlist),
6507 XCDR (dpyinfo->name_list_element)));
6509 label_cached:
6511 return newlist;
6515 #if GLYPH_DEBUG
6517 /* Check that FONT is valid on frame F. It is if it can be found in F's
6518 font table. */
6520 static void
6521 x_check_font (f, font)
6522 struct frame *f;
6523 XFontStruct *font;
6525 int i;
6526 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6528 xassert (font != NULL);
6530 for (i = 0; i < dpyinfo->n_fonts; i++)
6531 if (dpyinfo->font_table[i].name
6532 && font == dpyinfo->font_table[i].font)
6533 break;
6535 xassert (i < dpyinfo->n_fonts);
6538 #endif /* GLYPH_DEBUG != 0 */
6540 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6541 Note: There are (broken) X fonts out there with invalid XFontStruct
6542 min_bounds contents. For example, handa@etl.go.jp reports that
6543 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6544 have font->min_bounds.width == 0. */
6546 static INLINE void
6547 x_font_min_bounds (font, w, h)
6548 MacFontStruct *font;
6549 int *w, *h;
6551 *h = FONT_HEIGHT (font);
6552 *w = font->min_bounds.width;
6556 /* Compute the smallest character width and smallest font height over
6557 all fonts available on frame F. Set the members smallest_char_width
6558 and smallest_font_height in F's x_display_info structure to
6559 the values computed. Value is non-zero if smallest_font_height or
6560 smallest_char_width become smaller than they were before. */
6563 x_compute_min_glyph_bounds (f)
6564 struct frame *f;
6566 int i;
6567 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6568 MacFontStruct *font;
6569 int old_width = dpyinfo->smallest_char_width;
6570 int old_height = dpyinfo->smallest_font_height;
6572 dpyinfo->smallest_font_height = 100000;
6573 dpyinfo->smallest_char_width = 100000;
6575 for (i = 0; i < dpyinfo->n_fonts; ++i)
6576 if (dpyinfo->font_table[i].name)
6578 struct font_info *fontp = dpyinfo->font_table + i;
6579 int w, h;
6581 font = (MacFontStruct *) fontp->font;
6582 xassert (font != (MacFontStruct *) ~0);
6583 x_font_min_bounds (font, &w, &h);
6585 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6586 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6589 xassert (dpyinfo->smallest_char_width > 0
6590 && dpyinfo->smallest_font_height > 0);
6592 return (dpyinfo->n_fonts == 1
6593 || dpyinfo->smallest_char_width < old_width
6594 || dpyinfo->smallest_font_height < old_height);
6598 /* Determine whether given string is a fully-specified XLFD: all 14
6599 fields are present, none is '*'. */
6601 static int
6602 is_fully_specified_xlfd (char *p)
6604 int i;
6605 char *q;
6607 if (*p != '-')
6608 return 0;
6610 for (i = 0; i < 13; i++)
6612 q = strchr (p + 1, '-');
6613 if (q == NULL)
6614 return 0;
6615 if (q - p == 2 && *(p + 1) == '*')
6616 return 0;
6617 p = q;
6620 if (strchr (p + 1, '-') != NULL)
6621 return 0;
6623 if (*(p + 1) == '*' && *(p + 2) == '\0')
6624 return 0;
6626 return 1;
6630 const int kDefaultFontSize = 9;
6633 /* XLoadQueryFont creates and returns an internal representation for a
6634 font in a MacFontStruct struct. There is really no concept
6635 corresponding to "loading" a font on the Mac. But we check its
6636 existence and find the font number and all other information for it
6637 and store them in the returned MacFontStruct. */
6639 static MacFontStruct *
6640 XLoadQueryFont (Display *dpy, char *fontname)
6642 int i, size, is_two_byte_font, char_width;
6643 char *name;
6644 GrafPtr port;
6645 SInt16 old_fontnum, old_fontsize;
6646 Style old_fontface;
6647 Str32 mfontname;
6648 SInt16 fontnum;
6649 Style fontface = normal;
6650 MacFontStruct *font;
6651 FontInfo the_fontinfo;
6652 char s_weight[7], c_slant;
6654 if (is_fully_specified_xlfd (fontname))
6655 name = fontname;
6656 else
6658 Lisp_Object matched_fonts;
6660 matched_fonts = mac_do_list_fonts (fontname, 1);
6661 if (NILP (matched_fonts))
6662 return NULL;
6663 name = SDATA (XCAR (matched_fonts));
6666 GetPort (&port); /* save the current font number used */
6667 #if TARGET_API_MAC_CARBON
6668 old_fontnum = GetPortTextFont (port);
6669 old_fontsize = GetPortTextSize (port);
6670 old_fontface = GetPortTextFace (port);
6671 #else
6672 old_fontnum = port->txFont;
6673 old_fontsize = port->txSize;
6674 old_fontface = port->txFace;
6675 #endif
6677 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6678 size = kDefaultFontSize;
6680 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6681 if (strcmp (s_weight, "bold") == 0)
6682 fontface |= bold;
6684 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6685 if (c_slant == 'i')
6686 fontface |= italic;
6688 x_font_name_to_mac_font_name (name, mfontname);
6689 c2pstr (mfontname);
6690 GetFNum (mfontname, &fontnum);
6691 if (fontnum == 0)
6692 return NULL;
6694 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6696 font->fontname = (char *) xmalloc (strlen (name) + 1);
6697 bcopy (name, font->fontname, strlen (name) + 1);
6699 font->mac_fontnum = fontnum;
6700 font->mac_fontsize = size;
6701 font->mac_fontface = fontface;
6702 font->mac_scriptcode = FontToScript (fontnum);
6704 /* Apple Japanese (SJIS) font is listed as both
6705 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6706 (Roman script) in init_font_name_table (). The latter should be
6707 treated as a one-byte font. */
6709 char cs[32];
6711 if (sscanf (name,
6712 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6713 cs) == 1
6714 && 0 == strcmp (cs, "jisx0201.1976-0"))
6715 font->mac_scriptcode = smRoman;
6718 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6719 font->mac_scriptcode == smTradChinese ||
6720 font->mac_scriptcode == smSimpChinese ||
6721 font->mac_scriptcode == smKorean;
6723 TextFont (fontnum);
6724 TextSize (size);
6725 TextFace (fontface);
6727 GetFontInfo (&the_fontinfo);
6729 font->ascent = the_fontinfo.ascent;
6730 font->descent = the_fontinfo.descent;
6732 font->min_byte1 = 0;
6733 if (is_two_byte_font)
6734 font->max_byte1 = 1;
6735 else
6736 font->max_byte1 = 0;
6737 font->min_char_or_byte2 = 0x20;
6738 font->max_char_or_byte2 = 0xff;
6740 if (is_two_byte_font)
6742 /* Use the width of an "ideographic space" of that font because
6743 the_fontinfo.widMax returns the wrong width for some fonts. */
6744 switch (font->mac_scriptcode)
6746 case smJapanese:
6747 char_width = StringWidth("\p\x81\x40");
6748 break;
6749 case smTradChinese:
6750 char_width = StringWidth("\p\xa1\x40");
6751 break;
6752 case smSimpChinese:
6753 char_width = StringWidth("\p\xa1\xa1");
6754 break;
6755 case smKorean:
6756 char_width = StringWidth("\p\xa1\xa1");
6757 break;
6760 else
6761 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6762 returns 15 for 12-point Monaco! */
6763 char_width = CharWidth ('m');
6765 font->max_bounds.rbearing = char_width;
6766 font->max_bounds.lbearing = 0;
6767 font->max_bounds.width = char_width;
6768 font->max_bounds.ascent = the_fontinfo.ascent;
6769 font->max_bounds.descent = the_fontinfo.descent;
6771 font->min_bounds = font->max_bounds;
6773 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6774 font->per_char = NULL;
6775 else
6777 font->per_char = (XCharStruct *)
6778 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6780 int c, min_width, max_width;
6782 min_width = max_width = char_width;
6783 for (c = 0x20; c <= 0xff; c++)
6785 font->per_char[c - 0x20] = font->max_bounds;
6786 char_width = CharWidth (c);
6787 font->per_char[c - 0x20].width = char_width;
6788 font->per_char[c - 0x20].rbearing = char_width;
6789 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6790 character width of 0x7f. */
6791 if (char_width > 0)
6793 min_width = min (min_width, char_width);
6794 max_width = max (max_width, char_width);
6797 font->min_bounds.width = min_width;
6798 font->max_bounds.width = max_width;
6802 TextFont (old_fontnum); /* restore previous font number, size and face */
6803 TextSize (old_fontsize);
6804 TextFace (old_fontface);
6806 return font;
6810 void
6811 mac_unload_font (dpyinfo, font)
6812 struct mac_display_info *dpyinfo;
6813 XFontStruct *font;
6815 xfree (font->fontname);
6816 if (font->per_char)
6817 xfree (font->per_char);
6818 xfree (font);
6822 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6823 pointer to the structure font_info while allocating it dynamically.
6824 If SIZE is 0, load any size of font.
6825 If loading is failed, return NULL. */
6827 struct font_info *
6828 x_load_font (f, fontname, size)
6829 struct frame *f;
6830 register char *fontname;
6831 int size;
6833 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6834 Lisp_Object font_names;
6836 /* Get a list of all the fonts that match this name. Once we
6837 have a list of matching fonts, we compare them against the fonts
6838 we already have by comparing names. */
6839 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6841 if (!NILP (font_names))
6843 Lisp_Object tail;
6844 int i;
6846 for (i = 0; i < dpyinfo->n_fonts; i++)
6847 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6848 if (dpyinfo->font_table[i].name
6849 && (!strcmp (dpyinfo->font_table[i].name,
6850 SDATA (XCAR (tail)))
6851 || !strcmp (dpyinfo->font_table[i].full_name,
6852 SDATA (XCAR (tail)))))
6853 return (dpyinfo->font_table + i);
6856 /* Load the font and add it to the table. */
6858 char *full_name;
6859 struct MacFontStruct *font;
6860 struct font_info *fontp;
6861 unsigned long value;
6862 int i;
6864 /* If we have found fonts by x_list_font, load one of them. If
6865 not, we still try to load a font by the name given as FONTNAME
6866 because XListFonts (called in x_list_font) of some X server has
6867 a bug of not finding a font even if the font surely exists and
6868 is loadable by XLoadQueryFont. */
6869 if (size > 0 && !NILP (font_names))
6870 fontname = (char *) SDATA (XCAR (font_names));
6872 BLOCK_INPUT;
6873 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6874 UNBLOCK_INPUT;
6875 if (!font)
6876 return NULL;
6878 /* Find a free slot in the font table. */
6879 for (i = 0; i < dpyinfo->n_fonts; ++i)
6880 if (dpyinfo->font_table[i].name == NULL)
6881 break;
6883 /* If no free slot found, maybe enlarge the font table. */
6884 if (i == dpyinfo->n_fonts
6885 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6887 int sz;
6888 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6889 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6890 dpyinfo->font_table
6891 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6894 fontp = dpyinfo->font_table + i;
6895 if (i == dpyinfo->n_fonts)
6896 ++dpyinfo->n_fonts;
6898 /* Now fill in the slots of *FONTP. */
6899 BLOCK_INPUT;
6900 bzero (fontp, sizeof (*fontp));
6901 fontp->font = font;
6902 fontp->font_idx = i;
6903 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6904 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6906 if (font->min_bounds.width == font->max_bounds.width)
6908 /* Fixed width font. */
6909 fontp->average_width = fontp->space_width = font->min_bounds.width;
6911 else
6913 XChar2b char2b;
6914 XCharStruct *pcm;
6916 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
6917 pcm = mac_per_char_metric (font, &char2b, 0);
6918 if (pcm)
6919 fontp->space_width = pcm->width;
6920 else
6921 fontp->space_width = FONT_WIDTH (font);
6923 if (pcm)
6925 int width = pcm->width;
6926 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
6927 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
6928 width += pcm->width;
6929 fontp->average_width = width / 95;
6931 else
6932 fontp->average_width = FONT_WIDTH (font);
6935 fontp->full_name = fontp->name;
6937 fontp->size = font->max_bounds.width;
6938 fontp->height = FONT_HEIGHT (font);
6940 /* For some font, ascent and descent in max_bounds field is
6941 larger than the above value. */
6942 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6943 if (max_height > fontp->height)
6944 fontp->height = max_height;
6947 /* The slot `encoding' specifies how to map a character
6948 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6949 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6950 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6951 2:0xA020..0xFF7F). For the moment, we don't know which charset
6952 uses this font. So, we set information in fontp->encoding[1]
6953 which is never used by any charset. If mapping can't be
6954 decided, set FONT_ENCODING_NOT_DECIDED. */
6955 if (font->mac_scriptcode == smJapanese)
6956 fontp->encoding[1] = 4;
6957 else
6959 fontp->encoding[1]
6960 = (font->max_byte1 == 0
6961 /* 1-byte font */
6962 ? (font->min_char_or_byte2 < 0x80
6963 ? (font->max_char_or_byte2 < 0x80
6964 ? 0 /* 0x20..0x7F */
6965 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6966 : 1) /* 0xA0..0xFF */
6967 /* 2-byte font */
6968 : (font->min_byte1 < 0x80
6969 ? (font->max_byte1 < 0x80
6970 ? (font->min_char_or_byte2 < 0x80
6971 ? (font->max_char_or_byte2 < 0x80
6972 ? 0 /* 0x2020..0x7F7F */
6973 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6974 : 3) /* 0x20A0..0x7FFF */
6975 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6976 : (font->min_char_or_byte2 < 0x80
6977 ? (font->max_char_or_byte2 < 0x80
6978 ? 2 /* 0xA020..0xFF7F */
6979 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6980 : 1))); /* 0xA0A0..0xFFFF */
6983 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6984 fontp->baseline_offset
6985 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6986 ? (long) value : 0);
6987 fontp->relative_compose
6988 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6989 ? (long) value : 0);
6990 fontp->default_ascent
6991 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6992 ? (long) value : 0);
6993 #else
6994 fontp->baseline_offset = 0;
6995 fontp->relative_compose = 0;
6996 fontp->default_ascent = 0;
6997 #endif
6999 /* Set global flag fonts_changed_p to non-zero if the font loaded
7000 has a character with a smaller width than any other character
7001 before, or if the font loaded has a smalle>r height than any
7002 other font loaded before. If this happens, it will make a
7003 glyph matrix reallocation necessary. */
7004 fonts_changed_p = x_compute_min_glyph_bounds (f);
7005 UNBLOCK_INPUT;
7006 return fontp;
7011 /* Return a pointer to struct font_info of a font named FONTNAME for
7012 frame F. If no such font is loaded, return NULL. */
7014 struct font_info *
7015 x_query_font (f, fontname)
7016 struct frame *f;
7017 register char *fontname;
7019 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7020 int i;
7022 for (i = 0; i < dpyinfo->n_fonts; i++)
7023 if (dpyinfo->font_table[i].name
7024 && (!strcmp (dpyinfo->font_table[i].name, fontname)
7025 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
7026 return (dpyinfo->font_table + i);
7027 return NULL;
7031 /* Find a CCL program for a font specified by FONTP, and set the member
7032 `encoder' of the structure. */
7034 void
7035 x_find_ccl_program (fontp)
7036 struct font_info *fontp;
7038 Lisp_Object list, elt;
7040 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7042 elt = XCAR (list);
7043 if (CONSP (elt)
7044 && STRINGP (XCAR (elt))
7045 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7046 >= 0))
7047 break;
7049 if (! NILP (list))
7051 struct ccl_program *ccl
7052 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7054 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7055 xfree (ccl);
7056 else
7057 fontp->font_encoder = ccl;
7063 /* The Mac Event loop code */
7065 #ifndef MAC_OSX
7066 #include <Events.h>
7067 #include <Quickdraw.h>
7068 #include <Balloons.h>
7069 #include <Devices.h>
7070 #include <Fonts.h>
7071 #include <Gestalt.h>
7072 #include <Menus.h>
7073 #include <Processes.h>
7074 #include <Sound.h>
7075 #include <ToolUtils.h>
7076 #include <TextUtils.h>
7077 #include <Dialogs.h>
7078 #include <Script.h>
7079 #include <Types.h>
7080 #include <TextEncodingConverter.h>
7081 #include <Resources.h>
7083 #if __MWERKS__
7084 #include <unix.h>
7085 #endif
7086 #endif /* ! MAC_OSX */
7088 #define M_APPLE 128
7089 #define I_ABOUT 1
7091 #define WINDOW_RESOURCE 128
7092 #define TERM_WINDOW_RESOURCE 129
7094 #define DEFAULT_NUM_COLS 80
7096 #define MIN_DOC_SIZE 64
7097 #define MAX_DOC_SIZE 32767
7099 /* sleep time for WaitNextEvent */
7100 #define WNE_SLEEP_AT_SUSPEND 10
7101 #define WNE_SLEEP_AT_RESUME 1
7103 /* true when cannot handle any Mac OS events */
7104 static int handling_window_update = 0;
7106 #if 0
7107 /* the flag appl_is_suspended is used both for determining the sleep
7108 time to be passed to WaitNextEvent and whether the cursor should be
7109 drawn when updating the display. The cursor is turned off when
7110 Emacs is suspended. Redrawing it is unnecessary and what needs to
7111 be done depends on whether the cursor lies inside or outside the
7112 redraw region. So we might as well skip drawing it when Emacs is
7113 suspended. */
7114 static Boolean app_is_suspended = false;
7115 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
7116 #endif
7118 #define EXTRA_STACK_ALLOC (256 * 1024)
7120 #define ARGV_STRING_LIST_ID 129
7121 #define ABOUT_ALERT_ID 128
7122 #define RAM_TOO_LARGE_ALERT_ID 129
7124 Boolean terminate_flag = false;
7126 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7127 Lisp_Object Qreverse;
7129 /* True if using command key as meta key. */
7130 Lisp_Object Vmac_command_key_is_meta;
7132 /* Modifier associated with the option key, or nil for normal behavior. */
7133 Lisp_Object Vmac_option_modifier;
7135 /* True if the ctrl and meta keys should be reversed. */
7136 Lisp_Object Vmac_reverse_ctrl_meta;
7138 /* True if the option and command modifiers should be used to emulate
7139 a three button mouse */
7140 Lisp_Object Vmac_emulate_three_button_mouse;
7142 #if USE_CARBON_EVENTS
7143 /* True if the mouse wheel button (i.e. button 4) should map to
7144 mouse-2, instead of mouse-3. */
7145 Lisp_Object Vmac_wheel_button_is_mouse_2;
7147 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7148 for processing before Emacs sees it. */
7149 Lisp_Object Vmac_pass_command_to_system;
7151 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7152 for processing before Emacs sees it. */
7153 Lisp_Object Vmac_pass_control_to_system;
7154 #endif
7156 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7157 to this text encoding */
7158 int mac_keyboard_text_encoding;
7159 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7161 /* Set in term/mac-win.el to indicate that event loop can now generate
7162 drag and drop events. */
7163 Lisp_Object Qmac_ready_for_drag_n_drop;
7165 Lisp_Object drag_and_drop_file_list;
7167 Point saved_menu_event_location;
7169 #if !TARGET_API_MAC_CARBON
7170 /* Place holder for the default arrow cursor. */
7171 CursPtr arrow_cursor;
7172 #endif
7174 /* Apple Events */
7175 static void init_required_apple_events (void);
7176 static pascal OSErr
7177 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7178 static pascal OSErr
7179 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7180 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7181 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7183 #if TARGET_API_MAC_CARBON
7184 /* Drag and Drop */
7185 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
7186 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7187 #endif
7189 #if USE_CARBON_EVENTS
7190 /* Preliminary Support for the OSX Services Menu */
7191 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7192 static void init_service_handler ();
7193 /* Window Event Handler */
7194 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7195 EventRef, void *);
7196 #endif
7197 OSErr install_window_handler (WindowPtr);
7199 extern void init_emacs_passwd_dir ();
7200 extern int emacs_main (int, char **, char **);
7201 extern void check_alarm ();
7203 extern void initialize_applescript();
7204 extern void terminate_applescript();
7206 static unsigned int
7207 #if USE_CARBON_EVENTS
7208 mac_to_emacs_modifiers (UInt32 mods)
7209 #else
7210 mac_to_emacs_modifiers (EventModifiers mods)
7211 #endif
7213 unsigned int result = 0;
7214 if (mods & macShiftKey)
7215 result |= shift_modifier;
7216 if (mods & macCtrlKey)
7217 result |= ctrl_modifier;
7218 if (mods & macMetaKey)
7219 result |= meta_modifier;
7220 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7221 result |= alt_modifier;
7222 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7223 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7224 if (!NILP(val))
7225 result |= XUINT(val);
7228 return result;
7231 static int
7232 mac_get_emulated_btn ( UInt32 modifiers )
7234 int result = 0;
7235 if (!NILP (Vmac_emulate_three_button_mouse)) {
7236 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7237 if (modifiers & cmdKey)
7238 result = cmdIs3 ? 2 : 1;
7239 else if (modifiers & optionKey)
7240 result = cmdIs3 ? 1 : 2;
7242 return result;
7245 #if USE_CARBON_EVENTS
7246 /* Obtains the event modifiers from the event ref and then calls
7247 mac_to_emacs_modifiers. */
7248 static int
7249 mac_event_to_emacs_modifiers (EventRef eventRef)
7251 UInt32 mods = 0;
7252 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7253 sizeof (UInt32), NULL, &mods);
7254 if (!NILP (Vmac_emulate_three_button_mouse) &&
7255 GetEventClass(eventRef) == kEventClassMouse)
7257 mods &= ~(optionKey | cmdKey);
7259 return mac_to_emacs_modifiers (mods);
7262 /* Given an event ref, return the code to use for the mouse button
7263 code in the emacs input_event. */
7264 static int
7265 mac_get_mouse_btn (EventRef ref)
7267 EventMouseButton result = kEventMouseButtonPrimary;
7268 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7269 sizeof (EventMouseButton), NULL, &result);
7270 switch (result)
7272 case kEventMouseButtonPrimary:
7273 if (NILP (Vmac_emulate_three_button_mouse))
7274 return 0;
7275 else {
7276 UInt32 mods = 0;
7277 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7278 sizeof (UInt32), NULL, &mods);
7279 return mac_get_emulated_btn(mods);
7281 case kEventMouseButtonSecondary:
7282 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7283 case kEventMouseButtonTertiary:
7284 case 4: /* 4 is the number for the mouse wheel button */
7285 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7286 default:
7287 return 0;
7291 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7292 events. However the click of the mouse wheel is not converted to a
7293 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7294 checks to see if it is a mouse up or down carbon event that has not
7295 been converted, and if so, converts it by hand (to be picked up in
7296 the XTread_socket loop). */
7297 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7299 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7300 /* Do special case for mouse wheel button. */
7301 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7303 UInt32 kind = GetEventKind (eventRef);
7304 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7306 eventRec->what = mouseDown;
7307 result=1;
7309 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7311 eventRec->what = mouseUp;
7312 result=1;
7314 if (result)
7316 /* Need where and when. */
7317 UInt32 mods;
7318 GetEventParameter (eventRef, kEventParamMouseLocation,
7319 typeQDPoint, NULL, sizeof (Point),
7320 NULL, &eventRec->where);
7321 /* Use two step process because new event modifiers are
7322 32-bit and old are 16-bit. Currently, only loss is
7323 NumLock & Fn. */
7324 GetEventParameter (eventRef, kEventParamKeyModifiers,
7325 typeUInt32, NULL, sizeof (UInt32),
7326 NULL, &mods);
7327 eventRec->modifiers = mods;
7329 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7332 return result;
7335 #endif
7337 static void
7338 do_get_menus (void)
7340 Handle menubar_handle;
7341 MenuHandle menu_handle;
7343 menubar_handle = GetNewMBar (128);
7344 if(menubar_handle == NULL)
7345 abort ();
7346 SetMenuBar (menubar_handle);
7347 DrawMenuBar ();
7349 menu_handle = GetMenuHandle (M_APPLE);
7350 if(menu_handle != NULL)
7351 AppendResMenu (menu_handle,'DRVR');
7352 else
7353 abort ();
7357 static void
7358 do_init_managers (void)
7360 #if !TARGET_API_MAC_CARBON
7361 InitGraf (&qd.thePort);
7362 InitFonts ();
7363 FlushEvents (everyEvent, 0);
7364 InitWindows ();
7365 InitMenus ();
7366 TEInit ();
7367 InitDialogs (NULL);
7368 #endif /* !TARGET_API_MAC_CARBON */
7369 InitCursor ();
7371 #if !TARGET_API_MAC_CARBON
7372 arrow_cursor = &qd.arrow;
7374 /* set up some extra stack space for use by emacs */
7375 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7377 /* MaxApplZone must be called for AppleScript to execute more
7378 complicated scripts */
7379 MaxApplZone ();
7380 MoreMasters ();
7381 #endif /* !TARGET_API_MAC_CARBON */
7384 static void
7385 do_check_ram_size (void)
7387 SInt32 physical_ram_size, logical_ram_size;
7389 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7390 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7391 || physical_ram_size > (1 << VALBITS)
7392 || logical_ram_size > (1 << VALBITS))
7394 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7395 exit (1);
7399 static void
7400 do_window_update (WindowPtr win)
7402 struct frame *f = mac_window_to_frame (win);
7404 BeginUpdate (win);
7406 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7407 below. */
7408 if (win != tip_window)
7410 if (f->async_visible == 0)
7412 f->async_visible = 1;
7413 f->async_iconified = 0;
7414 SET_FRAME_GARBAGED (f);
7416 /* An update event is equivalent to MapNotify on X, so report
7417 visibility changes properly. */
7418 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7419 /* Force a redisplay sooner or later to update the
7420 frame titles in case this is the second frame. */
7421 record_asynch_buffer_change ();
7423 else
7425 Rect r;
7427 handling_window_update = 1;
7429 #if TARGET_API_MAC_CARBON
7431 RgnHandle region = NewRgn ();
7433 GetPortVisibleRegion (GetWindowPort (win), region);
7434 UpdateControls (win, region);
7435 GetRegionBounds (region, &r);
7436 DisposeRgn (region);
7438 #else
7439 UpdateControls (win, win->visRgn);
7440 r = (*win->visRgn)->rgnBBox;
7441 #endif
7442 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7444 handling_window_update = 0;
7448 EndUpdate (win);
7451 static int
7452 is_emacs_window (WindowPtr win)
7454 Lisp_Object tail, frame;
7456 if (!win)
7457 return 0;
7459 FOR_EACH_FRAME (tail, frame)
7460 if (FRAME_MAC_P (XFRAME (frame)))
7461 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7462 return 1;
7464 return 0;
7467 static void
7468 do_app_resume ()
7470 /* Window-activate events will do the job. */
7471 #if 0
7472 WindowPtr wp;
7473 struct frame *f;
7475 wp = front_emacs_window ();
7476 if (wp)
7478 f = mac_window_to_frame (wp);
7480 if (f)
7482 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7483 activate_scroll_bars (f);
7487 app_is_suspended = false;
7488 app_sleep_time = WNE_SLEEP_AT_RESUME;
7489 #endif
7492 static void
7493 do_app_suspend ()
7495 /* Window-deactivate events will do the job. */
7496 #if 0
7497 WindowPtr wp;
7498 struct frame *f;
7500 wp = front_emacs_window ();
7501 if (wp)
7503 f = mac_window_to_frame (wp);
7505 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7507 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7508 deactivate_scroll_bars (f);
7512 app_is_suspended = true;
7513 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7514 #endif
7518 static void
7519 do_mouse_moved (mouse_pos, f)
7520 Point mouse_pos;
7521 FRAME_PTR *f;
7523 WindowPtr wp = front_emacs_window ();
7524 struct x_display_info *dpyinfo;
7526 if (wp)
7528 *f = mac_window_to_frame (wp);
7529 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7531 if (dpyinfo->mouse_face_hidden)
7533 dpyinfo->mouse_face_hidden = 0;
7534 clear_mouse_face (dpyinfo);
7537 SetPortWindowPort (wp);
7539 GlobalToLocal (&mouse_pos);
7541 if (dpyinfo->grabbed && tracked_scroll_bar)
7542 x_scroll_bar_note_movement (tracked_scroll_bar,
7543 mouse_pos.v
7544 - XINT (tracked_scroll_bar->top),
7545 TickCount() * (1000 / 60));
7546 else
7547 note_mouse_movement (*f, &mouse_pos);
7552 static void
7553 do_apple_menu (SInt16 menu_item)
7555 #if !TARGET_API_MAC_CARBON
7556 Str255 item_name;
7557 SInt16 da_driver_refnum;
7559 if (menu_item == I_ABOUT)
7560 NoteAlert (ABOUT_ALERT_ID, NULL);
7561 else
7563 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7564 da_driver_refnum = OpenDeskAcc (item_name);
7566 #endif /* !TARGET_API_MAC_CARBON */
7569 void
7570 do_menu_choice (SInt32 menu_choice)
7572 SInt16 menu_id, menu_item;
7574 menu_id = HiWord (menu_choice);
7575 menu_item = LoWord (menu_choice);
7577 if (menu_id == 0)
7578 return;
7580 switch (menu_id)
7582 case M_APPLE:
7583 do_apple_menu (menu_item);
7584 break;
7586 default:
7588 struct frame *f = mac_window_to_frame (front_emacs_window ());
7589 MenuHandle menu = GetMenuHandle (menu_id);
7590 if (menu)
7592 UInt32 refcon;
7594 GetMenuItemRefCon (menu, menu_item, &refcon);
7595 menubar_selection_callback (f, refcon);
7600 HiliteMenu (0);
7604 /* Handle drags in size box. Based on code contributed by Ben
7605 Mesander and IM - Window Manager A. */
7607 static void
7608 do_grow_window (WindowPtr w, EventRecord *e)
7610 Rect limit_rect;
7611 int rows, columns, width, height;
7612 struct frame *f = mac_window_to_frame (w);
7613 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7614 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7615 #if TARGET_API_MAC_CARBON
7616 Rect new_rect;
7617 #else
7618 long grow_size;
7619 #endif
7621 if (size_hints->flags & PMinSize)
7623 min_width = size_hints->min_width;
7624 min_height = size_hints->min_height;
7626 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
7628 #if TARGET_API_MAC_CARBON
7629 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7630 return;
7631 height = new_rect.bottom - new_rect.top;
7632 width = new_rect.right - new_rect.left;
7633 #else
7634 grow_size = GrowWindow (w, e->where, &limit_rect);
7635 /* see if it really changed size */
7636 if (grow_size == 0)
7637 return;
7638 height = HiWord (grow_size);
7639 width = LoWord (grow_size);
7640 #endif
7642 if (width != FRAME_PIXEL_WIDTH (f)
7643 || height != FRAME_PIXEL_HEIGHT (f))
7645 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7646 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7648 x_set_window_size (f, 0, columns, rows);
7653 /* Handle clicks in zoom box. Calculation of "standard state" based
7654 on code in IM - Window Manager A and code contributed by Ben
7655 Mesander. The standard state of an Emacs window is 80-characters
7656 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7658 static void
7659 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7661 GrafPtr save_port;
7662 Rect zoom_rect, port_rect;
7663 Point top_left;
7664 int w_title_height, columns, rows, width, height;
7665 struct frame *f = mac_window_to_frame (w);
7667 #if TARGET_API_MAC_CARBON
7669 Point standard_size;
7671 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7672 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7674 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7675 zoom_in_or_out = inZoomIn;
7676 else
7678 /* Adjust the standard size according to character boundaries. */
7680 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7681 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7682 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7683 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7684 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7685 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7686 && port_rect.left == zoom_rect.left
7687 && port_rect.top == zoom_rect.top)
7688 zoom_in_or_out = inZoomIn;
7689 else
7690 zoom_in_or_out = inZoomOut;
7693 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7695 #else /* not TARGET_API_MAC_CARBON */
7696 GetPort (&save_port);
7698 SetPortWindowPort (w);
7700 /* Clear window to avoid flicker. */
7701 EraseRect (&(w->portRect));
7702 if (zoom_in_or_out == inZoomOut)
7704 SetPt (&top_left, w->portRect.left, w->portRect.top);
7705 LocalToGlobal (&top_left);
7707 /* calculate height of window's title bar */
7708 w_title_height = top_left.v - 1
7709 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7711 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7712 zoom_rect = qd.screenBits.bounds;
7713 zoom_rect.top += w_title_height;
7714 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7716 zoom_rect.right = zoom_rect.left
7717 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7719 /* Adjust the standard size according to character boundaries. */
7720 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7721 zoom_rect.bottom =
7722 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7724 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7725 = zoom_rect;
7728 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7730 SetPort (save_port);
7731 #endif /* not TARGET_API_MAC_CARBON */
7733 /* retrieve window size and update application values */
7734 #if TARGET_API_MAC_CARBON
7735 GetWindowPortBounds (w, &port_rect);
7736 #else
7737 port_rect = w->portRect;
7738 #endif
7739 height = port_rect.bottom - port_rect.top;
7740 width = port_rect.right - port_rect.left;
7742 if (width != FRAME_PIXEL_WIDTH (f)
7743 || height != FRAME_PIXEL_HEIGHT (f))
7745 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7746 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7748 change_frame_size (f, rows, columns, 0, 1, 0);
7749 SET_FRAME_GARBAGED (f);
7750 cancel_mouse_face (f);
7752 FRAME_PIXEL_WIDTH (f) = width;
7753 FRAME_PIXEL_HEIGHT (f) = height;
7755 x_real_positions (f, &f->left_pos, &f->top_pos);
7758 /* Intialize AppleEvent dispatcher table for the required events. */
7759 void
7760 init_required_apple_events ()
7762 OSErr err;
7763 long result;
7765 /* Make sure we have apple events before starting. */
7766 err = Gestalt (gestaltAppleEventsAttr, &result);
7767 if (err != noErr)
7768 abort ();
7770 if (!(result & (1 << gestaltAppleEventsPresent)))
7771 abort ();
7773 #if TARGET_API_MAC_CARBON
7774 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7775 NewAEEventHandlerUPP
7776 ((AEEventHandlerProcPtr) do_ae_open_application),
7777 0L, false);
7778 #else
7779 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7780 NewAEEventHandlerProc
7781 ((AEEventHandlerProcPtr) do_ae_open_application),
7782 0L, false);
7783 #endif
7784 if (err != noErr)
7785 abort ();
7787 #if TARGET_API_MAC_CARBON
7788 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7789 NewAEEventHandlerUPP
7790 ((AEEventHandlerProcPtr) do_ae_open_documents),
7791 0L, false);
7792 #else
7793 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7794 NewAEEventHandlerProc
7795 ((AEEventHandlerProcPtr) do_ae_open_documents),
7796 0L, false);
7797 #endif
7798 if (err != noErr)
7799 abort ();
7801 #if TARGET_API_MAC_CARBON
7802 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7803 NewAEEventHandlerUPP
7804 ((AEEventHandlerProcPtr) do_ae_print_documents),
7805 0L, false);
7806 #else
7807 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7808 NewAEEventHandlerProc
7809 ((AEEventHandlerProcPtr) do_ae_print_documents),
7810 0L, false);
7811 #endif
7812 if (err != noErr)
7813 abort ();
7815 #if TARGET_API_MAC_CARBON
7816 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7817 NewAEEventHandlerUPP
7818 ((AEEventHandlerProcPtr) do_ae_quit_application),
7819 0L, false);
7820 #else
7821 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7822 NewAEEventHandlerProc
7823 ((AEEventHandlerProcPtr) do_ae_quit_application),
7824 0L, false);
7825 #endif
7826 if (err != noErr)
7827 abort ();
7830 #if USE_CARBON_EVENTS
7832 void
7833 init_service_handler ()
7835 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7836 {kEventClassService, kEventServiceCopy},
7837 {kEventClassService, kEventServicePaste}};
7838 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7839 3, specs, NULL, NULL);
7843 MAC_TODO: Check to see if this is called by AEProcessDesc...
7845 OSStatus
7846 mac_handle_service_event (EventHandlerCallRef callRef,
7847 EventRef event, void *data)
7849 OSStatus err = noErr;
7850 switch (GetEventKind (event))
7852 case kEventServiceGetTypes:
7854 CFMutableArrayRef copyTypes, pasteTypes;
7855 CFStringRef type;
7856 Boolean selection = true;
7858 GetEventParameter(event, kEventParamServicePasteTypes,
7859 typeCFMutableArrayRef, NULL,
7860 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7862 GetEventParameter(event, kEventParamServiceCopyTypes,
7863 typeCFMutableArrayRef, NULL,
7864 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7865 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7866 if (type) {
7867 CFArrayAppendValue (copyTypes, type);
7868 //CFArrayAppendValue (pasteTypes, type);
7869 CFRelease (type);
7872 case kEventServiceCopy:
7874 ScrapRef currentScrap, specificScrap;
7875 char * buf = "";
7876 Size byteCount = 0;
7878 GetCurrentScrap (&currentScrap);
7880 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7881 if (err == noErr)
7883 void *buffer = xmalloc (byteCount);
7884 if (buffer != NULL)
7886 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7887 sizeof (ScrapRef), NULL, &specificScrap);
7889 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7890 &byteCount, buffer);
7891 if (err == noErr)
7892 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7893 kScrapFlavorMaskNone, byteCount, buffer);
7894 xfree (buffer);
7897 err = noErr;
7899 case kEventServicePaste:
7902 // Get the current location
7903 Size byteCount;
7904 ScrapRef specificScrap;
7905 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7906 sizeof(ScrapRef), NULL, &specificScrap);
7907 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7908 if (err == noErr) {
7909 void * buffer = xmalloc(byteCount);
7910 if (buffer != NULL ) {
7911 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7912 &byteCount, buffer);
7913 if (err == noErr) {
7914 // Actually place in the buffer
7915 BLOCK_INPUT;
7916 // Get the current "selection" string here
7917 UNBLOCK_INPUT;
7920 xfree(buffer);
7925 return err;
7929 static pascal OSStatus
7930 mac_handle_window_event (next_handler, event, data)
7931 EventHandlerCallRef next_handler;
7932 EventRef event;
7933 void *data;
7935 extern Lisp_Object Qcontrol;
7937 WindowPtr wp;
7938 OSStatus result;
7939 UInt32 attributes;
7940 XSizeHints *size_hints;
7942 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
7943 NULL, sizeof (WindowPtr), NULL, &wp);
7945 switch (GetEventKind (event))
7947 case kEventWindowUpdate:
7948 result = CallNextEventHandler (next_handler, event);
7949 if (result != eventNotHandledErr)
7950 return result;
7952 do_window_update (wp);
7953 break;
7955 case kEventWindowBoundsChanging:
7956 result = CallNextEventHandler (next_handler, event);
7957 if (result != eventNotHandledErr)
7958 return result;
7960 GetEventParameter (event, kEventParamAttributes, typeUInt32,
7961 NULL, sizeof (UInt32), NULL, &attributes);
7962 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
7963 if ((attributes & kWindowBoundsChangeUserResize)
7964 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
7965 == (PResizeInc | PBaseSize | PMinSize)))
7967 Rect bounds;
7968 int width, height;
7970 GetEventParameter (event, kEventParamCurrentBounds,
7971 typeQDRectangle,
7972 NULL, sizeof (Rect), NULL, &bounds);
7973 width = bounds.right - bounds.left;
7974 height = bounds.bottom - bounds.top;
7976 if (width < size_hints->min_width)
7977 width = size_hints->min_width;
7978 else
7979 width = size_hints->base_width
7980 + (int) ((width - size_hints->base_width)
7981 / (float) size_hints->width_inc + .5)
7982 * size_hints->width_inc;
7984 if (height < size_hints->min_height)
7985 height = size_hints->min_height;
7986 else
7987 height = size_hints->base_height
7988 + (int) ((height - size_hints->base_height)
7989 / (float) size_hints->height_inc + .5)
7990 * size_hints->height_inc;
7992 bounds.right = bounds.left + width;
7993 bounds.bottom = bounds.top + height;
7994 SetEventParameter (event, kEventParamCurrentBounds,
7995 typeQDRectangle, sizeof (Rect), &bounds);
7996 return noErr;
7998 break;
8001 return eventNotHandledErr;
8003 #endif /* USE_CARBON_EVENTS */
8006 OSErr
8007 install_window_handler (window)
8008 WindowPtr window;
8010 OSErr err = noErr;
8011 #if USE_CARBON_EVENTS
8012 EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate},
8013 {kEventClassWindow, kEventWindowBoundsChanging}};
8014 static EventHandlerUPP handle_window_event_UPP = NULL;
8016 if (handle_window_event_UPP == NULL)
8017 handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
8019 err = InstallWindowEventHandler (window, handle_window_event_UPP,
8020 GetEventTypeCount (specs), specs,
8021 NULL, NULL);
8022 #endif
8023 #if TARGET_API_MAC_CARBON
8024 if (err == noErr)
8025 err = InstallTrackingHandler (mac_do_track_drag, window, NULL);
8026 if (err == noErr)
8027 err = InstallReceiveHandler (mac_do_receive_drag, window, NULL);
8028 #endif
8029 return err;
8033 /* Open Application Apple Event */
8034 static pascal OSErr
8035 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
8037 return noErr;
8041 /* Defined in mac.c. */
8042 extern int
8043 path_from_vol_dir_name (char *, int, short, long, char *);
8046 /* Called when we receive an AppleEvent with an ID of
8047 "kAEOpenDocuments". This routine gets the direct parameter,
8048 extracts the FSSpecs in it, and puts their names on a list. */
8049 #pragma options align=mac68k
8050 typedef struct SelectionRange {
8051 short unused1; // 0 (not used)
8052 short lineNum; // line to select (<0 to specify range)
8053 long startRange; // start of selection range (if line < 0)
8054 long endRange; // end of selection range (if line < 0)
8055 long unused2; // 0 (not used)
8056 long theDate; // modification date/time
8057 } SelectionRange;
8058 #pragma options align=reset
8060 static pascal OSErr
8061 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
8063 OSErr err, err2;
8064 AEDesc the_desc;
8065 AEKeyword keyword;
8066 DescType actual_type;
8067 Size actual_size;
8068 SelectionRange position;
8070 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
8071 if (err != noErr)
8072 goto descriptor_error_exit;
8074 err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
8075 if (err == noErr)
8076 drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1),
8077 make_number (position.startRange + 1),
8078 make_number (position.endRange + 1)),
8079 drag_and_drop_file_list);
8081 /* Check to see that we got all of the required parameters from the
8082 event descriptor. For an 'odoc' event this should just be the
8083 file list. */
8084 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
8085 &actual_type, (Ptr) &keyword,
8086 sizeof (keyword), &actual_size);
8087 /* No error means that we found some unused parameters.
8088 errAEDescNotFound means that there are no more parameters. If we
8089 get an error code other than that, flag it. */
8090 if ((err == noErr) || (err != errAEDescNotFound))
8092 err = errAEEventNotHandled;
8093 goto error_exit;
8095 err = noErr;
8097 /* Got all the parameters we need. Now, go through the direct
8098 object list and parse it up. */
8100 long num_files_to_open;
8102 err = AECountItems (&the_desc, &num_files_to_open);
8103 if (err == noErr)
8105 int i;
8107 /* AE file list is one based so just use that for indexing here. */
8108 for (i = 1; i <= num_files_to_open; i++)
8110 #ifdef MAC_OSX
8111 FSRef fref;
8112 char unix_path_name[MAXPATHLEN];
8114 err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
8115 &actual_type, &fref, sizeof (FSRef),
8116 &actual_size);
8117 if (err != noErr || actual_type != typeFSRef)
8118 continue;
8120 if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
8121 == noErr)
8122 #else
8123 FSSpec fs;
8124 Str255 path_name, unix_path_name;
8126 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
8127 (Ptr) &fs, sizeof (fs), &actual_size);
8128 if (err != noErr) continue;
8130 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
8131 fs.name) &&
8132 mac_to_posix_pathname (path_name, unix_path_name, 255))
8133 #endif
8134 /* x-dnd functions expect undecoded filenames. */
8135 drag_and_drop_file_list =
8136 Fcons (make_unibyte_string (unix_path_name,
8137 strlen (unix_path_name)),
8138 drag_and_drop_file_list);
8143 error_exit:
8144 /* Nuke the coerced file list in any case */
8145 err2 = AEDisposeDesc(&the_desc);
8147 descriptor_error_exit:
8148 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8149 return err;
8153 #if TARGET_API_MAC_CARBON
8154 static pascal OSErr
8155 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
8156 void *handlerRefCon, DragReference theDrag)
8158 static int can_accept;
8159 short items;
8160 short index;
8161 ItemReference theItem;
8162 FlavorFlags theFlags;
8163 OSErr result;
8165 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8166 return dragNotAcceptedErr;
8168 switch (message)
8170 case kDragTrackingEnterHandler:
8171 CountDragItems (theDrag, &items);
8172 can_accept = 0;
8173 for (index = 1; index <= items; index++)
8175 GetDragItemReferenceNumber (theDrag, index, &theItem);
8176 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8177 if (result == noErr)
8179 can_accept = 1;
8180 break;
8183 break;
8185 case kDragTrackingEnterWindow:
8186 if (can_accept)
8188 RgnHandle hilite_rgn = NewRgn ();
8189 Rect r;
8190 struct frame *f = mac_window_to_frame (window);
8192 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
8193 GetWindowPortBounds (window, &r);
8194 OffsetRect (&r, -r.left, -r.top);
8195 RectRgn (hilite_rgn, &r);
8196 ShowDragHilite (theDrag, hilite_rgn, true);
8197 DisposeRgn (hilite_rgn);
8198 SetThemeCursor (kThemeCopyArrowCursor);
8200 break;
8202 case kDragTrackingInWindow:
8203 break;
8205 case kDragTrackingLeaveWindow:
8206 if (can_accept)
8208 struct frame *f = mac_window_to_frame (window);
8210 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
8211 HideDragHilite (theDrag);
8212 SetThemeCursor (kThemeArrowCursor);
8214 break;
8216 case kDragTrackingLeaveHandler:
8217 break;
8220 return noErr;
8223 static pascal OSErr
8224 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8225 DragReference theDrag)
8227 short items;
8228 short index;
8229 FlavorFlags theFlags;
8230 Point mouse;
8231 OSErr result;
8232 ItemReference theItem;
8233 HFSFlavor data;
8234 Size size = sizeof (HFSFlavor);
8236 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8237 return dragNotAcceptedErr;
8239 drag_and_drop_file_list = Qnil;
8240 GetDragMouse (theDrag, &mouse, 0L);
8241 CountDragItems (theDrag, &items);
8242 for (index = 1; index <= items; index++)
8244 /* Only handle file references. */
8245 GetDragItemReferenceNumber (theDrag, index, &theItem);
8246 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8247 if (result == noErr)
8249 #ifdef MAC_OSX
8250 FSRef fref;
8251 char unix_path_name[MAXPATHLEN];
8252 #else
8253 Str255 path_name, unix_path_name;
8254 #endif
8255 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8256 #ifdef MAC_OSX
8257 /* Use Carbon routines, otherwise it converts the file name
8258 to /Macintosh HD/..., which is not correct. */
8259 FSpMakeFSRef (&data.fileSpec, &fref);
8260 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8261 #else
8262 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
8263 data.fileSpec.parID, data.fileSpec.name) &&
8264 mac_to_posix_pathname (path_name, unix_path_name, 255))
8265 #endif
8266 /* x-dnd functions expect undecoded filenames. */
8267 drag_and_drop_file_list =
8268 Fcons (make_unibyte_string (unix_path_name,
8269 strlen (unix_path_name)),
8270 drag_and_drop_file_list);
8273 /* If there are items in the list, construct an event and post it to
8274 the queue like an interrupt using kbd_buffer_store_event. */
8275 if (!NILP (drag_and_drop_file_list))
8277 struct input_event event;
8278 Lisp_Object frame;
8279 struct frame *f = mac_window_to_frame (window);
8280 SInt16 modifiers;
8282 GlobalToLocal (&mouse);
8283 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
8285 event.kind = DRAG_N_DROP_EVENT;
8286 event.code = 0;
8287 event.modifiers = mac_to_emacs_modifiers (modifiers);
8288 event.timestamp = TickCount () * (1000 / 60);
8289 XSETINT (event.x, mouse.h);
8290 XSETINT (event.y, mouse.v);
8291 XSETFRAME (frame, f);
8292 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8293 event.arg = Qnil;
8294 /* Post to the interrupt queue */
8295 kbd_buffer_store_event (&event);
8296 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8298 ProcessSerialNumber psn;
8299 GetCurrentProcess (&psn);
8300 SetFrontProcess (&psn);
8303 return noErr;
8305 else
8306 return dragNotAcceptedErr;
8308 #endif
8311 /* Print Document Apple Event */
8312 static pascal OSErr
8313 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8315 return errAEEventNotHandled;
8319 static pascal OSErr
8320 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8322 /* FixMe: Do we need an unwind-protect or something here? And what
8323 do we do about unsaved files. Currently just forces quit rather
8324 than doing recursive callback to get user input. */
8326 terminate_flag = true;
8328 /* Fkill_emacs doesn't return. We have to return. (TI) */
8329 return noErr;
8333 #if __profile__
8334 void
8335 profiler_exit_proc ()
8337 ProfilerDump ("\pEmacs.prof");
8338 ProfilerTerm ();
8340 #endif
8342 /* These few functions implement Emacs as a normal Mac application
8343 (almost): set up the heap and the Toolbox, handle necessary
8344 system events plus a few simple menu events. They also set up
8345 Emacs's access to functions defined in the rest of this file.
8346 Emacs uses function hooks to perform all its terminal I/O. A
8347 complete list of these functions appear in termhooks.h. For what
8348 they do, read the comments there and see also w32term.c and
8349 xterm.c. What's noticeably missing here is the event loop, which
8350 is normally present in most Mac application. After performing the
8351 necessary Mac initializations, main passes off control to
8352 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8353 mac_read_socket (defined further below) to read input. This is
8354 where WaitNextEvent is called to process Mac events. This is also
8355 where check_alarm in sysdep.c is called to simulate alarm signals.
8356 This makes the cursor jump back to its correct position after
8357 briefly jumping to that of the matching parenthesis, print useful
8358 hints and prompts in the minibuffer after the user stops typing for
8359 a wait, etc. */
8361 #if !TARGET_API_MAC_CARBON
8362 #undef main
8364 main (void)
8366 #if __profile__ /* is the profiler on? */
8367 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8368 exit(1);
8369 #endif
8371 #if __MWERKS__
8372 /* set creator and type for files created by MSL */
8373 _fcreator = 'EMAx';
8374 _ftype = 'TEXT';
8375 #endif
8377 do_init_managers ();
8379 do_get_menus ();
8381 #ifndef USE_LSB_TAG
8382 do_check_ram_size ();
8383 #endif
8385 init_emacs_passwd_dir ();
8387 init_environ ();
8389 initialize_applescript ();
8391 init_required_apple_events ();
8394 char **argv;
8395 int argc = 0;
8397 /* set up argv array from STR# resource */
8398 get_string_list (&argv, ARGV_STRING_LIST_ID);
8399 while (argv[argc])
8400 argc++;
8402 /* free up AppleScript resources on exit */
8403 atexit (terminate_applescript);
8405 #if __profile__ /* is the profiler on? */
8406 atexit (profiler_exit_proc);
8407 #endif
8409 /* 3rd param "envp" never used in emacs_main */
8410 (void) emacs_main (argc, argv, 0);
8413 /* Never reached - real exit in Fkill_emacs */
8414 return 0;
8416 #endif
8418 /* Table for translating Mac keycode to X keysym values. Contributed
8419 by Sudhir Shenoy. */
8420 static unsigned char keycode_to_xkeysym_table[] = {
8421 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8422 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8423 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8425 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8426 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8427 /*0x38*/ 0, 0, 0, 0,
8428 /*0x3C*/ 0, 0, 0, 0,
8430 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8431 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8432 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8433 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8435 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8436 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8437 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8438 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8440 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8441 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8442 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8443 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8445 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8446 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8447 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8448 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8451 static int
8452 keycode_to_xkeysym (int keyCode, int *xKeySym)
8454 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8455 return *xKeySym != 0;
8458 #if !USE_CARBON_EVENTS
8459 static RgnHandle mouse_region = NULL;
8461 Boolean
8462 mac_wait_next_event (er, sleep_time, dequeue)
8463 EventRecord *er;
8464 UInt32 sleep_time;
8465 Boolean dequeue;
8467 static EventRecord er_buf = {nullEvent};
8468 UInt32 target_tick, current_tick;
8469 EventMask event_mask;
8471 if (mouse_region == NULL)
8472 mouse_region = NewRgn ();
8474 event_mask = everyEvent;
8475 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8476 event_mask -= highLevelEventMask;
8478 current_tick = TickCount ();
8479 target_tick = current_tick + sleep_time;
8481 if (er_buf.what == nullEvent)
8482 while (!WaitNextEvent (event_mask, &er_buf,
8483 target_tick - current_tick, mouse_region))
8485 current_tick = TickCount ();
8486 if (target_tick <= current_tick)
8487 return false;
8490 *er = er_buf;
8491 if (dequeue)
8492 er_buf.what = nullEvent;
8493 return true;
8495 #endif /* not USE_CARBON_EVENTS */
8497 /* Emacs calls this whenever it wants to read an input event from the
8498 user. */
8500 XTread_socket (sd, expected, hold_quit)
8501 int sd, expected;
8502 struct input_event *hold_quit;
8504 struct input_event inev;
8505 int count = 0;
8506 #if USE_CARBON_EVENTS
8507 EventRef eventRef;
8508 EventTargetRef toolbox_dispatcher;
8509 #endif
8510 EventRecord er;
8511 struct mac_display_info *dpyinfo = &one_mac_display_info;
8513 if (interrupt_input_blocked)
8515 interrupt_input_pending = 1;
8516 return -1;
8519 interrupt_input_pending = 0;
8520 BLOCK_INPUT;
8522 /* So people can tell when we have read the available input. */
8523 input_signal_count++;
8525 /* Don't poll for events to process (specifically updateEvt) if
8526 window update currently already in progress. A call to redisplay
8527 (in do_window_update) can be preempted by another call to
8528 redisplay, causing blank regions to be left on the screen and the
8529 cursor to be left at strange places. */
8530 if (handling_window_update)
8532 UNBLOCK_INPUT;
8533 return 0;
8536 if (terminate_flag)
8537 Fkill_emacs (make_number (1));
8539 #if USE_CARBON_EVENTS
8540 toolbox_dispatcher = GetEventDispatcherTarget ();
8542 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8543 kEventRemoveFromQueue, &eventRef))
8544 #else /* !USE_CARBON_EVENTS */
8545 while (mac_wait_next_event (&er, 0, true))
8546 #endif /* !USE_CARBON_EVENTS */
8548 int do_help = 0;
8549 struct frame *f;
8551 /* It is necessary to set this (additional) argument slot of an
8552 event to nil because keyboard.c protects incompletely
8553 processed event from being garbage collected by placing them
8554 in the kbd_buffer_gcpro vector. */
8555 EVENT_INIT (inev);
8556 inev.kind = NO_EVENT;
8557 inev.arg = Qnil;
8559 #if USE_CARBON_EVENTS
8560 /* Handle new events */
8561 if (!mac_convert_event_ref (eventRef, &er))
8562 switch (GetEventClass (eventRef))
8564 case kEventClassWindow:
8565 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8567 WindowPtr window_ptr;
8568 GetEventParameter(eventRef, kEventParamDirectObject,
8569 typeWindowRef, NULL, sizeof(WindowPtr),
8570 NULL, &window_ptr);
8571 f = mac_window_to_frame (window_ptr);
8572 if (f && !f->async_iconified)
8573 x_real_positions (f, &f->left_pos, &f->top_pos);
8574 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8576 break;
8577 case kEventClassMouse:
8578 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8580 SInt32 delta;
8581 Point point;
8582 WindowPtr window_ptr = front_emacs_window ();
8584 if (!IsValidWindowPtr (window_ptr))
8586 SysBeep(1);
8587 break;
8590 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8591 typeSInt32, NULL, sizeof (SInt32),
8592 NULL, &delta);
8593 GetEventParameter(eventRef, kEventParamMouseLocation,
8594 typeQDPoint, NULL, sizeof (Point),
8595 NULL, &point);
8596 inev.kind = WHEEL_EVENT;
8597 inev.code = 0;
8598 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8599 | ((delta < 0) ? down_modifier
8600 : up_modifier));
8601 SetPortWindowPort (window_ptr);
8602 GlobalToLocal (&point);
8603 XSETINT (inev.x, point.h);
8604 XSETINT (inev.y, point.v);
8605 XSETFRAME (inev.frame_or_window,
8606 mac_window_to_frame (window_ptr));
8607 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8609 else
8610 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8612 break;
8614 default:
8615 /* Send the event to the appropriate receiver. */
8616 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8618 else
8619 #endif /* USE_CARBON_EVENTS */
8620 switch (er.what)
8622 case mouseDown:
8623 case mouseUp:
8625 WindowPtr window_ptr;
8626 SInt16 part_code;
8627 int tool_bar_p = 0;
8629 #if USE_CARBON_EVENTS
8630 /* This is needed to send mouse events like aqua window
8631 buttons to the correct handler. */
8632 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8633 != eventNotHandledErr)
8634 break;
8635 #endif
8637 if (dpyinfo->grabbed && last_mouse_frame
8638 && FRAME_LIVE_P (last_mouse_frame))
8640 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8641 part_code = inContent;
8643 else
8645 part_code = FindWindow (er.where, &window_ptr);
8646 if (tip_window && window_ptr == tip_window)
8648 HideWindow (tip_window);
8649 part_code = FindWindow (er.where, &window_ptr);
8653 if (er.what != mouseDown && part_code != inContent)
8654 break;
8656 switch (part_code)
8658 case inMenuBar:
8659 f = mac_window_to_frame (front_emacs_window ());
8660 saved_menu_event_location = er.where;
8661 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8662 XSETFRAME (inev.frame_or_window, f);
8663 break;
8665 case inContent:
8666 if (window_ptr != front_emacs_window ())
8667 SelectWindow (window_ptr);
8668 else
8670 SInt16 control_part_code;
8671 ControlHandle ch;
8672 Point mouse_loc = er.where;
8674 f = mac_window_to_frame (window_ptr);
8675 /* convert to local coordinates of new window */
8676 SetPortWindowPort (window_ptr);
8678 GlobalToLocal (&mouse_loc);
8679 #if TARGET_API_MAC_CARBON
8680 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8681 &control_part_code);
8682 #else
8683 control_part_code = FindControl (mouse_loc, window_ptr,
8684 &ch);
8685 #endif
8687 #if USE_CARBON_EVENTS
8688 inev.code = mac_get_mouse_btn (eventRef);
8689 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8690 #else
8691 inev.code = mac_get_emulated_btn (er.modifiers);
8692 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8693 #endif
8694 XSETINT (inev.x, mouse_loc.h);
8695 XSETINT (inev.y, mouse_loc.v);
8696 inev.timestamp = er.when * (1000 / 60);
8697 /* ticks to milliseconds */
8699 if (dpyinfo->grabbed && tracked_scroll_bar
8700 #if TARGET_API_MAC_CARBON
8701 || ch != 0
8702 #else
8703 || control_part_code != 0
8704 #endif
8707 struct scroll_bar *bar;
8709 if (dpyinfo->grabbed && tracked_scroll_bar)
8711 bar = tracked_scroll_bar;
8712 control_part_code = kControlIndicatorPart;
8714 else
8715 bar = (struct scroll_bar *) GetControlReference (ch);
8716 x_scroll_bar_handle_click (bar, control_part_code,
8717 &er, &inev);
8718 if (er.what == mouseDown
8719 && control_part_code == kControlIndicatorPart)
8720 tracked_scroll_bar = bar;
8721 else
8722 tracked_scroll_bar = NULL;
8724 else
8726 Lisp_Object window;
8727 int x = mouse_loc.h;
8728 int y = mouse_loc.v;
8730 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8731 if (EQ (window, f->tool_bar_window))
8733 if (er.what == mouseDown)
8734 handle_tool_bar_click (f, x, y, 1, 0);
8735 else
8736 handle_tool_bar_click (f, x, y, 0,
8737 inev.modifiers);
8738 tool_bar_p = 1;
8740 else
8742 XSETFRAME (inev.frame_or_window, f);
8743 inev.kind = MOUSE_CLICK_EVENT;
8747 if (er.what == mouseDown)
8749 dpyinfo->grabbed |= (1 << inev.code);
8750 last_mouse_frame = f;
8751 /* Ignore any mouse motion that happened
8752 before this event; any subsequent
8753 mouse-movement Emacs events should reflect
8754 only motion after the ButtonPress. */
8755 if (f != 0)
8756 f->mouse_moved = 0;
8758 if (!tool_bar_p)
8759 last_tool_bar_item = -1;
8761 else
8763 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8764 /* If a button is released though it was not
8765 previously pressed, that would be because
8766 of multi-button emulation. */
8767 dpyinfo->grabbed = 0;
8768 else
8769 dpyinfo->grabbed &= ~(1 << inev.code);
8772 switch (er.what)
8774 case mouseDown:
8775 inev.modifiers |= down_modifier;
8776 break;
8777 case mouseUp:
8778 inev.modifiers |= up_modifier;
8779 break;
8782 break;
8784 case inDrag:
8785 #if TARGET_API_MAC_CARBON
8786 DragWindow (window_ptr, er.where, NULL);
8787 #else /* not TARGET_API_MAC_CARBON */
8788 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8789 #endif /* not TARGET_API_MAC_CARBON */
8790 /* Update the frame parameters. */
8792 struct frame *f = mac_window_to_frame (window_ptr);
8794 if (f && !f->async_iconified)
8795 x_real_positions (f, &f->left_pos, &f->top_pos);
8797 break;
8799 case inGoAway:
8800 if (TrackGoAway (window_ptr, er.where))
8802 inev.kind = DELETE_WINDOW_EVENT;
8803 XSETFRAME (inev.frame_or_window,
8804 mac_window_to_frame (window_ptr));
8806 break;
8808 /* window resize handling added --ben */
8809 case inGrow:
8810 do_grow_window (window_ptr, &er);
8811 break;
8813 /* window zoom handling added --ben */
8814 case inZoomIn:
8815 case inZoomOut:
8816 if (TrackBox (window_ptr, er.where, part_code))
8817 do_zoom_window (window_ptr, part_code);
8818 break;
8820 default:
8821 break;
8824 break;
8826 case updateEvt:
8827 #if USE_CARBON_EVENTS
8828 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8829 != eventNotHandledErr)
8830 break;
8831 #else
8832 do_window_update ((WindowPtr) er.message);
8833 #endif
8834 break;
8836 case osEvt:
8837 #if USE_CARBON_EVENTS
8838 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8839 != eventNotHandledErr)
8840 break;
8841 #endif
8842 switch ((er.message >> 24) & 0x000000FF)
8844 case suspendResumeMessage:
8845 if ((er.message & resumeFlag) == 1)
8846 do_app_resume ();
8847 else
8848 do_app_suspend ();
8849 break;
8851 case mouseMovedMessage:
8852 #if !USE_CARBON_EVENTS
8853 SetRectRgn (mouse_region, er.where.h, er.where.v,
8854 er.where.h + 1, er.where.v + 1);
8855 #endif
8856 previous_help_echo_string = help_echo_string;
8857 help_echo_string = help_echo_object = help_echo_window = Qnil;
8858 help_echo_pos = -1;
8860 do_mouse_moved (er.where, &f);
8862 /* If the contents of the global variable
8863 help_echo_string has changed, generate a
8864 HELP_EVENT. */
8865 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8866 do_help = 1;
8867 break;
8869 break;
8871 case activateEvt:
8873 WindowPtr window_ptr = (WindowPtr) er.message;
8875 #if USE_CARBON_EVENTS
8876 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8877 != eventNotHandledErr)
8878 break;
8879 #endif
8880 if (window_ptr == tip_window)
8882 HideWindow (tip_window);
8883 break;
8886 if (!is_emacs_window (window_ptr))
8887 break;
8889 f = mac_window_to_frame (window_ptr);
8891 if ((er.modifiers & activeFlag) != 0)
8893 /* A window has been activated */
8894 Point mouse_loc = er.where;
8896 x_new_focus_frame (dpyinfo, f);
8897 activate_scroll_bars (f);
8899 SetPortWindowPort (window_ptr);
8900 GlobalToLocal (&mouse_loc);
8901 /* Window-activated event counts as mouse movement,
8902 so update things that depend on mouse position. */
8903 note_mouse_movement (mac_window_to_frame (window_ptr),
8904 &mouse_loc);
8906 else
8908 /* A window has been deactivated */
8909 dpyinfo->grabbed = 0;
8911 if (f == dpyinfo->x_focus_frame)
8913 x_new_focus_frame (dpyinfo, 0);
8914 deactivate_scroll_bars (f);
8918 if (f == dpyinfo->mouse_face_mouse_frame)
8920 /* If we move outside the frame, then we're
8921 certainly no longer on any text in the
8922 frame. */
8923 clear_mouse_face (dpyinfo);
8924 dpyinfo->mouse_face_mouse_frame = 0;
8927 /* Generate a nil HELP_EVENT to cancel a help-echo.
8928 Do it only if there's something to cancel.
8929 Otherwise, the startup message is cleared when the
8930 mouse leaves the frame. */
8931 if (any_help_event_p)
8932 do_help = -1;
8935 break;
8937 case keyDown:
8938 case autoKey:
8940 int keycode = (er.message & keyCodeMask) >> 8;
8941 int xkeysym;
8943 #if USE_CARBON_EVENTS
8944 /* When using Carbon Events, we need to pass raw keyboard
8945 events to the TSM ourselves. If TSM handles it, it
8946 will pass back noErr, otherwise it will pass back
8947 "eventNotHandledErr" and we can process it
8948 normally. */
8949 if ((!NILP (Vmac_pass_command_to_system)
8950 || !(er.modifiers & cmdKey))
8951 && (!NILP (Vmac_pass_control_to_system)
8952 || !(er.modifiers & controlKey)))
8953 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8954 != eventNotHandledErr)
8955 break;
8956 #endif
8958 #if TARGET_API_MAC_CARBON
8959 if (!IsValidWindowPtr (front_emacs_window ()))
8961 SysBeep (1);
8962 break;
8964 #endif
8966 ObscureCursor ();
8968 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8970 clear_mouse_face (dpyinfo);
8971 dpyinfo->mouse_face_hidden = 1;
8974 if (keycode_to_xkeysym (keycode, &xkeysym))
8976 inev.code = 0xff00 | xkeysym;
8977 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8979 else
8981 if (er.modifiers & (controlKey |
8982 (NILP (Vmac_command_key_is_meta) ? optionKey
8983 : cmdKey)))
8985 /* This code comes from Keyboard Resource,
8986 Appendix C of IM - Text. This is necessary
8987 since shift is ignored in KCHR table
8988 translation when option or command is pressed.
8989 It also does not translate correctly
8990 control-shift chars like C-% so mask off shift
8991 here also */
8992 int new_modifiers = er.modifiers & 0xe600;
8993 /* mask off option and command */
8994 int new_keycode = keycode | new_modifiers;
8995 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8996 unsigned long some_state = 0;
8997 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8998 &some_state) & 0xff;
8999 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
9001 /* When using the option key as an emacs modifier, convert
9002 the pressed key code back to one without the Mac option
9003 modifier applied. */
9004 int new_modifiers = er.modifiers & ~optionKey;
9005 int new_keycode = keycode | new_modifiers;
9006 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9007 unsigned long some_state = 0;
9008 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9009 &some_state) & 0xff;
9011 else
9012 inev.code = er.message & charCodeMask;
9013 inev.kind = ASCII_KEYSTROKE_EVENT;
9017 /* If variable mac-convert-keyboard-input-to-latin-1 is
9018 non-nil, convert non-ASCII characters typed at the Mac
9019 keyboard (presumed to be in the Mac Roman encoding) to
9020 iso-latin-1 encoding before they are passed to Emacs.
9021 This enables the Mac keyboard to be used to enter
9022 non-ASCII iso-latin-1 characters directly. */
9023 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
9024 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
9026 static TECObjectRef converter = NULL;
9027 OSStatus the_err = noErr;
9028 OSStatus convert_status = noErr;
9030 if (converter == NULL)
9032 the_err = TECCreateConverter (&converter,
9033 kTextEncodingMacRoman,
9034 mac_keyboard_text_encoding);
9035 current_mac_keyboard_text_encoding
9036 = mac_keyboard_text_encoding;
9038 else if (mac_keyboard_text_encoding
9039 != current_mac_keyboard_text_encoding)
9041 /* Free the converter for the current encoding
9042 before creating a new one. */
9043 TECDisposeConverter (converter);
9044 the_err = TECCreateConverter (&converter,
9045 kTextEncodingMacRoman,
9046 mac_keyboard_text_encoding);
9047 current_mac_keyboard_text_encoding
9048 = mac_keyboard_text_encoding;
9051 if (the_err == noErr)
9053 unsigned char ch = inev.code;
9054 ByteCount actual_input_length, actual_output_length;
9055 unsigned char outbuf[32];
9057 convert_status = TECConvertText (converter, &ch, 1,
9058 &actual_input_length,
9059 outbuf, 1,
9060 &actual_output_length);
9061 if (convert_status == noErr
9062 && actual_input_length == 1
9063 && actual_output_length == 1)
9064 inev.code = *outbuf;
9066 /* Reset internal states of the converter object.
9067 If it fails, create another one. */
9068 convert_status = TECFlushText (converter, outbuf,
9069 sizeof (outbuf),
9070 &actual_output_length);
9071 if (convert_status != noErr)
9073 TECDisposeConverter (converter);
9074 TECCreateConverter (&converter,
9075 kTextEncodingMacRoman,
9076 mac_keyboard_text_encoding);
9081 #if USE_CARBON_EVENTS
9082 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9083 #else
9084 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9085 #endif
9086 XSETFRAME (inev.frame_or_window,
9087 mac_window_to_frame (front_emacs_window ()));
9088 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
9089 break;
9091 case kHighLevelEvent:
9092 drag_and_drop_file_list = Qnil;
9094 AEProcessAppleEvent(&er);
9096 /* Build a DRAG_N_DROP_EVENT type event as is done in
9097 constuct_drag_n_drop in w32term.c. */
9098 if (!NILP (drag_and_drop_file_list))
9100 struct frame *f = NULL;
9101 WindowPtr wp;
9102 Lisp_Object frame;
9104 wp = front_emacs_window ();
9106 if (!wp)
9108 struct frame *f = XFRAME (XCAR (Vframe_list));
9109 CollapseWindow (FRAME_MAC_WINDOW (f), false);
9110 wp = front_emacs_window ();
9113 if (wp)
9114 f = mac_window_to_frame (wp);
9116 inev.kind = DRAG_N_DROP_EVENT;
9117 inev.code = 0;
9118 inev.timestamp = er.when * (1000 / 60);
9119 /* ticks to milliseconds */
9120 #if USE_CARBON_EVENTS
9121 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9122 #else
9123 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9124 #endif
9126 XSETINT (inev.x, 0);
9127 XSETINT (inev.y, 0);
9129 XSETFRAME (frame, f);
9130 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
9132 /* Regardless of whether Emacs was suspended or in the
9133 foreground, ask it to redraw its entire screen.
9134 Otherwise parts of the screen can be left in an
9135 inconsistent state. */
9136 if (wp)
9137 #if TARGET_API_MAC_CARBON
9139 Rect r;
9141 GetWindowPortBounds (wp, &r);
9142 InvalWindowRect (wp, &r);
9144 #else /* not TARGET_API_MAC_CARBON */
9145 InvalRect (&(wp->portRect));
9146 #endif /* not TARGET_API_MAC_CARBON */
9148 default:
9149 break;
9151 #if USE_CARBON_EVENTS
9152 ReleaseEvent (eventRef);
9153 #endif
9155 if (inev.kind != NO_EVENT)
9157 kbd_buffer_store_event_hold (&inev, hold_quit);
9158 count++;
9161 if (do_help
9162 && !(hold_quit && hold_quit->kind != NO_EVENT))
9164 Lisp_Object frame;
9166 if (f)
9167 XSETFRAME (frame, f);
9168 else
9169 frame = Qnil;
9171 if (do_help > 0)
9173 any_help_event_p = 1;
9174 gen_help_event (help_echo_string, frame, help_echo_window,
9175 help_echo_object, help_echo_pos);
9177 else
9179 help_echo_string = Qnil;
9180 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9182 count++;
9187 /* If the focus was just given to an autoraising frame,
9188 raise it now. */
9189 /* ??? This ought to be able to handle more than one such frame. */
9190 if (pending_autoraise_frame)
9192 x_raise_frame (pending_autoraise_frame);
9193 pending_autoraise_frame = 0;
9196 #if !TARGET_API_MAC_CARBON
9197 check_alarm (); /* simulate the handling of a SIGALRM */
9198 #endif
9200 UNBLOCK_INPUT;
9201 return count;
9205 /* Need to override CodeWarrior's input function so no conversion is
9206 done on newlines Otherwise compiled functions in .elc files will be
9207 read incorrectly. Defined in ...:MSL C:MSL
9208 Common:Source:buffer_io.c. */
9209 #ifdef __MWERKS__
9210 void
9211 __convert_to_newlines (unsigned char * p, size_t * n)
9213 #pragma unused(p,n)
9216 void
9217 __convert_from_newlines (unsigned char * p, size_t * n)
9219 #pragma unused(p,n)
9221 #endif
9223 #ifdef MAC_OS8
9224 void
9225 make_mac_terminal_frame (struct frame *f)
9227 Lisp_Object frame;
9228 Rect r;
9230 XSETFRAME (frame, f);
9232 f->output_method = output_mac;
9233 f->output_data.mac = (struct mac_output *)
9234 xmalloc (sizeof (struct mac_output));
9235 bzero (f->output_data.mac, sizeof (struct mac_output));
9237 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9239 FRAME_COLS (f) = 96;
9240 FRAME_LINES (f) = 4;
9242 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9243 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9245 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9247 f->output_data.mac->cursor_pixel = 0;
9248 f->output_data.mac->border_pixel = 0x00ff00;
9249 f->output_data.mac->mouse_pixel = 0xff00ff;
9250 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9252 f->output_data.mac->text_cursor = GetCursor (iBeamCursor);
9253 f->output_data.mac->nontext_cursor = &arrow_cursor;
9254 f->output_data.mac->modeline_cursor = &arrow_cursor;
9255 f->output_data.mac->hand_cursor = &arrow_cursor;
9256 f->output_data.mac->hourglass_cursor = GetCursor (watchCursor);
9257 f->output_data.mac->horizontal_drag_cursor = &arrow_cursor;
9259 FRAME_FONTSET (f) = -1;
9260 f->output_data.mac->explicit_parent = 0;
9261 f->left_pos = 8;
9262 f->top_pos = 32;
9263 f->border_width = 0;
9265 f->internal_border_width = 0;
9267 f->auto_raise = 1;
9268 f->auto_lower = 1;
9270 f->new_text_cols = 0;
9271 f->new_text_lines = 0;
9273 SetRect (&r, f->left_pos, f->top_pos,
9274 f->left_pos + FRAME_PIXEL_WIDTH (f),
9275 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9277 BLOCK_INPUT;
9279 if (!(FRAME_MAC_WINDOW (f) =
9280 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9281 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9282 abort ();
9283 /* so that update events can find this mac_output struct */
9284 f->output_data.mac->mFP = f; /* point back to emacs frame */
9286 UNBLOCK_INPUT;
9288 x_make_gc (f);
9290 /* Need to be initialized for unshow_buffer in window.c. */
9291 selected_window = f->selected_window;
9293 Fmodify_frame_parameters (frame,
9294 Fcons (Fcons (Qfont,
9295 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9296 Fmodify_frame_parameters (frame,
9297 Fcons (Fcons (Qforeground_color,
9298 build_string ("black")), Qnil));
9299 Fmodify_frame_parameters (frame,
9300 Fcons (Fcons (Qbackground_color,
9301 build_string ("white")), Qnil));
9303 #endif
9306 /***********************************************************************
9307 Initialization
9308 ***********************************************************************/
9310 int mac_initialized = 0;
9312 void
9313 mac_initialize_display_info ()
9315 struct mac_display_info *dpyinfo = &one_mac_display_info;
9316 GDHandle main_device_handle;
9318 bzero (dpyinfo, sizeof (*dpyinfo));
9320 #ifdef MAC_OSX
9321 dpyinfo->mac_id_name
9322 = (char *) xmalloc (SCHARS (Vinvocation_name)
9323 + SCHARS (Vsystem_name)
9324 + 2);
9325 sprintf (dpyinfo->mac_id_name, "%s@%s",
9326 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9327 #else
9328 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9329 strcpy (dpyinfo->mac_id_name, "Mac Display");
9330 #endif
9332 main_device_handle = LMGetMainDevice();
9334 dpyinfo->reference_count = 0;
9335 dpyinfo->resx = 75.0;
9336 dpyinfo->resy = 75.0;
9337 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
9338 #ifdef MAC_OSX
9339 /* HasDepth returns true if it is possible to have a 32 bit display,
9340 but this may not be what is actually used. Mac OSX can do better.
9341 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9342 header for CGGetActiveDisplayList says that the first display returned
9343 is the active one, so we use that. */
9345 CGDirectDisplayID disp_id[1];
9346 CGDisplayCount disp_count;
9347 CGDisplayErr error_code;
9349 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9350 if (error_code != 0)
9351 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9353 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9355 #else
9356 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9357 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9358 gdDevType, dpyinfo->color_p))
9359 break;
9360 #endif
9361 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9362 dpyinfo->width = (**main_device_handle).gdRect.right;
9363 dpyinfo->grabbed = 0;
9364 dpyinfo->root_window = NULL;
9365 dpyinfo->image_cache = make_image_cache ();
9367 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9368 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9369 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9370 dpyinfo->mouse_face_window = Qnil;
9371 dpyinfo->mouse_face_overlay = Qnil;
9372 dpyinfo->mouse_face_hidden = 0;
9375 /* Create an xrdb-style database of resources to supercede registry settings.
9376 The database is just a concatenation of C strings, finished by an additional
9377 \0. The string are submitted to some basic normalization, so
9379 [ *]option[ *]:[ *]value...
9381 becomes
9383 option:value...
9385 but any whitespace following value is not removed. */
9387 static char *
9388 mac_make_rdb (xrm_option)
9389 char *xrm_option;
9391 char *buffer = xmalloc (strlen (xrm_option) + 2);
9392 char *current = buffer;
9393 char ch;
9394 int in_option = 1;
9395 int before_value = 0;
9397 do {
9398 ch = *xrm_option++;
9400 if (ch == '\n')
9402 *current++ = '\0';
9403 in_option = 1;
9404 before_value = 0;
9406 else if (ch != ' ')
9408 *current++ = ch;
9409 if (in_option && (ch == ':'))
9411 in_option = 0;
9412 before_value = 1;
9414 else if (before_value)
9416 before_value = 0;
9419 else if (!(in_option || before_value))
9421 *current++ = ch;
9423 } while (ch);
9425 *current = '\0';
9427 return buffer;
9430 struct mac_display_info *
9431 mac_term_init (display_name, xrm_option, resource_name)
9432 Lisp_Object display_name;
9433 char *xrm_option;
9434 char *resource_name;
9436 struct mac_display_info *dpyinfo;
9438 BLOCK_INPUT;
9440 if (!mac_initialized)
9442 mac_initialize ();
9443 mac_initialized = 1;
9446 if (x_display_list)
9447 error ("Sorry, this version can only handle one display");
9449 mac_initialize_display_info ();
9451 dpyinfo = &one_mac_display_info;
9453 dpyinfo->xrdb = xrm_option ? mac_make_rdb (xrm_option) : NULL;
9455 /* Put this display on the chain. */
9456 dpyinfo->next = x_display_list;
9457 x_display_list = dpyinfo;
9459 /* Put it on x_display_name_list. */
9460 x_display_name_list = Fcons (Fcons (display_name, Qnil),
9461 x_display_name_list);
9462 dpyinfo->name_list_element = XCAR (x_display_name_list);
9464 UNBLOCK_INPUT;
9466 return dpyinfo;
9468 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9470 void
9471 x_delete_display (dpyinfo)
9472 struct mac_display_info *dpyinfo;
9474 int i;
9476 /* Discard this display from x_display_name_list and x_display_list.
9477 We can't use Fdelq because that can quit. */
9478 if (! NILP (x_display_name_list)
9479 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9480 x_display_name_list = XCDR (x_display_name_list);
9481 else
9483 Lisp_Object tail;
9485 tail = x_display_name_list;
9486 while (CONSP (tail) && CONSP (XCDR (tail)))
9488 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9490 XSETCDR (tail, XCDR (XCDR (tail)));
9491 break;
9493 tail = XCDR (tail);
9497 if (x_display_list == dpyinfo)
9498 x_display_list = dpyinfo->next;
9499 else
9501 struct x_display_info *tail;
9503 for (tail = x_display_list; tail; tail = tail->next)
9504 if (tail->next == dpyinfo)
9505 tail->next = tail->next->next;
9508 /* Free the font names in the font table. */
9509 for (i = 0; i < dpyinfo->n_fonts; i++)
9510 if (dpyinfo->font_table[i].name)
9512 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9513 xfree (dpyinfo->font_table[i].full_name);
9514 xfree (dpyinfo->font_table[i].name);
9517 if (dpyinfo->font_table->font_encoder)
9518 xfree (dpyinfo->font_table->font_encoder);
9520 xfree (dpyinfo->font_table);
9521 xfree (dpyinfo->mac_id_name);
9523 if (x_display_list == 0)
9525 mac_clear_font_name_table ();
9526 bzero (dpyinfo, sizeof (*dpyinfo));
9531 #ifdef MAC_OSX
9532 void
9533 mac_check_bundle()
9535 extern int inhibit_window_system;
9536 extern int noninteractive;
9537 CFBundleRef appsBundle;
9538 pid_t child;
9540 /* No need to test if already -nw*/
9541 if (inhibit_window_system || noninteractive)
9542 return;
9544 appsBundle = CFBundleGetMainBundle();
9545 if (appsBundle != NULL)
9547 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9548 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9549 /* We found the bundle identifier, now we know we are valid. */
9550 if (res != NULL)
9552 CFRelease(res);
9553 return;
9556 /* MAC_TODO: Have this start the bundled executable */
9558 /* For now, prevent the fatal error by bringing it up in the terminal */
9559 inhibit_window_system = 1;
9562 void
9563 MakeMeTheFrontProcess ()
9565 ProcessSerialNumber psn;
9566 OSErr err;
9568 err = GetCurrentProcess (&psn);
9569 if (err == noErr)
9570 (void) SetFrontProcess (&psn);
9573 /***** Code to handle C-g testing *****/
9575 /* Contains the Mac modifier formed from quit_char */
9576 static mac_quit_char_modifiers = 0;
9577 static mac_quit_char_keycode;
9578 extern int quit_char;
9580 static void
9581 mac_determine_quit_char_modifiers()
9583 /* Todo: Determine modifiers from quit_char. */
9584 UInt32 qc_modifiers = ctrl_modifier;
9586 /* Map modifiers */
9587 mac_quit_char_modifiers = 0;
9588 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9589 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9590 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9591 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9594 static void
9595 init_quit_char_handler ()
9597 /* TODO: Let this support keys other the 'g' */
9598 mac_quit_char_keycode = 5;
9599 /* Look at <architecture/adb_kb_map.h> for details */
9600 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9602 mac_determine_quit_char_modifiers();
9605 static Boolean
9606 quit_char_comp (EventRef inEvent, void *inCompData)
9608 if (GetEventClass(inEvent) != kEventClassKeyboard)
9609 return false;
9610 if (GetEventKind(inEvent) != kEventRawKeyDown)
9611 return false;
9613 UInt32 keyCode;
9614 UInt32 keyModifiers;
9615 GetEventParameter(inEvent, kEventParamKeyCode,
9616 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9617 if (keyCode != mac_quit_char_keycode)
9618 return false;
9619 GetEventParameter(inEvent, kEventParamKeyModifiers,
9620 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9621 if (keyModifiers != mac_quit_char_modifiers)
9622 return false;
9624 return true;
9627 void
9628 mac_check_for_quit_char ()
9630 EventRef event;
9631 static EMACS_TIME last_check_time = { 0, 0 };
9632 static EMACS_TIME one_second = { 1, 0 };
9633 EMACS_TIME now, t;
9635 /* If windows are not initialized, return immediately (keep it bouncin'). */
9636 if (!mac_quit_char_modifiers)
9637 return;
9639 /* Don't check if last check is less than a second ago. */
9640 EMACS_GET_TIME (now);
9641 EMACS_SUB_TIME (t, now, last_check_time);
9642 if (EMACS_TIME_LT (t, one_second))
9643 return;
9644 last_check_time = now;
9646 /* Redetermine modifiers because they are based on lisp variables */
9647 mac_determine_quit_char_modifiers ();
9649 /* Fill the queue with events */
9650 BLOCK_INPUT;
9651 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9652 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9653 NULL);
9654 UNBLOCK_INPUT;
9655 if (event)
9657 struct input_event e;
9659 /* Use an input_event to emulate what the interrupt handler does. */
9660 EVENT_INIT (e);
9661 e.kind = ASCII_KEYSTROKE_EVENT;
9662 e.code = quit_char;
9663 e.arg = Qnil;
9664 e.modifiers = NULL;
9665 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9666 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9667 /* Remove event from queue to prevent looping. */
9668 RemoveEventFromQueue (GetMainEventQueue (), event);
9669 ReleaseEvent (event);
9670 kbd_buffer_store_event (&e);
9674 #endif /* MAC_OSX */
9676 /* Set up use of X before we make the first connection. */
9678 extern frame_parm_handler mac_frame_parm_handlers[];
9680 static struct redisplay_interface x_redisplay_interface =
9682 mac_frame_parm_handlers,
9683 x_produce_glyphs,
9684 x_write_glyphs,
9685 x_insert_glyphs,
9686 x_clear_end_of_line,
9687 x_scroll_run,
9688 x_after_update_window_line,
9689 x_update_window_begin,
9690 x_update_window_end,
9691 x_cursor_to,
9692 x_flush,
9693 0, /* flush_display_optional */
9694 x_clear_window_mouse_face,
9695 x_get_glyph_overhangs,
9696 x_fix_overlapping_area,
9697 x_draw_fringe_bitmap,
9698 0, /* define_fringe_bitmap */
9699 0, /* destroy_fringe_bitmap */
9700 mac_per_char_metric,
9701 mac_encode_char,
9702 NULL, /* mac_compute_glyph_string_overhangs */
9703 x_draw_glyph_string,
9704 mac_define_frame_cursor,
9705 mac_clear_frame_area,
9706 mac_draw_window_cursor,
9707 mac_draw_vertical_window_border,
9708 mac_shift_glyphs_for_insert
9711 void
9712 mac_initialize ()
9714 rif = &x_redisplay_interface;
9716 clear_frame_hook = x_clear_frame;
9717 ins_del_lines_hook = x_ins_del_lines;
9718 delete_glyphs_hook = x_delete_glyphs;
9719 ring_bell_hook = XTring_bell;
9720 reset_terminal_modes_hook = XTreset_terminal_modes;
9721 set_terminal_modes_hook = XTset_terminal_modes;
9722 update_begin_hook = x_update_begin;
9723 update_end_hook = x_update_end;
9724 set_terminal_window_hook = XTset_terminal_window;
9725 read_socket_hook = XTread_socket;
9726 frame_up_to_date_hook = XTframe_up_to_date;
9727 mouse_position_hook = XTmouse_position;
9728 frame_rehighlight_hook = XTframe_rehighlight;
9729 frame_raise_lower_hook = XTframe_raise_lower;
9731 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9732 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9733 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9734 judge_scroll_bars_hook = XTjudge_scroll_bars;
9736 scroll_region_ok = 1; /* we'll scroll partial frames */
9737 char_ins_del_ok = 1;
9738 line_ins_del_ok = 1; /* we'll just blt 'em */
9739 fast_clear_end_of_line = 1; /* X does this well */
9740 memory_below_frame = 0; /* we don't remember what scrolls
9741 off the bottom */
9742 baud_rate = 19200;
9744 x_noop_count = 0;
9745 last_tool_bar_item = -1;
9746 any_help_event_p = 0;
9748 /* Try to use interrupt input; if we can't, then start polling. */
9749 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9751 #ifdef USE_X_TOOLKIT
9752 XtToolkitInitialize ();
9753 Xt_app_con = XtCreateApplicationContext ();
9754 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9756 /* Install an asynchronous timer that processes Xt timeout events
9757 every 0.1s. This is necessary because some widget sets use
9758 timeouts internally, for example the LessTif menu bar, or the
9759 Xaw3d scroll bar. When Xt timouts aren't processed, these
9760 widgets don't behave normally. */
9762 EMACS_TIME interval;
9763 EMACS_SET_SECS_USECS (interval, 0, 100000);
9764 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9766 #endif
9768 #if USE_TOOLKIT_SCROLL_BARS
9769 xaw3d_arrow_scroll = False;
9770 xaw3d_pick_top = True;
9771 #endif
9773 #if 0
9774 /* Note that there is no real way portable across R3/R4 to get the
9775 original error handler. */
9776 XSetErrorHandler (x_error_handler);
9777 XSetIOErrorHandler (x_io_error_quitter);
9779 /* Disable Window Change signals; they are handled by X events. */
9780 #ifdef SIGWINCH
9781 signal (SIGWINCH, SIG_DFL);
9782 #endif /* ! defined (SIGWINCH) */
9784 signal (SIGPIPE, x_connection_signal);
9785 #endif
9787 BLOCK_INPUT;
9789 #if TARGET_API_MAC_CARBON
9790 init_required_apple_events ();
9792 #if USE_CARBON_EVENTS
9793 init_service_handler ();
9795 init_quit_char_handler ();
9796 #endif
9798 DisableMenuCommand (NULL, kHICommandQuit);
9800 if (!inhibit_window_system)
9801 MakeMeTheFrontProcess ();
9802 #endif
9803 UNBLOCK_INPUT;
9807 void
9808 syms_of_macterm ()
9810 #if 0
9811 staticpro (&x_error_message_string);
9812 x_error_message_string = Qnil;
9813 #endif
9815 Qmodifier_value = intern ("modifier-value");
9816 Qalt = intern ("alt");
9817 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9818 Qhyper = intern ("hyper");
9819 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9820 Qsuper = intern ("super");
9821 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9823 #ifdef MAC_OSX
9824 Fprovide (intern ("mac-carbon"), Qnil);
9825 #endif
9827 staticpro (&Qreverse);
9828 Qreverse = intern ("reverse");
9830 staticpro (&x_display_name_list);
9831 x_display_name_list = Qnil;
9833 staticpro (&last_mouse_scroll_bar);
9834 last_mouse_scroll_bar = Qnil;
9836 staticpro (&Qvendor_specific_keysyms);
9837 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9839 staticpro (&last_mouse_press_frame);
9840 last_mouse_press_frame = Qnil;
9842 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9843 staticpro (&Qmac_ready_for_drag_n_drop);
9845 Qbig5 = intern ("big5");
9846 staticpro (&Qbig5);
9848 Qcn_gb = intern ("cn-gb");
9849 staticpro (&Qcn_gb);
9851 Qsjis = intern ("sjis");
9852 staticpro (&Qsjis);
9854 Qeuc_kr = intern ("euc-kr");
9855 staticpro (&Qeuc_kr);
9857 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9858 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9859 x_autoselect_window_p = 0;
9861 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9862 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9863 Vx_toolkit_scroll_bars = Qt;
9865 DEFVAR_BOOL ("x-use-underline-position-properties",
9866 &x_use_underline_position_properties,
9867 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9868 nil means ignore them. If you encounter fonts with bogus
9869 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9870 to 4.1, set this to nil. */);
9871 x_use_underline_position_properties = 0;
9873 staticpro (&last_mouse_motion_frame);
9874 last_mouse_motion_frame = Qnil;
9876 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9877 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9878 Otherwise the option key is used. */);
9879 Vmac_command_key_is_meta = Qt;
9881 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9882 doc: /* Modifier to use for the Mac alt/option key. The value can
9883 be alt, hyper, or super for the respective modifier. If the value is
9884 nil then the key will act as the normal Mac option modifier. */);
9885 Vmac_option_modifier = Qnil;
9887 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9888 doc: /* Non-nil means that the control and meta keys are reversed. This is
9889 useful for non-standard keyboard layouts. */);
9890 Vmac_reverse_ctrl_meta = Qnil;
9892 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9893 &Vmac_emulate_three_button_mouse,
9894 doc: /* t means that when the option-key is held down while pressing the
9895 mouse button, the click will register as mouse-2 and while the
9896 command-key is held down, the click will register as mouse-3.
9897 'reverse means that the the option-key will register for mouse-3
9898 and the command-key will register for mouse-2. nil means that
9899 not emulation should be done and the modifiers should be placed
9900 on the mouse-1 event. */);
9901 Vmac_emulate_three_button_mouse = Qnil;
9903 #if USE_CARBON_EVENTS
9904 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9905 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9906 the right click will be mouse-3.
9907 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9908 Vmac_wheel_button_is_mouse_2 = Qt;
9910 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9911 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9912 Toolbox for processing before Emacs sees it. */);
9913 Vmac_pass_command_to_system = Qt;
9915 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9916 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9917 Toolbox for processing before Emacs sees it. */);
9918 Vmac_pass_control_to_system = Qt;
9920 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9921 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9922 Toolbox for processing before Emacs sees it. */);
9923 Vmac_pass_control_to_system = Qt;
9924 #endif
9926 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
9927 doc: /* If non-nil, allow anti-aliasing.
9928 The text will be rendered using Core Graphics text rendering which
9929 may anti-alias the text. */);
9930 Vmac_use_core_graphics = Qnil;
9932 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9933 doc: /* One of the Text Encoding Base constant values defined in the
9934 Basic Text Constants section of Inside Macintosh - Text Encoding
9935 Conversion Manager. Its value determines the encoding characters
9936 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9937 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9938 its default value, no conversion takes place. If it is set to
9939 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9940 characters typed on Mac keyboard are first converted into the
9941 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9942 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9943 command, this enables the Mac keyboard to be used to enter non-ASCII
9944 characters directly. */);
9945 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9948 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9949 (do not change this comment) */