*** empty log message ***
[emacs.git] / src / macterm.c
blob566f0c5b04b2fe2dc32b489135c61f771adb8bf1
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
31 #include "macterm.h"
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
37 #ifdef MAC_OSX
38 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
40 used instead. */
41 #define USE_CARBON_EVENTS 1
42 #else /* not MAC_OSX */
43 #include <Quickdraw.h>
44 #include <ToolUtils.h>
45 #include <Sound.h>
46 #include <Events.h>
47 #include <Script.h>
48 #include <Resources.h>
49 #include <Fonts.h>
50 #include <TextUtils.h>
51 #include <LowMem.h>
52 #include <Controls.h>
53 #include <Windows.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
56 #endif
58 #if __profile__
59 #include <profiler.h>
60 #endif
61 #endif /* not MAC_OSX */
63 #include "systty.h"
64 #include "systime.h"
65 #include "atimer.h"
66 #include "keymap.h"
68 #include <ctype.h>
69 #include <errno.h>
70 #include <setjmp.h>
71 #include <sys/stat.h>
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 /* Non-zero means that a HELP_EVENT has been generated since Emacs
105 start. */
107 static int any_help_event_p;
109 /* Non-zero means autoselect window with the mouse cursor. */
111 int x_autoselect_window_p;
113 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
115 int x_use_underline_position_properties;
117 /* Non-zero means draw block and hollow cursor as wide as the glyph
118 under it. For example, if a block cursor is over a tab, it will be
119 drawn as wide as that tab on the display. */
122 /* This is a chain of structures for all the X displays currently in
123 use. */
125 struct x_display_info *x_display_list;
127 /* This is a list of cons cells, each of the form (NAME
128 . FONT-LIST-CACHE), one for each element of x_display_list and in
129 the same order. NAME is the name of the frame. FONT-LIST-CACHE
130 records previous values returned by x-list-fonts. */
132 Lisp_Object x_display_name_list;
134 /* This is display since Mac does not support multiple ones. */
135 struct mac_display_info one_mac_display_info;
137 /* Frame being updated by update_frame. This is declared in term.c.
138 This is set by update_begin and looked at by all the XT functions.
139 It is zero while not inside an update. In that case, the XT
140 functions assume that `selected_frame' is the frame to apply to. */
142 extern struct frame *updating_frame;
144 extern int waiting_for_input;
146 /* This is a frame waiting to be auto-raised, within XTread_socket. */
148 struct frame *pending_autoraise_frame;
150 /* Non-zero means user is interacting with a toolkit scroll bar. */
152 static int toolkit_scroll_bar_interaction;
154 /* Mouse movement.
156 Formerly, we used PointerMotionHintMask (in standard_event_mask)
157 so that we would have to call XQueryPointer after each MotionNotify
158 event to ask for another such event. However, this made mouse tracking
159 slow, and there was a bug that made it eventually stop.
161 Simply asking for MotionNotify all the time seems to work better.
163 In order to avoid asking for motion events and then throwing most
164 of them away or busy-polling the server for mouse positions, we ask
165 the server for pointer motion hints. This means that we get only
166 one event per group of mouse movements. "Groups" are delimited by
167 other kinds of events (focus changes and button clicks, for
168 example), or by XQueryPointer calls; when one of these happens, we
169 get another MotionNotify event the next time the mouse moves. This
170 is at least as efficient as getting motion events when mouse
171 tracking is on, and I suspect only negligibly worse when tracking
172 is off. */
174 /* Where the mouse was last time we reported a mouse event. */
176 static Rect last_mouse_glyph;
177 static Lisp_Object last_mouse_press_frame;
179 /* The scroll bar in which the last X motion event occurred.
181 If the last X motion event occurred in a scroll bar, we set this so
182 XTmouse_position can know whether to report a scroll bar motion or
183 an ordinary motion.
185 If the last X motion event didn't occur in a scroll bar, we set
186 this to Qnil, to tell XTmouse_position to return an ordinary motion
187 event. */
189 static Lisp_Object last_mouse_scroll_bar;
191 /* This is a hack. We would really prefer that XTmouse_position would
192 return the time associated with the position it returns, but there
193 doesn't seem to be any way to wrest the time-stamp from the server
194 along with the position query. So, we just keep track of the time
195 of the last movement we received, and return that in hopes that
196 it's somewhat accurate. */
198 static Time last_mouse_movement_time;
200 struct scroll_bar *tracked_scroll_bar = NULL;
202 /* Incremented by XTread_socket whenever it really tries to read
203 events. */
205 #ifdef __STDC__
206 static int volatile input_signal_count;
207 #else
208 static int input_signal_count;
209 #endif
211 /* Used locally within XTread_socket. */
213 static int x_noop_count;
215 /* Initial values of argv and argc. */
217 extern char **initial_argv;
218 extern int initial_argc;
220 extern Lisp_Object Vcommand_line_args, Vsystem_name;
222 /* Tells if a window manager is present or not. */
224 extern Lisp_Object Vx_no_window_manager;
226 extern int errno;
228 /* A mask of extra modifier bits to put into every keyboard char. */
230 extern int extra_keyboard_modifiers;
232 /* The keysyms to use for the various modifiers. */
234 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
236 static Lisp_Object Qvendor_specific_keysyms;
238 #if 0
239 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
240 #endif
242 extern int inhibit_window_system;
244 #if __MRC__
245 QDGlobals qd; /* QuickDraw global information structure. */
246 #endif
249 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
250 struct mac_display_info *mac_display_info_for_display (Display *);
251 static void x_update_window_end P_ ((struct window *, int, int));
252 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
253 static int x_io_error_quitter P_ ((Display *));
254 int x_catch_errors P_ ((Display *));
255 void x_uncatch_errors P_ ((Display *, int));
256 void x_lower_frame P_ ((struct frame *));
257 void x_scroll_bar_clear P_ ((struct frame *));
258 int x_had_errors_p P_ ((Display *));
259 void x_wm_set_size_hint P_ ((struct frame *, long, int));
260 void x_raise_frame P_ ((struct frame *));
261 void x_set_window_size P_ ((struct frame *, int, int, int));
262 void x_wm_set_window_state P_ ((struct frame *, int));
263 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
264 void mac_initialize P_ ((void));
265 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
266 static int x_compute_min_glyph_bounds P_ ((struct frame *));
267 static void x_update_end P_ ((struct frame *));
268 static void XTframe_up_to_date P_ ((struct frame *));
269 static void XTreassert_line_highlight P_ ((int, int));
270 static void x_change_line_highlight P_ ((int, int, int, int));
271 static void XTset_terminal_modes P_ ((void));
272 static void XTreset_terminal_modes P_ ((void));
273 static void x_clear_frame P_ ((void));
274 static void frame_highlight P_ ((struct frame *));
275 static void frame_unhighlight P_ ((struct frame *));
276 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
277 static void XTframe_rehighlight P_ ((struct frame *));
278 static void x_frame_rehighlight P_ ((struct x_display_info *));
279 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
280 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
281 enum text_cursor_kinds));
283 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
284 static void x_flush P_ ((struct frame *f));
285 static void x_update_begin P_ ((struct frame *));
286 static void x_update_window_begin P_ ((struct window *));
287 static void x_after_update_window_line P_ ((struct glyph_row *));
289 void activate_scroll_bars (FRAME_PTR);
290 void deactivate_scroll_bars (FRAME_PTR);
292 static int is_emacs_window (WindowPtr);
294 int x_bitmap_icon (struct frame *, Lisp_Object);
295 void x_make_frame_visible (struct frame *);
297 extern void window_scroll (Lisp_Object, int, int, int);
299 /* Defined in macmenu.h. */
300 extern void menubar_selection_callback (FRAME_PTR, int);
301 extern void set_frame_menubar (FRAME_PTR, int, int);
303 /* X display function emulation */
305 void
306 XFreePixmap (display, pixmap)
307 Display *display; /* not used */
308 Pixmap pixmap;
310 DisposeGWorld (pixmap);
314 /* Set foreground color for subsequent QuickDraw commands. Assume
315 graphic port has already been set. */
317 static void
318 mac_set_forecolor (unsigned long color)
320 RGBColor fg_color;
322 fg_color.red = RED16_FROM_ULONG (color);
323 fg_color.green = GREEN16_FROM_ULONG (color);
324 fg_color.blue = BLUE16_FROM_ULONG (color);
326 RGBForeColor (&fg_color);
330 /* Set background color for subsequent QuickDraw commands. Assume
331 graphic port has already been set. */
333 static void
334 mac_set_backcolor (unsigned long color)
336 RGBColor bg_color;
338 bg_color.red = RED16_FROM_ULONG (color);
339 bg_color.green = GREEN16_FROM_ULONG (color);
340 bg_color.blue = BLUE16_FROM_ULONG (color);
342 RGBBackColor (&bg_color);
345 /* Set foreground and background color for subsequent QuickDraw
346 commands. Assume that the graphic port has already been set. */
348 static void
349 mac_set_colors (GC gc)
351 mac_set_forecolor (gc->foreground);
352 mac_set_backcolor (gc->background);
355 /* Mac version of XDrawLine. */
357 static void
358 XDrawLine (display, w, gc, x1, y1, x2, y2)
359 Display *display;
360 WindowPtr w;
361 GC gc;
362 int x1, y1, x2, y2;
364 SetPortWindowPort (w);
366 mac_set_colors (gc);
368 MoveTo (x1, y1);
369 LineTo (x2, y2);
372 void
373 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
374 Display *display;
375 Pixmap p;
376 GC gc;
377 int x1, y1, x2, y2;
379 CGrafPtr old_port;
380 GDHandle old_gdh;
382 GetGWorld (&old_port, &old_gdh);
383 SetGWorld (p, NULL);
385 mac_set_colors (gc);
387 LockPixels (GetGWorldPixMap (p));
388 MoveTo (x1, y1);
389 LineTo (x2, y2);
390 UnlockPixels (GetGWorldPixMap (p));
392 SetGWorld (old_port, old_gdh);
395 /* Mac version of XClearArea. */
397 void
398 XClearArea (display, w, x, y, width, height, exposures)
399 Display *display;
400 WindowPtr w;
401 int x, y;
402 unsigned int width, height;
403 int exposures;
405 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
406 Rect r;
407 XGCValues xgc;
409 xgc.foreground = mwp->x_compatible.foreground_pixel;
410 xgc.background = mwp->x_compatible.background_pixel;
412 SetPortWindowPort (w);
414 mac_set_colors (&xgc);
415 SetRect (&r, x, y, x + width, y + height);
417 EraseRect (&r);
420 /* Mac version of XClearWindow. */
422 static void
423 XClearWindow (display, w)
424 Display *display;
425 WindowPtr w;
427 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
428 XGCValues xgc;
430 xgc.foreground = mwp->x_compatible.foreground_pixel;
431 xgc.background = mwp->x_compatible.background_pixel;
433 SetPortWindowPort (w);
435 mac_set_colors (&xgc);
437 #if TARGET_API_MAC_CARBON
439 Rect r;
441 GetWindowPortBounds (w, &r);
442 EraseRect (&r);
444 #else /* not TARGET_API_MAC_CARBON */
445 EraseRect (&(w->portRect));
446 #endif /* not TARGET_API_MAC_CARBON */
450 /* Mac replacement for XCopyArea. */
452 static void
453 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
454 Display *display;
455 WindowPtr w;
456 GC gc;
457 int x, y, width, height;
458 unsigned short *bits;
459 int overlay_p;
461 BitMap bitmap;
462 Rect r;
464 bitmap.rowBytes = sizeof(unsigned short);
465 bitmap.baseAddr = (char *)bits;
466 SetRect (&(bitmap.bounds), 0, 0, width, height);
468 SetPortWindowPort (w);
470 mac_set_colors (gc);
471 SetRect (&r, x, y, x + width, y + height);
473 #if TARGET_API_MAC_CARBON
474 LockPortBits (GetWindowPort (w));
475 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
476 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
477 UnlockPortBits (GetWindowPort (w));
478 #else /* not TARGET_API_MAC_CARBON */
479 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
480 overlay_p ? srcOr : srcCopy, 0);
481 #endif /* not TARGET_API_MAC_CARBON */
485 /* Mac replacement for XSetClipRectangles. */
487 static void
488 mac_set_clip_rectangle (display, w, r)
489 Display *display;
490 WindowPtr w;
491 Rect *r;
493 SetPortWindowPort (w);
495 ClipRect (r);
499 /* Mac replacement for XSetClipMask. */
501 static void
502 mac_reset_clipping (display, w)
503 Display *display;
504 WindowPtr w;
506 Rect r;
508 SetPortWindowPort (w);
510 SetRect (&r, -32767, -32767, 32767, 32767);
511 ClipRect (&r);
515 /* Mac replacement for XCreateBitmapFromBitmapData. */
517 static void
518 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
519 BitMap *bitmap;
520 char *bits;
521 int w, h;
523 static unsigned char swap_nibble[16]
524 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
525 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
526 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
527 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
528 int i, j, w1;
529 char *p;
531 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
532 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
533 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
534 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
535 for (i = 0; i < h; i++)
537 p = bitmap->baseAddr + i * bitmap->rowBytes;
538 for (j = 0; j < w1; j++)
540 /* Bitswap XBM bytes to match how Mac does things. */
541 unsigned char c = *bits++;
542 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
543 | (swap_nibble[(c>>4) & 0xf]));;
547 SetRect (&(bitmap->bounds), 0, 0, w, h);
551 static void
552 mac_free_bitmap (bitmap)
553 BitMap *bitmap;
555 xfree (bitmap->baseAddr);
559 Pixmap
560 XCreatePixmap (display, w, width, height, depth)
561 Display *display; /* not used */
562 WindowPtr w;
563 unsigned int width, height;
564 unsigned int depth;
566 Pixmap pixmap;
567 Rect r;
568 QDErr err;
570 SetPortWindowPort (w);
572 SetRect (&r, 0, 0, width, height);
573 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
574 if (err != noErr)
575 return NULL;
576 return pixmap;
580 Pixmap
581 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
582 Display *display; /* not used */
583 WindowPtr w;
584 char *data;
585 unsigned int width, height;
586 unsigned long fg, bg;
587 unsigned int depth; /* not used */
589 Pixmap pixmap;
590 BitMap bitmap;
591 CGrafPtr old_port;
592 GDHandle old_gdh;
594 pixmap = XCreatePixmap (display, w, width, height, depth);
595 if (pixmap == NULL)
596 return NULL;
598 GetGWorld (&old_port, &old_gdh);
599 SetGWorld (pixmap, NULL);
600 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
601 mac_set_forecolor (fg);
602 mac_set_backcolor (bg);
603 LockPixels (GetGWorldPixMap (pixmap));
604 #if TARGET_API_MAC_CARBON
605 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
606 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
607 #else /* not TARGET_API_MAC_CARBON */
608 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
609 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
610 #endif /* not TARGET_API_MAC_CARBON */
611 UnlockPixels (GetGWorldPixMap (pixmap));
612 SetGWorld (old_port, old_gdh);
613 mac_free_bitmap (&bitmap);
615 return pixmap;
619 /* Mac replacement for XFillRectangle. */
621 static void
622 XFillRectangle (display, w, gc, x, y, width, height)
623 Display *display;
624 WindowPtr w;
625 GC gc;
626 int x, y;
627 unsigned int width, height;
629 Rect r;
631 SetPortWindowPort (w);
633 mac_set_colors (gc);
634 SetRect (&r, x, y, x + width, y + height);
636 PaintRect (&r); /* using foreground color of gc */
640 #if 0 /* TODO: figure out if we need to do this on Mac. */
641 static void
642 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
643 Display *display;
644 Pixmap p;
645 GC gc;
646 int x, y;
647 unsigned int width, height;
649 CGrafPtr old_port;
650 GDHandle old_gdh;
651 Rect r;
653 GetGWorld (&old_port, &old_gdh);
654 SetGWorld (p, NULL);
655 mac_set_colors (gc);
656 SetRect (&r, x, y, x + width, y + height);
658 LockPixels (GetGWorldPixMap (p));
659 PaintRect (&r); /* using foreground color of gc */
660 UnlockPixels (GetGWorldPixMap (p));
662 SetGWorld (old_port, old_gdh);
664 #endif
667 /* Mac replacement for XDrawRectangle: dest is a window. */
669 static void
670 mac_draw_rectangle (display, w, gc, x, y, width, height)
671 Display *display;
672 WindowPtr w;
673 GC gc;
674 int x, y;
675 unsigned int width, height;
677 Rect r;
679 SetPortWindowPort (w);
681 mac_set_colors (gc);
682 SetRect (&r, x, y, x + width + 1, y + height + 1);
684 FrameRect (&r); /* using foreground color of gc */
688 #if 0 /* TODO: figure out if we need to do this on Mac. */
689 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
691 static void
692 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
693 Display *display;
694 Pixmap p;
695 GC gc;
696 int x, y;
697 unsigned int width, height;
699 CGrafPtr old_port;
700 GDHandle old_gdh;
701 Rect r;
703 GetGWorld (&old_port, &old_gdh);
704 SetGWorld (p, NULL);
705 mac_set_colors (gc);
706 SetRect (&r, x, y, x + width + 1, y + height + 1);
708 LockPixels (GetGWorldPixMap (p));
709 FrameRect (&r); /* using foreground color of gc */
710 UnlockPixels (GetGWorldPixMap (p));
712 SetGWorld (old_port, old_gdh);
714 #endif
717 static void
718 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
719 bytes_per_char)
720 Display *display;
721 WindowPtr w;
722 GC gc;
723 int x, y;
724 char *buf;
725 int nchars, mode, bytes_per_char;
727 SetPortWindowPort (w);
729 mac_set_colors (gc);
731 TextFont (gc->font->mac_fontnum);
732 TextSize (gc->font->mac_fontsize);
733 TextFace (gc->font->mac_fontface);
734 TextMode (mode);
736 MoveTo (x, y);
737 DrawText (buf, 0, nchars * bytes_per_char);
741 /* Mac replacement for XDrawString. */
743 static void
744 XDrawString (display, w, gc, x, y, buf, nchars)
745 Display *display;
746 WindowPtr w;
747 GC gc;
748 int x, y;
749 char *buf;
750 int nchars;
752 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
756 /* Mac replacement for XDrawString16. */
758 static void
759 XDrawString16 (display, w, gc, x, y, buf, nchars)
760 Display *display;
761 WindowPtr w;
762 GC gc;
763 int x, y;
764 XChar2b *buf;
765 int nchars;
767 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
772 /* Mac replacement for XDrawImageString. */
774 static void
775 XDrawImageString (display, w, gc, x, y, buf, nchars)
776 Display *display;
777 WindowPtr w;
778 GC gc;
779 int x, y;
780 char *buf;
781 int nchars;
783 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
787 /* Mac replacement for XDrawString16. */
789 static void
790 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
791 Display *display;
792 WindowPtr w;
793 GC gc;
794 int x, y;
795 XChar2b *buf;
796 int nchars;
798 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
803 /* Mac replacement for XCopyArea: dest must be window. */
805 static void
806 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
807 dest_y)
808 Display *display;
809 Pixmap src;
810 WindowPtr dest;
811 GC gc;
812 int src_x, src_y;
813 unsigned int width, height;
814 int dest_x, dest_y;
816 Rect src_r, dest_r;
818 SetPortWindowPort (dest);
820 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
821 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
823 ForeColor (blackColor);
824 BackColor (whiteColor);
826 LockPixels (GetGWorldPixMap (src));
827 #if TARGET_API_MAC_CARBON
828 LockPortBits (GetWindowPort (dest));
829 CopyBits (GetPortBitMapForCopyBits (src),
830 GetPortBitMapForCopyBits (GetWindowPort (dest)),
831 &src_r, &dest_r, srcCopy, 0);
832 UnlockPortBits (GetWindowPort (dest));
833 #else /* not TARGET_API_MAC_CARBON */
834 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
835 &src_r, &dest_r, srcCopy, 0);
836 #endif /* not TARGET_API_MAC_CARBON */
837 UnlockPixels (GetGWorldPixMap (src));
841 static void
842 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
843 width, height, dest_x, dest_y)
844 Display *display;
845 Pixmap src, mask;
846 WindowPtr dest;
847 GC gc;
848 int src_x, src_y;
849 unsigned int width, height;
850 int dest_x, dest_y;
852 Rect src_r, dest_r;
854 SetPortWindowPort (dest);
856 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
857 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
859 ForeColor (blackColor);
860 BackColor (whiteColor);
862 LockPixels (GetGWorldPixMap (src));
863 LockPixels (GetGWorldPixMap (mask));
864 #if TARGET_API_MAC_CARBON
865 LockPortBits (GetWindowPort (dest));
866 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
867 GetPortBitMapForCopyBits (GetWindowPort (dest)),
868 &src_r, &src_r, &dest_r);
869 UnlockPortBits (GetWindowPort (dest));
870 #else /* not TARGET_API_MAC_CARBON */
871 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
872 &(dest->portBits), &src_r, &src_r, &dest_r);
873 #endif /* not TARGET_API_MAC_CARBON */
874 UnlockPixels (GetGWorldPixMap (mask));
875 UnlockPixels (GetGWorldPixMap (src));
879 #if 0
880 /* Convert a pair of local coordinates to global (screen) coordinates.
881 Assume graphic port has been properly set. */
882 static void
883 local_to_global_coord (short *h, short *v)
885 Point p;
887 p.h = *h;
888 p.v = *v;
890 LocalToGlobal (&p);
892 *h = p.h;
893 *v = p.v;
895 #endif
897 /* Mac replacement for XCopyArea: used only for scrolling. */
899 static void
900 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
901 Display *display;
902 WindowPtr w;
903 GC gc;
904 int src_x, src_y;
905 unsigned int width, height;
906 int dest_x, dest_y;
908 #if TARGET_API_MAC_CARBON
909 Rect src_r;
910 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
912 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
913 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
914 kScrollWindowNoOptions, dummy);
915 DisposeRgn (dummy);
916 #else /* not TARGET_API_MAC_CARBON */
917 Rect src_r, dest_r;
919 SetPort (w);
920 #if 0
921 mac_set_colors (gc);
922 #endif
924 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
925 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
927 #if 0
928 /* Need to use global coordinates and screenBits since src and dest
929 areas overlap in general. */
930 local_to_global_coord (&src_r.left, &src_r.top);
931 local_to_global_coord (&src_r.right, &src_r.bottom);
932 local_to_global_coord (&dest_r.left, &dest_r.top);
933 local_to_global_coord (&dest_r.right, &dest_r.bottom);
935 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
936 #else
937 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
938 color mapping in CopyBits. Otherwise, it will be slow. */
939 ForeColor (blackColor);
940 BackColor (whiteColor);
941 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
943 mac_set_colors (gc);
944 #endif
945 #endif /* not TARGET_API_MAC_CARBON */
949 #if 0 /* TODO: figure out if we need to do this on Mac. */
950 /* Mac replacement for XCopyArea: dest must be Pixmap. */
952 static void
953 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
954 dest_x, dest_y)
955 Display *display;
956 Pixmap src, dest;
957 GC gc;
958 int src_x, src_y;
959 unsigned int width, height;
960 int dest_x, dest_y;
962 CGrafPtr old_port;
963 GDHandle old_gdh;
964 Rect src_r, dest_r;
966 GetGWorld (&old_port, &old_gdh);
967 SetGWorld (dest, NULL);
968 ForeColor (blackColor);
969 BackColor (whiteColor);
971 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
972 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
974 LockPixels (GetGWorldPixMap (src));
975 LockPixels (GetGWorldPixMap (dest));
976 #if TARGET_API_MAC_CARBON
977 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
978 &src_r, &dest_r, srcCopy, 0);
979 #else /* not TARGET_API_MAC_CARBON */
980 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
981 &src_r, &dest_r, srcCopy, 0);
982 #endif /* not TARGET_API_MAC_CARBON */
983 UnlockPixels (GetGWorldPixMap (dest));
984 UnlockPixels (GetGWorldPixMap (src));
986 SetGWorld (old_port, old_gdh);
990 static void
991 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
992 width, height, dest_x, dest_y)
993 Display *display;
994 Pixmap src, mask, dest;
995 GC gc;
996 int src_x, src_y;
997 unsigned int width, height;
998 int dest_x, dest_y;
1000 CGrafPtr old_port;
1001 GDHandle old_gdh;
1002 Rect src_r, dest_r;
1004 GetGWorld (&old_port, &old_gdh);
1005 SetGWorld (dest, NULL);
1006 ForeColor (blackColor);
1007 BackColor (whiteColor);
1009 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1010 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1012 LockPixels (GetGWorldPixMap (src));
1013 LockPixels (GetGWorldPixMap (mask));
1014 LockPixels (GetGWorldPixMap (dest));
1015 #if TARGET_API_MAC_CARBON
1016 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1017 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1018 #else /* not TARGET_API_MAC_CARBON */
1019 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1020 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1021 #endif /* not TARGET_API_MAC_CARBON */
1022 UnlockPixels (GetGWorldPixMap (dest));
1023 UnlockPixels (GetGWorldPixMap (mask));
1024 UnlockPixels (GetGWorldPixMap (src));
1026 SetGWorld (old_port, old_gdh);
1028 #endif
1031 /* Mac replacement for XChangeGC. */
1033 static void
1034 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1035 XGCValues *xgcv)
1037 if (mask & GCForeground)
1038 gc->foreground = xgcv->foreground;
1039 if (mask & GCBackground)
1040 gc->background = xgcv->background;
1041 if (mask & GCFont)
1042 gc->font = xgcv->font;
1046 /* Mac replacement for XCreateGC. */
1048 XGCValues *
1049 XCreateGC (void * ignore, Window window, unsigned long mask,
1050 XGCValues *xgcv)
1052 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1053 bzero (gc, sizeof (XGCValues));
1055 XChangeGC (ignore, gc, mask, xgcv);
1057 return gc;
1061 /* Used in xfaces.c. */
1063 void
1064 XFreeGC (display, gc)
1065 Display *display;
1066 GC gc;
1068 xfree (gc);
1072 /* Mac replacement for XGetGCValues. */
1074 static void
1075 XGetGCValues (void* ignore, XGCValues *gc,
1076 unsigned long mask, XGCValues *xgcv)
1078 XChangeGC (ignore, xgcv, mask, gc);
1082 /* Mac replacement for XSetForeground. */
1084 void
1085 XSetForeground (display, gc, color)
1086 Display *display;
1087 GC gc;
1088 unsigned long color;
1090 gc->foreground = color;
1094 /* Mac replacement for XSetFont. */
1096 static void
1097 XSetFont (display, gc, font)
1098 Display *display;
1099 GC gc;
1100 XFontStruct *font;
1102 gc->font = font;
1106 static void
1107 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1108 int *direction,int *font_ascent,
1109 int *font_descent, XCharStruct *cs)
1111 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1115 /* x_sync is a no-op on Mac. */
1116 void
1117 x_sync (f)
1118 void *f;
1123 /* Flush display of frame F, or of all frames if F is null. */
1125 static void
1126 x_flush (f)
1127 struct frame *f;
1129 #if TARGET_API_MAC_CARBON
1130 BLOCK_INPUT;
1131 if (f)
1132 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1133 else
1134 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1135 UNBLOCK_INPUT;
1136 #endif
1140 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1141 Calls to XFlush should be unnecessary because the X output buffer
1142 is flushed automatically as needed by calls to XPending,
1143 XNextEvent, or XWindowEvent according to the XFlush man page.
1144 XTread_socket calls XPending. Removing XFlush improves
1145 performance. */
1147 #define XFlush(DISPLAY) (void) 0
1150 /* Return the struct mac_display_info corresponding to DPY. There's
1151 only one. */
1153 struct mac_display_info *
1154 mac_display_info_for_display (dpy)
1155 Display *dpy;
1157 return &one_mac_display_info;
1162 /***********************************************************************
1163 Starting and ending an update
1164 ***********************************************************************/
1166 /* Start an update of frame F. This function is installed as a hook
1167 for update_begin, i.e. it is called when update_begin is called.
1168 This function is called prior to calls to x_update_window_begin for
1169 each window being updated. */
1171 static void
1172 x_update_begin (f)
1173 struct frame *f;
1175 #if TARGET_API_MAC_CARBON
1176 /* During update of a frame, availability of input events is
1177 periodically checked with ReceiveNextEvent if
1178 redisplay-dont-pause is nil. That normally flushes window buffer
1179 changes for every check, and thus screen update looks waving even
1180 if no input is available. So we disable screen updates during
1181 update of a frame. */
1182 BLOCK_INPUT;
1183 DisableScreenUpdates ();
1184 UNBLOCK_INPUT;
1185 #endif
1189 /* Start update of window W. Set the global variable updated_window
1190 to the window being updated and set output_cursor to the cursor
1191 position of W. */
1193 static void
1194 x_update_window_begin (w)
1195 struct window *w;
1197 struct frame *f = XFRAME (WINDOW_FRAME (w));
1198 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1200 updated_window = w;
1201 set_output_cursor (&w->cursor);
1203 BLOCK_INPUT;
1205 if (f == display_info->mouse_face_mouse_frame)
1207 /* Don't do highlighting for mouse motion during the update. */
1208 display_info->mouse_face_defer = 1;
1210 /* If F needs to be redrawn, simply forget about any prior mouse
1211 highlighting. */
1212 if (FRAME_GARBAGED_P (f))
1213 display_info->mouse_face_window = Qnil;
1215 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1216 their mouse_face_p flag set, which means that they are always
1217 unequal to rows in a desired matrix which never have that
1218 flag set. So, rows containing mouse-face glyphs are never
1219 scrolled, and we don't have to switch the mouse highlight off
1220 here to prevent it from being scrolled. */
1222 /* Can we tell that this update does not affect the window
1223 where the mouse highlight is? If so, no need to turn off.
1224 Likewise, don't do anything if the frame is garbaged;
1225 in that case, the frame's current matrix that we would use
1226 is all wrong, and we will redisplay that line anyway. */
1227 if (!NILP (display_info->mouse_face_window)
1228 && w == XWINDOW (display_info->mouse_face_window))
1230 int i;
1232 for (i = 0; i < w->desired_matrix->nrows; ++i)
1233 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1234 break;
1236 if (i < w->desired_matrix->nrows)
1237 clear_mouse_face (display_info);
1239 #endif /* 0 */
1242 UNBLOCK_INPUT;
1246 /* Draw a vertical window border from (x,y0) to (x,y1) */
1248 static void
1249 mac_draw_vertical_window_border (w, x, y0, y1)
1250 struct window *w;
1251 int x, y0, y1;
1253 struct frame *f = XFRAME (WINDOW_FRAME (w));
1255 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1256 f->output_data.mac->normal_gc, x, y0, x, y1);
1260 /* End update of window W (which is equal to updated_window).
1262 Draw vertical borders between horizontally adjacent windows, and
1263 display W's cursor if CURSOR_ON_P is non-zero.
1265 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1266 glyphs in mouse-face were overwritten. In that case we have to
1267 make sure that the mouse-highlight is properly redrawn.
1269 W may be a menu bar pseudo-window in case we don't have X toolkit
1270 support. Such windows don't have a cursor, so don't display it
1271 here. */
1273 static void
1274 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1275 struct window *w;
1276 int cursor_on_p, mouse_face_overwritten_p;
1278 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1280 if (!w->pseudo_window_p)
1282 BLOCK_INPUT;
1284 if (cursor_on_p)
1285 display_and_set_cursor (w, 1, output_cursor.hpos,
1286 output_cursor.vpos,
1287 output_cursor.x, output_cursor.y);
1289 if (draw_window_fringes (w, 1))
1290 x_draw_vertical_border (w);
1292 UNBLOCK_INPUT;
1295 /* If a row with mouse-face was overwritten, arrange for
1296 XTframe_up_to_date to redisplay the mouse highlight. */
1297 if (mouse_face_overwritten_p)
1299 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1300 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1301 dpyinfo->mouse_face_window = Qnil;
1304 #if 0
1305 /* Unhide the caret. This won't actually show the cursor, unless it
1306 was visible before the corresponding call to HideCaret in
1307 x_update_window_begin. */
1308 if (w32_use_visible_system_caret)
1309 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1310 #endif
1312 updated_window = NULL;
1316 /* End update of frame F. This function is installed as a hook in
1317 update_end. */
1319 static void
1320 x_update_end (f)
1321 struct frame *f;
1323 /* Mouse highlight may be displayed again. */
1324 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1326 BLOCK_INPUT;
1327 /* Reset the background color of Mac OS Window to that of the frame after
1328 update so that it is used by Mac Toolbox to clear the update region before
1329 an update event is generated. */
1330 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1332 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1334 #if TARGET_API_MAC_CARBON
1335 EnableScreenUpdates ();
1336 #endif
1337 XFlush (FRAME_MAC_DISPLAY (f));
1338 UNBLOCK_INPUT;
1342 /* This function is called from various places in xdisp.c whenever a
1343 complete update has been performed. The global variable
1344 updated_window is not available here. */
1346 static void
1347 XTframe_up_to_date (f)
1348 struct frame *f;
1350 if (FRAME_MAC_P (f))
1352 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1354 if (dpyinfo->mouse_face_deferred_gc
1355 || f == dpyinfo->mouse_face_mouse_frame)
1357 BLOCK_INPUT;
1358 if (dpyinfo->mouse_face_mouse_frame)
1359 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1360 dpyinfo->mouse_face_mouse_x,
1361 dpyinfo->mouse_face_mouse_y);
1362 dpyinfo->mouse_face_deferred_gc = 0;
1363 UNBLOCK_INPUT;
1369 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1370 arrow bitmaps, or clear the fringes if no bitmaps are required
1371 before DESIRED_ROW is made current. The window being updated is
1372 found in updated_window. This function is called from
1373 update_window_line only if it is known that there are differences
1374 between bitmaps to be drawn between current row and DESIRED_ROW. */
1376 static void
1377 x_after_update_window_line (desired_row)
1378 struct glyph_row *desired_row;
1380 struct window *w = updated_window;
1381 struct frame *f;
1382 int width, height;
1384 xassert (w);
1386 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1387 desired_row->redraw_fringe_bitmaps_p = 1;
1389 /* When a window has disappeared, make sure that no rest of
1390 full-width rows stays visible in the internal border. Could
1391 check here if updated_window is the leftmost/rightmost window,
1392 but I guess it's not worth doing since vertically split windows
1393 are almost never used, internal border is rarely set, and the
1394 overhead is very small. */
1395 if (windows_or_buffers_changed
1396 && desired_row->full_width_p
1397 && (f = XFRAME (w->frame),
1398 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1399 width != 0)
1400 && (height = desired_row->visible_height,
1401 height > 0))
1403 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1404 /* Internal border is drawn below the tool bar. */
1405 if (WINDOWP (f->tool_bar_window)
1406 && w == XWINDOW (f->tool_bar_window))
1407 y -= width;
1409 BLOCK_INPUT;
1411 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1412 0, y, width, height, 0);
1413 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1414 FRAME_PIXEL_WIDTH (f) - width, y,
1415 width, height, 0);
1417 UNBLOCK_INPUT;
1422 /* Draw the bitmap WHICH in one of the left or right fringes of
1423 window W. ROW is the glyph row for which to display the bitmap; it
1424 determines the vertical position at which the bitmap has to be
1425 drawn. */
1427 static void
1428 x_draw_fringe_bitmap (w, row, p)
1429 struct window *w;
1430 struct glyph_row *row;
1431 struct draw_fringe_bitmap_params *p;
1433 struct frame *f = XFRAME (WINDOW_FRAME (w));
1434 Display *display = FRAME_MAC_DISPLAY (f);
1435 WindowPtr window = FRAME_MAC_WINDOW (f);
1436 XGCValues gcv;
1437 GC gc = f->output_data.mac->normal_gc;
1438 struct face *face = p->face;
1439 int rowY;
1441 /* Must clip because of partially visible lines. */
1442 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1443 if (p->y < rowY)
1445 /* Adjust position of "bottom aligned" bitmap on partially
1446 visible last row. */
1447 int oldY = row->y;
1448 int oldVH = row->visible_height;
1449 row->visible_height = p->h;
1450 row->y -= rowY - p->y;
1451 x_clip_to_row (w, row, -1, gc);
1452 row->y = oldY;
1453 row->visible_height = oldVH;
1455 else
1456 x_clip_to_row (w, row, -1, gc);
1458 if (p->bx >= 0 && !p->overlay_p)
1460 XGCValues gcv;
1461 gcv.foreground = face->background;
1463 #if 0 /* MAC_TODO: stipple */
1464 /* In case the same realized face is used for fringes and
1465 for something displayed in the text (e.g. face `region' on
1466 mono-displays, the fill style may have been changed to
1467 FillSolid in x_draw_glyph_string_background. */
1468 if (face->stipple)
1469 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1470 else
1471 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1472 #endif
1474 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1475 &gcv,
1476 p->bx, p->by, p->nx, p->ny);
1478 #if 0 /* MAC_TODO: stipple */
1479 if (!face->stipple)
1480 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1481 #endif
1484 if (p->which)
1486 unsigned short *bits = p->bits + p->dh;
1488 gcv.foreground = (p->cursor_p
1489 ? (p->overlay_p ? face->background
1490 : f->output_data.mac->cursor_pixel)
1491 : face->foreground);
1492 gcv.background = face->background;
1494 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1495 p->wd, p->h, bits, p->overlay_p);
1498 mac_reset_clipping (display, window);
1502 /* This is called when starting Emacs and when restarting after
1503 suspend. When starting Emacs, no window is mapped. And nothing
1504 must be done to Emacs's own window if it is suspended (though that
1505 rarely happens). */
1507 static void
1508 XTset_terminal_modes ()
1512 /* This is called when exiting or suspending Emacs. Exiting will make
1513 the windows go away, and suspending requires no action. */
1515 static void
1516 XTreset_terminal_modes ()
1521 /***********************************************************************
1522 Display Iterator
1523 ***********************************************************************/
1525 /* Function prototypes of this page. */
1527 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1528 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1531 /* Return a pointer to per-char metric information in FONT of a
1532 character pointed by B which is a pointer to an XChar2b. */
1534 #define PER_CHAR_METRIC(font, b) \
1535 ((font)->per_char \
1536 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1537 + (((font)->min_byte1 || (font)->max_byte1) \
1538 ? (((b)->byte1 - (font)->min_byte1) \
1539 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1540 : 0)) \
1541 : &((font)->max_bounds))
1544 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1545 is not contained in the font. */
1547 static INLINE XCharStruct *
1548 x_per_char_metric (font, char2b)
1549 XFontStruct *font;
1550 XChar2b *char2b;
1552 /* The result metric information. */
1553 XCharStruct *pcm = NULL;
1555 xassert (font && char2b);
1557 if (font->per_char != NULL)
1559 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1561 /* min_char_or_byte2 specifies the linear character index
1562 corresponding to the first element of the per_char array,
1563 max_char_or_byte2 is the index of the last character. A
1564 character with non-zero CHAR2B->byte1 is not in the font.
1565 A character with byte2 less than min_char_or_byte2 or
1566 greater max_char_or_byte2 is not in the font. */
1567 if (char2b->byte1 == 0
1568 && char2b->byte2 >= font->min_char_or_byte2
1569 && char2b->byte2 <= font->max_char_or_byte2)
1570 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1572 else
1574 /* If either min_byte1 or max_byte1 are nonzero, both
1575 min_char_or_byte2 and max_char_or_byte2 are less than
1576 256, and the 2-byte character index values corresponding
1577 to the per_char array element N (counting from 0) are:
1579 byte1 = N/D + min_byte1
1580 byte2 = N\D + min_char_or_byte2
1582 where:
1584 D = max_char_or_byte2 - min_char_or_byte2 + 1
1585 / = integer division
1586 \ = integer modulus */
1587 if (char2b->byte1 >= font->min_byte1
1588 && char2b->byte1 <= font->max_byte1
1589 && char2b->byte2 >= font->min_char_or_byte2
1590 && char2b->byte2 <= font->max_char_or_byte2)
1592 pcm = (font->per_char
1593 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1594 * (char2b->byte1 - font->min_byte1))
1595 + (char2b->byte2 - font->min_char_or_byte2));
1599 else
1601 /* If the per_char pointer is null, all glyphs between the first
1602 and last character indexes inclusive have the same
1603 information, as given by both min_bounds and max_bounds. */
1604 if (char2b->byte2 >= font->min_char_or_byte2
1605 && char2b->byte2 <= font->max_char_or_byte2)
1606 pcm = &font->max_bounds;
1609 return ((pcm == NULL
1610 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1611 ? NULL : pcm);
1614 /* RIF:
1617 static XCharStruct *
1618 mac_per_char_metric (font, char2b, font_type)
1619 XFontStruct *font;
1620 XChar2b *char2b;
1621 int font_type;
1623 return x_per_char_metric (font, char2b);
1626 /* RIF:
1627 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1628 the two-byte form of C. Encoding is returned in *CHAR2B. */
1630 static int
1631 mac_encode_char (c, char2b, font_info, two_byte_p)
1632 int c;
1633 XChar2b *char2b;
1634 struct font_info *font_info;
1635 int *two_byte_p;
1637 int charset = CHAR_CHARSET (c);
1638 XFontStruct *font = font_info->font;
1640 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1641 This may be either a program in a special encoder language or a
1642 fixed encoding. */
1643 if (font_info->font_encoder)
1645 /* It's a program. */
1646 struct ccl_program *ccl = font_info->font_encoder;
1648 if (CHARSET_DIMENSION (charset) == 1)
1650 ccl->reg[0] = charset;
1651 ccl->reg[1] = char2b->byte2;
1653 else
1655 ccl->reg[0] = charset;
1656 ccl->reg[1] = char2b->byte1;
1657 ccl->reg[2] = char2b->byte2;
1660 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1662 /* We assume that MSBs are appropriately set/reset by CCL
1663 program. */
1664 if (font->max_byte1 == 0) /* 1-byte font */
1665 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1666 else
1667 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1669 else if (font_info->encoding[charset])
1671 /* Fixed encoding scheme. See fontset.h for the meaning of the
1672 encoding numbers. */
1673 int enc = font_info->encoding[charset];
1675 if ((enc == 1 || enc == 2)
1676 && CHARSET_DIMENSION (charset) == 2)
1677 char2b->byte1 |= 0x80;
1679 if (enc == 1 || enc == 3)
1680 char2b->byte2 |= 0x80;
1682 if (enc == 4)
1684 int sjis1, sjis2;
1686 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1687 char2b->byte1 = sjis1;
1688 char2b->byte2 = sjis2;
1692 if (two_byte_p)
1693 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1695 return FONT_TYPE_UNKNOWN;
1700 /***********************************************************************
1701 Glyph display
1702 ***********************************************************************/
1705 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1706 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1707 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1708 int));
1709 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1710 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1711 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1712 static void x_draw_glyph_string P_ ((struct glyph_string *));
1713 static void x_set_cursor_gc P_ ((struct glyph_string *));
1714 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1715 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1716 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1717 unsigned long *, double, int));*/
1718 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1719 double, int, unsigned long));
1720 static void x_setup_relief_colors P_ ((struct glyph_string *));
1721 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1722 static void x_draw_image_relief P_ ((struct glyph_string *));
1723 static void x_draw_image_foreground P_ ((struct glyph_string *));
1724 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1725 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1726 int, int, int));
1727 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1728 int, int, int, int, int, int,
1729 Rect *));
1730 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1731 int, int, int, Rect *));
1733 #if GLYPH_DEBUG
1734 static void x_check_font P_ ((struct frame *, XFontStruct *));
1735 #endif
1738 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1739 face. */
1741 static void
1742 x_set_cursor_gc (s)
1743 struct glyph_string *s;
1745 if (s->font == FRAME_FONT (s->f)
1746 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1747 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1748 && !s->cmp)
1749 s->gc = s->f->output_data.mac->cursor_gc;
1750 else
1752 /* Cursor on non-default face: must merge. */
1753 XGCValues xgcv;
1754 unsigned long mask;
1756 xgcv.background = s->f->output_data.mac->cursor_pixel;
1757 xgcv.foreground = s->face->background;
1759 /* If the glyph would be invisible, try a different foreground. */
1760 if (xgcv.foreground == xgcv.background)
1761 xgcv.foreground = s->face->foreground;
1762 if (xgcv.foreground == xgcv.background)
1763 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1764 if (xgcv.foreground == xgcv.background)
1765 xgcv.foreground = s->face->foreground;
1767 /* Make sure the cursor is distinct from text in this face. */
1768 if (xgcv.background == s->face->background
1769 && xgcv.foreground == s->face->foreground)
1771 xgcv.background = s->face->foreground;
1772 xgcv.foreground = s->face->background;
1775 IF_DEBUG (x_check_font (s->f, s->font));
1776 xgcv.font = s->font;
1777 mask = GCForeground | GCBackground | GCFont;
1779 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1780 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1781 mask, &xgcv);
1782 else
1783 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1784 = XCreateGC (s->display, s->window, mask, &xgcv);
1786 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1791 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1793 static void
1794 x_set_mouse_face_gc (s)
1795 struct glyph_string *s;
1797 int face_id;
1798 struct face *face;
1800 /* What face has to be used last for the mouse face? */
1801 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1802 face = FACE_FROM_ID (s->f, face_id);
1803 if (face == NULL)
1804 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1806 if (s->first_glyph->type == CHAR_GLYPH)
1807 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1808 else
1809 face_id = FACE_FOR_CHAR (s->f, face, 0);
1810 s->face = FACE_FROM_ID (s->f, face_id);
1811 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1813 /* If font in this face is same as S->font, use it. */
1814 if (s->font == s->face->font)
1815 s->gc = s->face->gc;
1816 else
1818 /* Otherwise construct scratch_cursor_gc with values from FACE
1819 but font FONT. */
1820 XGCValues xgcv;
1821 unsigned long mask;
1823 xgcv.background = s->face->background;
1824 xgcv.foreground = s->face->foreground;
1825 IF_DEBUG (x_check_font (s->f, s->font));
1826 xgcv.font = s->font;
1827 mask = GCForeground | GCBackground | GCFont;
1829 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1830 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1831 mask, &xgcv);
1832 else
1833 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1834 = XCreateGC (s->display, s->window, mask, &xgcv);
1836 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1839 xassert (s->gc != 0);
1843 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1844 Faces to use in the mode line have already been computed when the
1845 matrix was built, so there isn't much to do, here. */
1847 static INLINE void
1848 x_set_mode_line_face_gc (s)
1849 struct glyph_string *s;
1851 s->gc = s->face->gc;
1855 /* Set S->gc of glyph string S for drawing that glyph string. Set
1856 S->stippled_p to a non-zero value if the face of S has a stipple
1857 pattern. */
1859 static INLINE void
1860 x_set_glyph_string_gc (s)
1861 struct glyph_string *s;
1863 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1865 if (s->hl == DRAW_NORMAL_TEXT)
1867 s->gc = s->face->gc;
1868 s->stippled_p = s->face->stipple != 0;
1870 else if (s->hl == DRAW_INVERSE_VIDEO)
1872 x_set_mode_line_face_gc (s);
1873 s->stippled_p = s->face->stipple != 0;
1875 else if (s->hl == DRAW_CURSOR)
1877 x_set_cursor_gc (s);
1878 s->stippled_p = 0;
1880 else if (s->hl == DRAW_MOUSE_FACE)
1882 x_set_mouse_face_gc (s);
1883 s->stippled_p = s->face->stipple != 0;
1885 else if (s->hl == DRAW_IMAGE_RAISED
1886 || s->hl == DRAW_IMAGE_SUNKEN)
1888 s->gc = s->face->gc;
1889 s->stippled_p = s->face->stipple != 0;
1891 else
1893 s->gc = s->face->gc;
1894 s->stippled_p = s->face->stipple != 0;
1897 /* GC must have been set. */
1898 xassert (s->gc != 0);
1902 /* Set clipping for output of glyph string S. S may be part of a mode
1903 line or menu if we don't have X toolkit support. */
1905 static INLINE void
1906 x_set_glyph_string_clipping (s)
1907 struct glyph_string *s;
1909 Rect r;
1910 get_glyph_string_clip_rect (s, &r);
1911 mac_set_clip_rectangle (s->display, s->window, &r);
1915 /* RIF:
1916 Compute left and right overhang of glyph string S. If S is a glyph
1917 string for a composition, assume overhangs don't exist. */
1919 static void
1920 mac_compute_glyph_string_overhangs (s)
1921 struct glyph_string *s;
1923 #if 0
1924 /* MAC_TODO: XTextExtents16 does nothing yet... */
1926 if (s->cmp == NULL
1927 && s->first_glyph->type == CHAR_GLYPH)
1929 XCharStruct cs;
1930 int direction, font_ascent, font_descent;
1931 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
1932 &font_ascent, &font_descent, &cs);
1933 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
1934 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
1936 #endif
1940 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1942 static INLINE void
1943 x_clear_glyph_string_rect (s, x, y, w, h)
1944 struct glyph_string *s;
1945 int x, y, w, h;
1947 XGCValues xgcv;
1949 xgcv.foreground = s->gc->background;
1950 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
1954 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
1955 on Mac OS X because:
1956 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1957 into an offscreen graphics world first. So performance gain
1958 cannot be expected.)
1959 - It lowers rendering quality.
1960 - Some fonts leave garbage on cursor movement. */
1962 /* Draw the background of glyph_string S. If S->background_filled_p
1963 is non-zero don't draw it. FORCE_P non-zero means draw the
1964 background even if it wouldn't be drawn normally. This is used
1965 when a string preceding S draws into the background of S, or S
1966 contains the first component of a composition. */
1968 static void
1969 x_draw_glyph_string_background (s, force_p)
1970 struct glyph_string *s;
1971 int force_p;
1973 /* Nothing to do if background has already been drawn or if it
1974 shouldn't be drawn in the first place. */
1975 if (!s->background_filled_p)
1977 int box_line_width = max (s->face->box_line_width, 0);
1979 #if 0 /* MAC_TODO: stipple */
1980 if (s->stippled_p)
1982 /* Fill background with a stipple pattern. */
1983 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1984 XFillRectangle (s->display, s->window, s->gc, s->x,
1985 s->y + box_line_width,
1986 s->background_width,
1987 s->height - 2 * box_line_width);
1988 XSetFillStyle (s->display, s->gc, FillSolid);
1989 s->background_filled_p = 1;
1991 else
1992 #endif
1993 #ifdef MAC_OS8
1994 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1995 || s->font_not_found_p
1996 || s->extends_to_end_of_line_p
1997 || force_p)
1998 #endif
2000 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2001 s->background_width,
2002 s->height - 2 * box_line_width);
2003 s->background_filled_p = 1;
2009 /* Draw the foreground of glyph string S. */
2011 static void
2012 x_draw_glyph_string_foreground (s)
2013 struct glyph_string *s;
2015 int i, x;
2017 /* If first glyph of S has a left box line, start drawing the text
2018 of S to the right of that box line. */
2019 if (s->face->box != FACE_NO_BOX
2020 && s->first_glyph->left_box_line_p)
2021 x = s->x + abs (s->face->box_line_width);
2022 else
2023 x = s->x;
2025 /* Draw characters of S as rectangles if S's font could not be
2026 loaded. */
2027 if (s->font_not_found_p)
2029 for (i = 0; i < s->nchars; ++i)
2031 struct glyph *g = s->first_glyph + i;
2032 mac_draw_rectangle (s->display, s->window,
2033 s->gc, x, s->y, g->pixel_width - 1,
2034 s->height - 1);
2035 x += g->pixel_width;
2038 else
2040 char *char1b = (char *) s->char2b;
2041 int boff = s->font_info->baseline_offset;
2043 if (s->font_info->vertical_centering)
2044 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2046 /* If we can use 8-bit functions, condense S->char2b. */
2047 if (!s->two_byte_p)
2048 for (i = 0; i < s->nchars; ++i)
2049 char1b[i] = s->char2b[i].byte2;
2051 #ifdef MAC_OS8
2052 /* Draw text with XDrawString if background has already been
2053 filled. Otherwise, use XDrawImageString. (Note that
2054 XDrawImageString is usually faster than XDrawString.) Always
2055 use XDrawImageString when drawing the cursor so that there is
2056 no chance that characters under a box cursor are invisible. */
2057 if (s->for_overlaps_p
2058 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2059 #endif
2061 /* Draw characters with 16-bit or 8-bit functions. */
2062 if (s->two_byte_p)
2063 XDrawString16 (s->display, s->window, s->gc, x,
2064 s->ybase - boff, s->char2b, s->nchars);
2065 else
2066 XDrawString (s->display, s->window, s->gc, x,
2067 s->ybase - boff, char1b, s->nchars);
2069 #ifdef MAC_OS8
2070 else
2072 if (s->two_byte_p)
2073 XDrawImageString16 (s->display, s->window, s->gc, x,
2074 s->ybase - boff, s->char2b, s->nchars);
2075 else
2076 XDrawImageString (s->display, s->window, s->gc, x,
2077 s->ybase - boff, char1b, s->nchars);
2079 #endif
2083 /* Draw the foreground of composite glyph string S. */
2085 static void
2086 x_draw_composite_glyph_string_foreground (s)
2087 struct glyph_string *s;
2089 int i, x;
2091 /* If first glyph of S has a left box line, start drawing the text
2092 of S to the right of that box line. */
2093 if (s->face->box != FACE_NO_BOX
2094 && s->first_glyph->left_box_line_p)
2095 x = s->x + abs (s->face->box_line_width);
2096 else
2097 x = s->x;
2099 /* S is a glyph string for a composition. S->gidx is the index of
2100 the first character drawn for glyphs of this composition.
2101 S->gidx == 0 means we are drawing the very first character of
2102 this composition. */
2104 /* Draw a rectangle for the composition if the font for the very
2105 first character of the composition could not be loaded. */
2106 if (s->font_not_found_p)
2108 if (s->gidx == 0)
2109 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2110 s->width - 1, s->height - 1);
2112 else
2114 for (i = 0; i < s->nchars; i++, ++s->gidx)
2115 XDrawString16 (s->display, s->window, s->gc,
2116 x + s->cmp->offsets[s->gidx * 2],
2117 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2118 s->char2b + i, 1);
2123 #ifdef USE_X_TOOLKIT
2125 static struct frame *x_frame_of_widget P_ ((Widget));
2128 /* Return the frame on which widget WIDGET is used.. Abort if frame
2129 cannot be determined. */
2131 static struct frame *
2132 x_frame_of_widget (widget)
2133 Widget widget;
2135 struct x_display_info *dpyinfo;
2136 Lisp_Object tail;
2137 struct frame *f;
2139 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2141 /* Find the top-level shell of the widget. Note that this function
2142 can be called when the widget is not yet realized, so XtWindow
2143 (widget) == 0. That's the reason we can't simply use
2144 x_any_window_to_frame. */
2145 while (!XtIsTopLevelShell (widget))
2146 widget = XtParent (widget);
2148 /* Look for a frame with that top-level widget. Allocate the color
2149 on that frame to get the right gamma correction value. */
2150 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2151 if (GC_FRAMEP (XCAR (tail))
2152 && (f = XFRAME (XCAR (tail)),
2153 (f->output_data.nothing != 1
2154 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2155 && f->output_data.x->widget == widget)
2156 return f;
2158 abort ();
2162 /* Allocate the color COLOR->pixel on the screen and display of
2163 widget WIDGET in colormap CMAP. If an exact match cannot be
2164 allocated, try the nearest color available. Value is non-zero
2165 if successful. This is called from lwlib. */
2168 x_alloc_nearest_color_for_widget (widget, cmap, color)
2169 Widget widget;
2170 Colormap cmap;
2171 XColor *color;
2173 struct frame *f = x_frame_of_widget (widget);
2174 return x_alloc_nearest_color (f, cmap, color);
2178 #endif /* USE_X_TOOLKIT */
2180 #if 0 /* MAC_TODO */
2182 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2183 CMAP. If an exact match can't be allocated, try the nearest color
2184 available. Value is non-zero if successful. Set *COLOR to the
2185 color allocated. */
2188 x_alloc_nearest_color (f, cmap, color)
2189 struct frame *f;
2190 Colormap cmap;
2191 XColor *color;
2193 Display *display = FRAME_X_DISPLAY (f);
2194 Screen *screen = FRAME_X_SCREEN (f);
2195 int rc;
2197 gamma_correct (f, color);
2198 rc = XAllocColor (display, cmap, color);
2199 if (rc == 0)
2201 /* If we got to this point, the colormap is full, so we're going
2202 to try to get the next closest color. The algorithm used is
2203 a least-squares matching, which is what X uses for closest
2204 color matching with StaticColor visuals. */
2205 int nearest, i;
2206 unsigned long nearest_delta = ~0;
2207 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2208 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2210 for (i = 0; i < ncells; ++i)
2211 cells[i].pixel = i;
2212 XQueryColors (display, cmap, cells, ncells);
2214 for (nearest = i = 0; i < ncells; ++i)
2216 long dred = (color->red >> 8) - (cells[i].red >> 8);
2217 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2218 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2219 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2221 if (delta < nearest_delta)
2223 nearest = i;
2224 nearest_delta = delta;
2228 color->red = cells[nearest].red;
2229 color->green = cells[nearest].green;
2230 color->blue = cells[nearest].blue;
2231 rc = XAllocColor (display, cmap, color);
2234 #ifdef DEBUG_X_COLORS
2235 if (rc)
2236 register_color (color->pixel);
2237 #endif /* DEBUG_X_COLORS */
2239 return rc;
2243 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2244 It's necessary to do this instead of just using PIXEL directly to
2245 get color reference counts right. */
2247 unsigned long
2248 x_copy_color (f, pixel)
2249 struct frame *f;
2250 unsigned long pixel;
2252 XColor color;
2254 color.pixel = pixel;
2255 BLOCK_INPUT;
2256 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2257 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2258 UNBLOCK_INPUT;
2259 #ifdef DEBUG_X_COLORS
2260 register_color (pixel);
2261 #endif
2262 return color.pixel;
2266 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2267 It's necessary to do this instead of just using PIXEL directly to
2268 get color reference counts right. */
2270 unsigned long
2271 x_copy_dpy_color (dpy, cmap, pixel)
2272 Display *dpy;
2273 Colormap cmap;
2274 unsigned long pixel;
2276 XColor color;
2278 color.pixel = pixel;
2279 BLOCK_INPUT;
2280 XQueryColor (dpy, cmap, &color);
2281 XAllocColor (dpy, cmap, &color);
2282 UNBLOCK_INPUT;
2283 #ifdef DEBUG_X_COLORS
2284 register_color (pixel);
2285 #endif
2286 return color.pixel;
2289 #endif /* MAC_TODO */
2292 /* Brightness beyond which a color won't have its highlight brightness
2293 boosted.
2295 Nominally, highlight colors for `3d' faces are calculated by
2296 brightening an object's color by a constant scale factor, but this
2297 doesn't yield good results for dark colors, so for colors who's
2298 brightness is less than this value (on a scale of 0-255) have to
2299 use an additional additive factor.
2301 The value here is set so that the default menu-bar/mode-line color
2302 (grey75) will not have its highlights changed at all. */
2303 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2306 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2307 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2308 If this produces the same color as COLOR, try a color where all RGB
2309 values have DELTA added. Return the allocated color in *COLOR.
2310 DISPLAY is the X display, CMAP is the colormap to operate on.
2311 Value is non-zero if successful. */
2313 static int
2314 mac_alloc_lighter_color (f, color, factor, delta)
2315 struct frame *f;
2316 unsigned long *color;
2317 double factor;
2318 int delta;
2320 unsigned long new;
2321 long bright;
2323 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2324 delta /= 256;
2326 /* Change RGB values by specified FACTOR. Avoid overflow! */
2327 xassert (factor >= 0);
2328 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2329 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2330 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2332 /* Calculate brightness of COLOR. */
2333 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2334 + BLUE_FROM_ULONG (*color)) / 6;
2336 /* We only boost colors that are darker than
2337 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2338 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2339 /* Make an additive adjustment to NEW, because it's dark enough so
2340 that scaling by FACTOR alone isn't enough. */
2342 /* How far below the limit this color is (0 - 1, 1 being darker). */
2343 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2344 /* The additive adjustment. */
2345 int min_delta = delta * dimness * factor / 2;
2347 if (factor < 1)
2348 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2349 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2350 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2351 else
2352 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2353 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2354 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2357 if (new == *color)
2358 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2359 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2360 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2362 /* MAC_TODO: Map to palette and retry with delta if same? */
2363 /* MAC_TODO: Free colors (if using palette)? */
2365 if (new == *color)
2366 return 0;
2368 *color = new;
2370 return 1;
2374 /* Set up the foreground color for drawing relief lines of glyph
2375 string S. RELIEF is a pointer to a struct relief containing the GC
2376 with which lines will be drawn. Use a color that is FACTOR or
2377 DELTA lighter or darker than the relief's background which is found
2378 in S->f->output_data.x->relief_background. If such a color cannot
2379 be allocated, use DEFAULT_PIXEL, instead. */
2381 static void
2382 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2383 struct frame *f;
2384 struct relief *relief;
2385 double factor;
2386 int delta;
2387 unsigned long default_pixel;
2389 XGCValues xgcv;
2390 struct mac_output *di = f->output_data.mac;
2391 unsigned long mask = GCForeground;
2392 unsigned long pixel;
2393 unsigned long background = di->relief_background;
2394 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2396 /* MAC_TODO: Free colors (if using palette)? */
2398 /* Allocate new color. */
2399 xgcv.foreground = default_pixel;
2400 pixel = background;
2401 if (dpyinfo->n_planes != 1
2402 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2404 relief->allocated_p = 1;
2405 xgcv.foreground = relief->pixel = pixel;
2408 if (relief->gc == 0)
2410 #if 0 /* MAC_TODO: stipple */
2411 xgcv.stipple = dpyinfo->gray;
2412 mask |= GCStipple;
2413 #endif
2414 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2416 else
2417 XChangeGC (NULL, relief->gc, mask, &xgcv);
2421 /* Set up colors for the relief lines around glyph string S. */
2423 static void
2424 x_setup_relief_colors (s)
2425 struct glyph_string *s;
2427 struct mac_output *di = s->f->output_data.mac;
2428 unsigned long color;
2430 if (s->face->use_box_color_for_shadows_p)
2431 color = s->face->box_color;
2432 else if (s->first_glyph->type == IMAGE_GLYPH
2433 && s->img->pixmap
2434 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2435 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2436 else
2438 XGCValues xgcv;
2440 /* Get the background color of the face. */
2441 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2442 color = xgcv.background;
2445 if (di->white_relief.gc == 0
2446 || color != di->relief_background)
2448 di->relief_background = color;
2449 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2450 WHITE_PIX_DEFAULT (s->f));
2451 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2452 BLACK_PIX_DEFAULT (s->f));
2457 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2458 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2459 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2460 relief. LEFT_P non-zero means draw a relief on the left side of
2461 the rectangle. RIGHT_P non-zero means draw a relief on the right
2462 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2463 when drawing. */
2465 static void
2466 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2467 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2468 struct frame *f;
2469 int left_x, top_y, right_x, bottom_y, width;
2470 int top_p, bot_p, left_p, right_p, raised_p;
2471 Rect *clip_rect;
2473 Display *dpy = FRAME_MAC_DISPLAY (f);
2474 Window window = FRAME_MAC_WINDOW (f);
2475 int i;
2476 GC gc;
2478 if (raised_p)
2479 gc = f->output_data.mac->white_relief.gc;
2480 else
2481 gc = f->output_data.mac->black_relief.gc;
2482 mac_set_clip_rectangle (dpy, window, clip_rect);
2484 /* Top. */
2485 if (top_p)
2486 for (i = 0; i < width; ++i)
2487 XDrawLine (dpy, window, gc,
2488 left_x + i * left_p, top_y + i,
2489 right_x - i * right_p, top_y + i);
2491 /* Left. */
2492 if (left_p)
2493 for (i = 0; i < width; ++i)
2494 XDrawLine (dpy, window, gc,
2495 left_x + i, top_y + i, left_x + i, bottom_y - i);
2497 mac_reset_clipping (dpy, window);
2498 if (raised_p)
2499 gc = f->output_data.mac->black_relief.gc;
2500 else
2501 gc = f->output_data.mac->white_relief.gc;
2502 mac_set_clip_rectangle (dpy, window,
2503 clip_rect);
2505 /* Bottom. */
2506 if (bot_p)
2507 for (i = 0; i < width; ++i)
2508 XDrawLine (dpy, window, gc,
2509 left_x + i * left_p, bottom_y - i,
2510 right_x - i * right_p, bottom_y - i);
2512 /* Right. */
2513 if (right_p)
2514 for (i = 0; i < width; ++i)
2515 XDrawLine (dpy, window, gc,
2516 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2518 mac_reset_clipping (dpy, window);
2522 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2523 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2524 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2525 left side of the rectangle. RIGHT_P non-zero means draw a line
2526 on the right side of the rectangle. CLIP_RECT is the clipping
2527 rectangle to use when drawing. */
2529 static void
2530 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2531 left_p, right_p, clip_rect)
2532 struct glyph_string *s;
2533 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2534 Rect *clip_rect;
2536 XGCValues xgcv;
2538 xgcv.foreground = s->face->box_color;
2539 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2541 /* Top. */
2542 XFillRectangle (s->display, s->window, &xgcv,
2543 left_x, top_y, right_x - left_x + 1, width);
2545 /* Left. */
2546 if (left_p)
2547 XFillRectangle (s->display, s->window, &xgcv,
2548 left_x, top_y, width, bottom_y - top_y + 1);
2550 /* Bottom. */
2551 XFillRectangle (s->display, s->window, &xgcv,
2552 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2554 /* Right. */
2555 if (right_p)
2556 XFillRectangle (s->display, s->window, &xgcv,
2557 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2559 mac_reset_clipping (s->display, s->window);
2563 /* Draw a box around glyph string S. */
2565 static void
2566 x_draw_glyph_string_box (s)
2567 struct glyph_string *s;
2569 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2570 int left_p, right_p;
2571 struct glyph *last_glyph;
2572 Rect clip_rect;
2574 last_x = window_box_right (s->w, s->area);
2575 if (s->row->full_width_p
2576 && !s->w->pseudo_window_p)
2578 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2579 if (s->area != RIGHT_MARGIN_AREA
2580 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2581 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2584 /* The glyph that may have a right box line. */
2585 last_glyph = (s->cmp || s->img
2586 ? s->first_glyph
2587 : s->first_glyph + s->nchars - 1);
2589 width = abs (s->face->box_line_width);
2590 raised_p = s->face->box == FACE_RAISED_BOX;
2591 left_x = s->x;
2592 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2593 ? last_x - 1
2594 : min (last_x, s->x + s->background_width) - 1);
2595 top_y = s->y;
2596 bottom_y = top_y + s->height - 1;
2598 left_p = (s->first_glyph->left_box_line_p
2599 || (s->hl == DRAW_MOUSE_FACE
2600 && (s->prev == NULL
2601 || s->prev->hl != s->hl)));
2602 right_p = (last_glyph->right_box_line_p
2603 || (s->hl == DRAW_MOUSE_FACE
2604 && (s->next == NULL
2605 || s->next->hl != s->hl)));
2607 get_glyph_string_clip_rect (s, &clip_rect);
2609 if (s->face->box == FACE_SIMPLE_BOX)
2610 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2611 left_p, right_p, &clip_rect);
2612 else
2614 x_setup_relief_colors (s);
2615 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2616 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2621 /* Draw foreground of image glyph string S. */
2623 static void
2624 x_draw_image_foreground (s)
2625 struct glyph_string *s;
2627 int x = s->x;
2628 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2630 /* If first glyph of S has a left box line, start drawing it to the
2631 right of that line. */
2632 if (s->face->box != FACE_NO_BOX
2633 && s->first_glyph->left_box_line_p
2634 && s->slice.x == 0)
2635 x += abs (s->face->box_line_width);
2637 /* If there is a margin around the image, adjust x- and y-position
2638 by that margin. */
2639 if (s->slice.x == 0)
2640 x += s->img->hmargin;
2641 if (s->slice.y == 0)
2642 y += s->img->vmargin;
2644 if (s->img->pixmap)
2646 x_set_glyph_string_clipping (s);
2648 if (s->img->mask)
2649 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2650 s->window, s->gc, s->slice.x, s->slice.y,
2651 s->slice.width, s->slice.height, x, y);
2652 else
2654 mac_copy_area (s->display, s->img->pixmap,
2655 s->window, s->gc, s->slice.x, s->slice.y,
2656 s->slice.width, s->slice.height, x, y);
2658 /* When the image has a mask, we can expect that at
2659 least part of a mouse highlight or a block cursor will
2660 be visible. If the image doesn't have a mask, make
2661 a block cursor visible by drawing a rectangle around
2662 the image. I believe it's looking better if we do
2663 nothing here for mouse-face. */
2664 if (s->hl == DRAW_CURSOR)
2666 int r = s->img->relief;
2667 if (r < 0) r = -r;
2668 mac_draw_rectangle (s->display, s->window, s->gc,
2669 x - r, y - r,
2670 s->slice.width + r*2 - 1,
2671 s->slice.height + r*2 - 1);
2675 else
2676 /* Draw a rectangle if image could not be loaded. */
2677 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2678 s->slice.width - 1, s->slice.height - 1);
2682 /* Draw a relief around the image glyph string S. */
2684 static void
2685 x_draw_image_relief (s)
2686 struct glyph_string *s;
2688 int x0, y0, x1, y1, thick, raised_p;
2689 Rect r;
2690 int x = s->x;
2691 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2693 /* If first glyph of S has a left box line, start drawing it to the
2694 right of that line. */
2695 if (s->face->box != FACE_NO_BOX
2696 && s->first_glyph->left_box_line_p
2697 && s->slice.x == 0)
2698 x += abs (s->face->box_line_width);
2700 /* If there is a margin around the image, adjust x- and y-position
2701 by that margin. */
2702 if (s->slice.x == 0)
2703 x += s->img->hmargin;
2704 if (s->slice.y == 0)
2705 y += s->img->vmargin;
2707 if (s->hl == DRAW_IMAGE_SUNKEN
2708 || s->hl == DRAW_IMAGE_RAISED)
2710 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2711 raised_p = s->hl == DRAW_IMAGE_RAISED;
2713 else
2715 thick = abs (s->img->relief);
2716 raised_p = s->img->relief > 0;
2719 x0 = x - thick;
2720 y0 = y - thick;
2721 x1 = x + s->slice.width + thick - 1;
2722 y1 = y + s->slice.height + thick - 1;
2724 x_setup_relief_colors (s);
2725 get_glyph_string_clip_rect (s, &r);
2726 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2727 s->slice.y == 0,
2728 s->slice.y + s->slice.height == s->img->height,
2729 s->slice.x == 0,
2730 s->slice.x + s->slice.width == s->img->width,
2731 &r);
2735 #if 0 /* TODO: figure out if we need to do this on Mac. */
2736 /* Draw the foreground of image glyph string S to PIXMAP. */
2738 static void
2739 x_draw_image_foreground_1 (s, pixmap)
2740 struct glyph_string *s;
2741 Pixmap pixmap;
2743 int x = 0;
2744 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2746 /* If first glyph of S has a left box line, start drawing it to the
2747 right of that line. */
2748 if (s->face->box != FACE_NO_BOX
2749 && s->first_glyph->left_box_line_p
2750 && s->slice.x == 0)
2751 x += abs (s->face->box_line_width);
2753 /* If there is a margin around the image, adjust x- and y-position
2754 by that margin. */
2755 if (s->slice.x == 0)
2756 x += s->img->hmargin;
2757 if (s->slice.y == 0)
2758 y += s->img->vmargin;
2760 if (s->img->pixmap)
2762 if (s->img->mask)
2763 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2764 s->img->mask, pixmap, s->gc,
2765 s->slice.x, s->slice.y,
2766 s->slice.width, s->slice.height,
2767 x, y);
2768 else
2770 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2771 s->slice.x, s->slice.y,
2772 s->slice.width, s->slice.height,
2773 x, y);
2775 /* When the image has a mask, we can expect that at
2776 least part of a mouse highlight or a block cursor will
2777 be visible. If the image doesn't have a mask, make
2778 a block cursor visible by drawing a rectangle around
2779 the image. I believe it's looking better if we do
2780 nothing here for mouse-face. */
2781 if (s->hl == DRAW_CURSOR)
2783 int r = s->img->relief;
2784 if (r < 0) r = -r;
2785 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2786 s->slice.width + r*2 - 1,
2787 s->slice.height + r*2 - 1);
2791 else
2792 /* Draw a rectangle if image could not be loaded. */
2793 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2794 s->slice.width - 1, s->slice.height - 1);
2796 #endif
2799 /* Draw part of the background of glyph string S. X, Y, W, and H
2800 give the rectangle to draw. */
2802 static void
2803 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2804 struct glyph_string *s;
2805 int x, y, w, h;
2807 #if 0 /* MAC_TODO: stipple */
2808 if (s->stippled_p)
2810 /* Fill background with a stipple pattern. */
2811 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2812 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2813 XSetFillStyle (s->display, s->gc, FillSolid);
2815 else
2816 #endif /* MAC_TODO */
2817 x_clear_glyph_string_rect (s, x, y, w, h);
2821 /* Draw image glyph string S.
2823 s->y
2824 s->x +-------------------------
2825 | s->face->box
2827 | +-------------------------
2828 | | s->img->margin
2830 | | +-------------------
2831 | | | the image
2835 static void
2836 x_draw_image_glyph_string (s)
2837 struct glyph_string *s;
2839 int x, y;
2840 int box_line_hwidth = abs (s->face->box_line_width);
2841 int box_line_vwidth = max (s->face->box_line_width, 0);
2842 int height;
2843 Pixmap pixmap = 0;
2845 height = s->height - 2 * box_line_vwidth;
2848 /* Fill background with face under the image. Do it only if row is
2849 taller than image or if image has a clip mask to reduce
2850 flickering. */
2851 s->stippled_p = s->face->stipple != 0;
2852 if (height > s->slice.height
2853 || s->img->hmargin
2854 || s->img->vmargin
2855 || s->img->mask
2856 || s->img->pixmap == 0
2857 || s->width != s->background_width)
2859 x = s->x;
2860 if (s->first_glyph->left_box_line_p
2861 && s->slice.x == 0)
2862 x += box_line_hwidth;
2864 y = s->y;
2865 if (s->slice.y == 0)
2866 y += box_line_vwidth;
2868 #if 0 /* TODO: figure out if we need to do this on Mac. */
2869 if (s->img->mask)
2871 /* Create a pixmap as large as the glyph string. Fill it
2872 with the background color. Copy the image to it, using
2873 its mask. Copy the temporary pixmap to the display. */
2874 int depth = one_mac_display_info.n_planes;
2876 /* Create a pixmap as large as the glyph string. */
2877 pixmap = XCreatePixmap (s->display, s->window,
2878 s->background_width,
2879 s->height, depth);
2881 /* Fill the pixmap with the background color/stipple. */
2882 #if 0 /* TODO: stipple */
2883 if (s->stippled_p)
2885 /* Fill background with a stipple pattern. */
2886 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2887 XFillRectangle (s->display, pixmap, s->gc,
2888 0, 0, s->background_width, s->height);
2889 XSetFillStyle (s->display, s->gc, FillSolid);
2891 else
2892 #endif
2894 XGCValues xgcv;
2895 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2896 &xgcv);
2897 XSetForeground (s->display, s->gc, xgcv.background);
2898 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2899 0, 0, s->background_width,
2900 s->height);
2901 XSetForeground (s->display, s->gc, xgcv.foreground);
2904 else
2905 #endif
2906 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2908 s->background_filled_p = 1;
2911 /* Draw the foreground. */
2912 #if 0 /* TODO: figure out if we need to do this on Mac. */
2913 if (pixmap != 0)
2915 x_draw_image_foreground_1 (s, pixmap);
2916 x_set_glyph_string_clipping (s);
2917 mac_copy_area (s->display, pixmap, s->window, s->gc,
2918 0, 0, s->background_width, s->height, s->x, s->y);
2919 mac_reset_clipping (s->display, s->window);
2920 XFreePixmap (s->display, pixmap);
2922 else
2923 #endif
2924 x_draw_image_foreground (s);
2926 /* If we must draw a relief around the image, do it. */
2927 if (s->img->relief
2928 || s->hl == DRAW_IMAGE_RAISED
2929 || s->hl == DRAW_IMAGE_SUNKEN)
2930 x_draw_image_relief (s);
2934 /* Draw stretch glyph string S. */
2936 static void
2937 x_draw_stretch_glyph_string (s)
2938 struct glyph_string *s;
2940 xassert (s->first_glyph->type == STRETCH_GLYPH);
2941 s->stippled_p = s->face->stipple != 0;
2943 if (s->hl == DRAW_CURSOR
2944 && !x_stretch_cursor_p)
2946 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2947 as wide as the stretch glyph. */
2948 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2950 /* Draw cursor. */
2951 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2953 /* Clear rest using the GC of the original non-cursor face. */
2954 if (width < s->background_width)
2956 int x = s->x + width, y = s->y;
2957 int w = s->background_width - width, h = s->height;
2958 Rect r;
2959 GC gc;
2961 if (s->row->mouse_face_p
2962 && cursor_in_mouse_face_p (s->w))
2964 x_set_mouse_face_gc (s);
2965 gc = s->gc;
2967 else
2968 gc = s->face->gc;
2970 get_glyph_string_clip_rect (s, &r);
2971 mac_set_clip_rectangle (s->display, s->window, &r);
2973 #if 0 /* MAC_TODO: stipple */
2974 if (s->face->stipple)
2976 /* Fill background with a stipple pattern. */
2977 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2978 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2979 XSetFillStyle (s->display, gc, FillSolid);
2981 else
2982 #endif /* MAC_TODO */
2984 XGCValues xgcv;
2985 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2986 XSetForeground (s->display, gc, xgcv.background);
2987 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2988 XSetForeground (s->display, gc, xgcv.foreground);
2991 mac_reset_clipping (s->display, s->window);
2994 else if (!s->background_filled_p)
2995 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2996 s->height);
2998 s->background_filled_p = 1;
3002 /* Draw glyph string S. */
3004 static void
3005 x_draw_glyph_string (s)
3006 struct glyph_string *s;
3008 int relief_drawn_p = 0;
3010 /* If S draws into the background of its successor, draw the
3011 background of the successor first so that S can draw into it.
3012 This makes S->next use XDrawString instead of XDrawImageString. */
3013 if (s->next && s->right_overhang && !s->for_overlaps_p)
3015 xassert (s->next->img == NULL);
3016 x_set_glyph_string_gc (s->next);
3017 x_set_glyph_string_clipping (s->next);
3018 x_draw_glyph_string_background (s->next, 1);
3021 /* Set up S->gc, set clipping and draw S. */
3022 x_set_glyph_string_gc (s);
3024 /* Draw relief (if any) in advance for char/composition so that the
3025 glyph string can be drawn over it. */
3026 if (!s->for_overlaps_p
3027 && s->face->box != FACE_NO_BOX
3028 && (s->first_glyph->type == CHAR_GLYPH
3029 || s->first_glyph->type == COMPOSITE_GLYPH))
3032 x_set_glyph_string_clipping (s);
3033 x_draw_glyph_string_background (s, 1);
3034 x_draw_glyph_string_box (s);
3035 x_set_glyph_string_clipping (s);
3036 relief_drawn_p = 1;
3038 else
3039 x_set_glyph_string_clipping (s);
3041 switch (s->first_glyph->type)
3043 case IMAGE_GLYPH:
3044 x_draw_image_glyph_string (s);
3045 break;
3047 case STRETCH_GLYPH:
3048 x_draw_stretch_glyph_string (s);
3049 break;
3051 case CHAR_GLYPH:
3052 if (s->for_overlaps_p)
3053 s->background_filled_p = 1;
3054 else
3055 x_draw_glyph_string_background (s, 0);
3056 x_draw_glyph_string_foreground (s);
3057 break;
3059 case COMPOSITE_GLYPH:
3060 if (s->for_overlaps_p || s->gidx > 0)
3061 s->background_filled_p = 1;
3062 else
3063 x_draw_glyph_string_background (s, 1);
3064 x_draw_composite_glyph_string_foreground (s);
3065 break;
3067 default:
3068 abort ();
3071 if (!s->for_overlaps_p)
3073 /* Draw underline. */
3074 if (s->face->underline_p)
3076 unsigned long h = 1;
3077 unsigned long dy = s->height - h;
3079 if (s->face->underline_defaulted_p)
3080 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3081 s->width, h);
3082 else
3084 XGCValues xgcv;
3085 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3086 XSetForeground (s->display, s->gc, s->face->underline_color);
3087 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3088 s->width, h);
3089 XSetForeground (s->display, s->gc, xgcv.foreground);
3093 /* Draw overline. */
3094 if (s->face->overline_p)
3096 unsigned long dy = 0, h = 1;
3098 if (s->face->overline_color_defaulted_p)
3099 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3100 s->width, h);
3101 else
3103 XGCValues xgcv;
3104 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3105 XSetForeground (s->display, s->gc, s->face->overline_color);
3106 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3107 s->width, h);
3108 XSetForeground (s->display, s->gc, xgcv.foreground);
3112 /* Draw strike-through. */
3113 if (s->face->strike_through_p)
3115 unsigned long h = 1;
3116 unsigned long dy = (s->height - h) / 2;
3118 if (s->face->strike_through_color_defaulted_p)
3119 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3120 s->width, h);
3121 else
3123 XGCValues xgcv;
3124 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3125 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3126 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3127 s->width, h);
3128 XSetForeground (s->display, s->gc, xgcv.foreground);
3132 /* Draw relief if not yet drawn. */
3133 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3134 x_draw_glyph_string_box (s);
3137 /* Reset clipping. */
3138 mac_reset_clipping (s->display, s->window);
3141 /* Shift display to make room for inserted glyphs. */
3143 void
3144 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3145 struct frame *f;
3146 int x, y, width, height, shift_by;
3148 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3149 f->output_data.mac->normal_gc,
3150 x, y, width, height,
3151 x + shift_by, y);
3154 /* Delete N glyphs at the nominal cursor position. Not implemented
3155 for X frames. */
3157 static void
3158 x_delete_glyphs (n)
3159 register int n;
3161 abort ();
3165 /* Clear entire frame. If updating_frame is non-null, clear that
3166 frame. Otherwise clear the selected frame. */
3168 static void
3169 x_clear_frame ()
3171 struct frame *f;
3173 if (updating_frame)
3174 f = updating_frame;
3175 else
3176 f = SELECTED_FRAME ();
3178 /* Clearing the frame will erase any cursor, so mark them all as no
3179 longer visible. */
3180 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3181 output_cursor.hpos = output_cursor.vpos = 0;
3182 output_cursor.x = -1;
3184 /* We don't set the output cursor here because there will always
3185 follow an explicit cursor_to. */
3186 BLOCK_INPUT;
3187 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3189 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3190 /* We have to clear the scroll bars, too. If we have changed
3191 colors or something like that, then they should be notified. */
3192 x_scroll_bar_clear (f);
3193 #endif
3195 XFlush (FRAME_MAC_DISPLAY (f));
3196 UNBLOCK_INPUT;
3201 /* Invert the middle quarter of the frame for .15 sec. */
3203 /* We use the select system call to do the waiting, so we have to make
3204 sure it's available. If it isn't, we just won't do visual bells. */
3206 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3209 /* Subtract the `struct timeval' values X and Y, storing the result in
3210 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3212 static int
3213 timeval_subtract (result, x, y)
3214 struct timeval *result, x, y;
3216 /* Perform the carry for the later subtraction by updating y. This
3217 is safer because on some systems the tv_sec member is unsigned. */
3218 if (x.tv_usec < y.tv_usec)
3220 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3221 y.tv_usec -= 1000000 * nsec;
3222 y.tv_sec += nsec;
3225 if (x.tv_usec - y.tv_usec > 1000000)
3227 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3228 y.tv_usec += 1000000 * nsec;
3229 y.tv_sec -= nsec;
3232 /* Compute the time remaining to wait. tv_usec is certainly
3233 positive. */
3234 result->tv_sec = x.tv_sec - y.tv_sec;
3235 result->tv_usec = x.tv_usec - y.tv_usec;
3237 /* Return indication of whether the result should be considered
3238 negative. */
3239 return x.tv_sec < y.tv_sec;
3242 void
3243 XTflash (f)
3244 struct frame *f;
3246 BLOCK_INPUT;
3248 FlashMenuBar (0);
3251 struct timeval wakeup;
3253 EMACS_GET_TIME (wakeup);
3255 /* Compute time to wait until, propagating carry from usecs. */
3256 wakeup.tv_usec += 150000;
3257 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3258 wakeup.tv_usec %= 1000000;
3260 /* Keep waiting until past the time wakeup. */
3261 while (1)
3263 struct timeval timeout;
3265 EMACS_GET_TIME (timeout);
3267 /* In effect, timeout = wakeup - timeout.
3268 Break if result would be negative. */
3269 if (timeval_subtract (&timeout, wakeup, timeout))
3270 break;
3272 /* Try to wait that long--but we might wake up sooner. */
3273 select (0, NULL, NULL, NULL, &timeout);
3277 FlashMenuBar (0);
3279 UNBLOCK_INPUT;
3282 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3285 /* Make audible bell. */
3287 void
3288 XTring_bell ()
3290 struct frame *f = SELECTED_FRAME ();
3292 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3293 if (visible_bell)
3294 XTflash (f);
3295 else
3296 #endif
3298 BLOCK_INPUT;
3299 SysBeep (1);
3300 XFlush (FRAME_MAC_DISPLAY (f));
3301 UNBLOCK_INPUT;
3307 /* Specify how many text lines, from the top of the window,
3308 should be affected by insert-lines and delete-lines operations.
3309 This, and those operations, are used only within an update
3310 that is bounded by calls to x_update_begin and x_update_end. */
3312 static void
3313 XTset_terminal_window (n)
3314 register int n;
3316 /* This function intentionally left blank. */
3321 /***********************************************************************
3322 Line Dance
3323 ***********************************************************************/
3325 /* Perform an insert-lines or delete-lines operation, inserting N
3326 lines or deleting -N lines at vertical position VPOS. */
3328 static void
3329 x_ins_del_lines (vpos, n)
3330 int vpos, n;
3332 abort ();
3336 /* Scroll part of the display as described by RUN. */
3338 static void
3339 x_scroll_run (w, run)
3340 struct window *w;
3341 struct run *run;
3343 struct frame *f = XFRAME (w->frame);
3344 int x, y, width, height, from_y, to_y, bottom_y;
3346 /* Get frame-relative bounding box of the text display area of W,
3347 without mode lines. Include in this box the left and right
3348 fringe of W. */
3349 window_box (w, -1, &x, &y, &width, &height);
3351 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3352 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3353 bottom_y = y + height;
3355 if (to_y < from_y)
3357 /* Scrolling up. Make sure we don't copy part of the mode
3358 line at the bottom. */
3359 if (from_y + run->height > bottom_y)
3360 height = bottom_y - from_y;
3361 else
3362 height = run->height;
3364 else
3366 /* Scolling down. Make sure we don't copy over the mode line.
3367 at the bottom. */
3368 if (to_y + run->height > bottom_y)
3369 height = bottom_y - to_y;
3370 else
3371 height = run->height;
3374 BLOCK_INPUT;
3376 /* Cursor off. Will be switched on again in x_update_window_end. */
3377 updated_window = w;
3378 x_clear_cursor (w);
3380 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3381 f->output_data.mac->normal_gc,
3382 x, from_y,
3383 width, height,
3384 x, to_y);
3386 UNBLOCK_INPUT;
3391 /***********************************************************************
3392 Exposure Events
3393 ***********************************************************************/
3396 static void
3397 frame_highlight (f)
3398 struct frame *f;
3400 x_update_cursor (f, 1);
3403 static void
3404 frame_unhighlight (f)
3405 struct frame *f;
3407 x_update_cursor (f, 1);
3410 /* The focus has changed. Update the frames as necessary to reflect
3411 the new situation. Note that we can't change the selected frame
3412 here, because the Lisp code we are interrupting might become confused.
3413 Each event gets marked with the frame in which it occurred, so the
3414 Lisp code can tell when the switch took place by examining the events. */
3416 static void
3417 x_new_focus_frame (dpyinfo, frame)
3418 struct x_display_info *dpyinfo;
3419 struct frame *frame;
3421 struct frame *old_focus = dpyinfo->x_focus_frame;
3423 if (frame != dpyinfo->x_focus_frame)
3425 /* Set this before calling other routines, so that they see
3426 the correct value of x_focus_frame. */
3427 dpyinfo->x_focus_frame = frame;
3429 if (old_focus && old_focus->auto_lower)
3430 x_lower_frame (old_focus);
3432 #if 0
3433 selected_frame = frame;
3434 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3435 selected_frame);
3436 Fselect_window (selected_frame->selected_window, Qnil);
3437 choose_minibuf_frame ();
3438 #endif /* ! 0 */
3440 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3441 pending_autoraise_frame = dpyinfo->x_focus_frame;
3442 else
3443 pending_autoraise_frame = 0;
3446 x_frame_rehighlight (dpyinfo);
3449 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3451 void
3452 x_mouse_leave (dpyinfo)
3453 struct x_display_info *dpyinfo;
3455 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3458 /* The focus has changed, or we have redirected a frame's focus to
3459 another frame (this happens when a frame uses a surrogate
3460 mini-buffer frame). Shift the highlight as appropriate.
3462 The FRAME argument doesn't necessarily have anything to do with which
3463 frame is being highlighted or un-highlighted; we only use it to find
3464 the appropriate X display info. */
3466 static void
3467 XTframe_rehighlight (frame)
3468 struct frame *frame;
3470 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3473 static void
3474 x_frame_rehighlight (dpyinfo)
3475 struct x_display_info *dpyinfo;
3477 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3479 if (dpyinfo->x_focus_frame)
3481 dpyinfo->x_highlight_frame
3482 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3483 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3484 : dpyinfo->x_focus_frame);
3485 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3487 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3488 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3491 else
3492 dpyinfo->x_highlight_frame = 0;
3494 if (dpyinfo->x_highlight_frame != old_highlight)
3496 if (old_highlight)
3497 frame_unhighlight (old_highlight);
3498 if (dpyinfo->x_highlight_frame)
3499 frame_highlight (dpyinfo->x_highlight_frame);
3505 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3507 #if 0 /* MAC_TODO */
3508 /* Initialize mode_switch_bit and modifier_meaning. */
3509 static void
3510 x_find_modifier_meanings (dpyinfo)
3511 struct x_display_info *dpyinfo;
3513 int min_code, max_code;
3514 KeySym *syms;
3515 int syms_per_code;
3516 XModifierKeymap *mods;
3518 dpyinfo->meta_mod_mask = 0;
3519 dpyinfo->shift_lock_mask = 0;
3520 dpyinfo->alt_mod_mask = 0;
3521 dpyinfo->super_mod_mask = 0;
3522 dpyinfo->hyper_mod_mask = 0;
3524 #ifdef HAVE_X11R4
3525 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3526 #else
3527 min_code = dpyinfo->display->min_keycode;
3528 max_code = dpyinfo->display->max_keycode;
3529 #endif
3531 syms = XGetKeyboardMapping (dpyinfo->display,
3532 min_code, max_code - min_code + 1,
3533 &syms_per_code);
3534 mods = XGetModifierMapping (dpyinfo->display);
3536 /* Scan the modifier table to see which modifier bits the Meta and
3537 Alt keysyms are on. */
3539 int row, col; /* The row and column in the modifier table. */
3541 for (row = 3; row < 8; row++)
3542 for (col = 0; col < mods->max_keypermod; col++)
3544 KeyCode code
3545 = mods->modifiermap[(row * mods->max_keypermod) + col];
3547 /* Zeroes are used for filler. Skip them. */
3548 if (code == 0)
3549 continue;
3551 /* Are any of this keycode's keysyms a meta key? */
3553 int code_col;
3555 for (code_col = 0; code_col < syms_per_code; code_col++)
3557 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3559 switch (sym)
3561 case XK_Meta_L:
3562 case XK_Meta_R:
3563 dpyinfo->meta_mod_mask |= (1 << row);
3564 break;
3566 case XK_Alt_L:
3567 case XK_Alt_R:
3568 dpyinfo->alt_mod_mask |= (1 << row);
3569 break;
3571 case XK_Hyper_L:
3572 case XK_Hyper_R:
3573 dpyinfo->hyper_mod_mask |= (1 << row);
3574 break;
3576 case XK_Super_L:
3577 case XK_Super_R:
3578 dpyinfo->super_mod_mask |= (1 << row);
3579 break;
3581 case XK_Shift_Lock:
3582 /* Ignore this if it's not on the lock modifier. */
3583 if ((1 << row) == LockMask)
3584 dpyinfo->shift_lock_mask = LockMask;
3585 break;
3592 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3593 if (! dpyinfo->meta_mod_mask)
3595 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3596 dpyinfo->alt_mod_mask = 0;
3599 /* If some keys are both alt and meta,
3600 make them just meta, not alt. */
3601 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3603 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3606 XFree ((char *) syms);
3607 XFreeModifiermap (mods);
3610 #endif /* MAC_TODO */
3612 /* Convert between the modifier bits X uses and the modifier bits
3613 Emacs uses. */
3615 static unsigned int
3616 x_mac_to_emacs_modifiers (dpyinfo, state)
3617 struct x_display_info *dpyinfo;
3618 unsigned short state;
3620 return (((state & shiftKey) ? shift_modifier : 0)
3621 | ((state & controlKey) ? ctrl_modifier : 0)
3622 | ((state & cmdKey) ? meta_modifier : 0)
3623 | ((state & optionKey) ? alt_modifier : 0));
3626 #if 0 /* MAC_TODO */
3627 static unsigned short
3628 x_emacs_to_x_modifiers (dpyinfo, state)
3629 struct x_display_info *dpyinfo;
3630 unsigned int state;
3632 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3633 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3634 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3635 | ((state & shift_modifier) ? ShiftMask : 0)
3636 | ((state & ctrl_modifier) ? ControlMask : 0)
3637 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3639 #endif /* MAC_TODO */
3641 /* Convert a keysym to its name. */
3643 char *
3644 x_get_keysym_name (keysym)
3645 int keysym;
3647 char *value;
3649 BLOCK_INPUT;
3650 #if 0
3651 value = XKeysymToString (keysym);
3652 #else
3653 value = 0;
3654 #endif
3655 UNBLOCK_INPUT;
3657 return value;
3662 #if 0
3663 /* Mouse clicks and mouse movement. Rah. */
3665 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3667 If the event is a button press, then note that we have grabbed
3668 the mouse. */
3670 static Lisp_Object
3671 construct_mouse_click (result, event, f)
3672 struct input_event *result;
3673 EventRecord *event;
3674 struct frame *f;
3676 Point mouseLoc;
3678 result->kind = MOUSE_CLICK_EVENT;
3679 result->code = 0; /* only one mouse button */
3680 result->timestamp = event->when;
3681 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3683 mouseLoc = event->where;
3685 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3687 GlobalToLocal (&mouseLoc);
3688 XSETINT (result->x, mouseLoc.h);
3689 XSETINT (result->y, mouseLoc.v);
3691 XSETFRAME (result->frame_or_window, f);
3693 result->arg = Qnil;
3694 return Qnil;
3696 #endif
3699 /* Function to report a mouse movement to the mainstream Emacs code.
3700 The input handler calls this.
3702 We have received a mouse movement event, which is given in *event.
3703 If the mouse is over a different glyph than it was last time, tell
3704 the mainstream emacs code by setting mouse_moved. If not, ask for
3705 another motion event, so we can check again the next time it moves. */
3707 static Point last_mouse_motion_position;
3708 static Lisp_Object last_mouse_motion_frame;
3710 static void
3711 note_mouse_movement (frame, pos)
3712 FRAME_PTR frame;
3713 Point *pos;
3715 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3716 #if TARGET_API_MAC_CARBON
3717 Rect r;
3718 #endif
3720 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3721 last_mouse_motion_position = *pos;
3722 XSETFRAME (last_mouse_motion_frame, frame);
3724 #if TARGET_API_MAC_CARBON
3725 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3726 #else
3727 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3728 #endif
3730 if (frame == dpyinfo->mouse_face_mouse_frame)
3731 /* This case corresponds to LeaveNotify in X11. */
3733 /* If we move outside the frame, then we're certainly no
3734 longer on any text in the frame. */
3735 clear_mouse_face (dpyinfo);
3736 dpyinfo->mouse_face_mouse_frame = 0;
3737 if (!dpyinfo->grabbed)
3738 rif->define_frame_cursor (frame,
3739 frame->output_data.mac->nontext_cursor);
3742 /* Has the mouse moved off the glyph it was on at the last sighting? */
3743 else if (pos->h < last_mouse_glyph.left
3744 || pos->h >= last_mouse_glyph.right
3745 || pos->v < last_mouse_glyph.top
3746 || pos->v >= last_mouse_glyph.bottom)
3748 frame->mouse_moved = 1;
3749 last_mouse_scroll_bar = Qnil;
3750 note_mouse_highlight (frame, pos->h, pos->v);
3754 /* This is used for debugging, to turn off note_mouse_highlight. */
3756 int disable_mouse_highlight;
3760 /************************************************************************
3761 Mouse Face
3762 ************************************************************************/
3764 static struct scroll_bar *x_window_to_scroll_bar ();
3765 static void x_scroll_bar_report_motion ();
3766 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3769 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3771 static void
3772 redo_mouse_highlight ()
3774 if (!NILP (last_mouse_motion_frame)
3775 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3776 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3777 last_mouse_motion_position.h,
3778 last_mouse_motion_position.v);
3782 /* Try to determine frame pixel position and size of the glyph under
3783 frame pixel coordinates X/Y on frame F . Return the position and
3784 size in *RECT. Value is non-zero if we could compute these
3785 values. */
3787 static int
3788 glyph_rect (f, x, y, rect)
3789 struct frame *f;
3790 int x, y;
3791 Rect *rect;
3793 Lisp_Object window;
3795 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3797 if (!NILP (window))
3799 struct window *w = XWINDOW (window);
3800 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3801 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3803 for (; r < end && r->enabled_p; ++r)
3804 if (r->y <= y && r->y + r->height > y)
3806 /* Found the row at y. */
3807 struct glyph *g = r->glyphs[TEXT_AREA];
3808 struct glyph *end = g + r->used[TEXT_AREA];
3809 int gx;
3811 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3812 rect->bottom = rect->top + r->height;
3814 if (x < r->x)
3816 /* x is to the left of the first glyph in the row. */
3817 /* Shouldn't this be a pixel value?
3818 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3819 ++KFS */
3820 rect->left = WINDOW_LEFT_EDGE_COL (w);
3821 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3822 return 1;
3825 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3826 if (gx <= x && gx + g->pixel_width > x)
3828 /* x is on a glyph. */
3829 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3830 rect->right = rect->left + g->pixel_width;
3831 return 1;
3834 /* x is to the right of the last glyph in the row. */
3835 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3836 /* Shouldn't this be a pixel value?
3837 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3838 ++KFS */
3839 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3840 return 1;
3844 /* The y is not on any row. */
3845 return 0;
3848 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3850 /* Record the position of the mouse in last_mouse_glyph. */
3851 static void
3852 remember_mouse_glyph (f1, gx, gy)
3853 struct frame * f1;
3854 int gx, gy;
3856 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3858 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3859 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3861 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3862 round down even for negative values. */
3863 if (gx < 0)
3864 gx -= width - 1;
3865 if (gy < 0)
3866 gy -= height - 1;
3867 #if 0
3868 /* This was the original code from XTmouse_position, but it seems
3869 to give the position of the glyph diagonally next to the one
3870 the mouse is over. */
3871 gx = (gx + width - 1) / width * width;
3872 gy = (gy + height - 1) / height * height;
3873 #else
3874 gx = gx / width * width;
3875 gy = gy / height * height;
3876 #endif
3878 last_mouse_glyph.left = gx;
3879 last_mouse_glyph.top = gy;
3880 last_mouse_glyph.right = gx + width;
3881 last_mouse_glyph.bottom = gy + height;
3886 static WindowPtr
3887 front_emacs_window ()
3889 #if TARGET_API_MAC_CARBON
3890 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3892 while (wp && !is_emacs_window (wp))
3893 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3894 #else
3895 WindowPtr wp = FrontWindow ();
3897 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3898 wp = GetNextWindow (wp);
3899 #endif
3901 return wp;
3904 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3906 /* Return the current position of the mouse.
3907 *fp should be a frame which indicates which display to ask about.
3909 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3910 and *part to the frame, window, and scroll bar part that the mouse
3911 is over. Set *x and *y to the portion and whole of the mouse's
3912 position on the scroll bar.
3914 If the mouse movement started elsewhere, set *fp to the frame the
3915 mouse is on, *bar_window to nil, and *x and *y to the character cell
3916 the mouse is over.
3918 Set *time to the server time-stamp for the time at which the mouse
3919 was at this position.
3921 Don't store anything if we don't have a valid set of values to report.
3923 This clears the mouse_moved flag, so we can wait for the next mouse
3924 movement. */
3926 static void
3927 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3928 FRAME_PTR *fp;
3929 int insist;
3930 Lisp_Object *bar_window;
3931 enum scroll_bar_part *part;
3932 Lisp_Object *x, *y;
3933 unsigned long *time;
3935 Point mouse_pos;
3936 int ignore1, ignore2;
3937 WindowPtr wp = front_emacs_window ();
3938 struct frame *f;
3939 Lisp_Object frame, tail;
3941 if (is_emacs_window(wp))
3942 f = mac_window_to_frame (wp);
3944 BLOCK_INPUT;
3946 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3947 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3948 else
3950 /* Clear the mouse-moved flag for every frame on this display. */
3951 FOR_EACH_FRAME (tail, frame)
3952 XFRAME (frame)->mouse_moved = 0;
3954 last_mouse_scroll_bar = Qnil;
3956 SetPortWindowPort (wp);
3958 GetMouse (&mouse_pos);
3960 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3961 &last_mouse_glyph, insist);
3963 *bar_window = Qnil;
3964 *part = scroll_bar_handle;
3965 *fp = f;
3966 XSETINT (*x, mouse_pos.h);
3967 XSETINT (*y, mouse_pos.v);
3968 *time = last_mouse_movement_time;
3971 UNBLOCK_INPUT;
3975 /***********************************************************************
3976 Tool-bars
3977 ***********************************************************************/
3979 /* Handle mouse button event on the tool-bar of frame F, at
3980 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3981 or ButtonRelase. */
3983 static void
3984 mac_handle_tool_bar_click (f, button_event)
3985 struct frame *f;
3986 EventRecord *button_event;
3988 int x = button_event->where.h;
3989 int y = button_event->where.v;
3991 if (button_event->what == mouseDown)
3992 handle_tool_bar_click (f, x, y, 1, 0);
3993 else
3994 handle_tool_bar_click (f, x, y, 0,
3995 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
3996 button_event->modifiers));
4000 /************************************************************************
4001 Scroll bars, general
4002 ************************************************************************/
4004 /* Create a scroll bar and return the scroll bar vector for it. W is
4005 the Emacs window on which to create the scroll bar. TOP, LEFT,
4006 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4007 scroll bar. */
4009 static struct scroll_bar *
4010 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4011 struct window *w;
4012 int top, left, width, height, disp_top, disp_height;
4014 struct frame *f = XFRAME (w->frame);
4015 struct scroll_bar *bar
4016 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4017 Rect r;
4018 ControlHandle ch;
4020 BLOCK_INPUT;
4022 r.left = left;
4023 r.top = disp_top;
4024 r.right = left + width;
4025 r.bottom = disp_top + disp_height;
4027 #if TARGET_API_MAC_CARBON
4028 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4029 kControlScrollBarProc, 0L);
4030 #else
4031 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4032 0L);
4033 #endif
4034 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4035 SetControlReference (ch, (long) bar);
4037 XSETWINDOW (bar->window, w);
4038 XSETINT (bar->top, top);
4039 XSETINT (bar->left, left);
4040 XSETINT (bar->width, width);
4041 XSETINT (bar->height, height);
4042 XSETINT (bar->start, 0);
4043 XSETINT (bar->end, 0);
4044 bar->dragging = Qnil;
4046 /* Add bar to its frame's list of scroll bars. */
4047 bar->next = FRAME_SCROLL_BARS (f);
4048 bar->prev = Qnil;
4049 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4050 if (!NILP (bar->next))
4051 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4053 UNBLOCK_INPUT;
4054 return bar;
4058 /* Draw BAR's handle in the proper position.
4060 If the handle is already drawn from START to END, don't bother
4061 redrawing it, unless REBUILD is non-zero; in that case, always
4062 redraw it. (REBUILD is handy for drawing the handle after expose
4063 events.)
4065 Normally, we want to constrain the start and end of the handle to
4066 fit inside its rectangle, but if the user is dragging the scroll
4067 bar handle, we want to let them drag it down all the way, so that
4068 the bar's top is as far down as it goes; otherwise, there's no way
4069 to move to the very end of the buffer. */
4071 static void
4072 x_scroll_bar_set_handle (bar, start, end, rebuild)
4073 struct scroll_bar *bar;
4074 int start, end;
4075 int rebuild;
4077 int dragging = ! NILP (bar->dragging);
4078 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4079 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4080 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4081 int length = end - start;
4083 /* If the display is already accurate, do nothing. */
4084 if (! rebuild
4085 && start == XINT (bar->start)
4086 && end == XINT (bar->end))
4087 return;
4089 BLOCK_INPUT;
4091 /* Make sure the values are reasonable, and try to preserve the
4092 distance between start and end. */
4093 if (start < 0)
4094 start = 0;
4095 else if (start > top_range)
4096 start = top_range;
4097 end = start + length;
4099 if (end < start)
4100 end = start;
4101 else if (end > top_range && ! dragging)
4102 end = top_range;
4104 /* Store the adjusted setting in the scroll bar. */
4105 XSETINT (bar->start, start);
4106 XSETINT (bar->end, end);
4108 /* Clip the end position, just for display. */
4109 if (end > top_range)
4110 end = top_range;
4112 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4113 top positions, to make sure the handle is always at least that
4114 many pixels tall. */
4115 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4117 SetControlMinimum (ch, 0);
4118 /* Don't inadvertently activate deactivated scroll bars */
4119 if (GetControlMaximum (ch) != -1)
4120 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4121 - (end - start));
4122 SetControlValue (ch, start);
4123 #if TARGET_API_MAC_CARBON
4124 SetControlViewSize (ch, end - start);
4125 #endif
4127 UNBLOCK_INPUT;
4131 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4132 nil. */
4134 static void
4135 x_scroll_bar_remove (bar)
4136 struct scroll_bar *bar;
4138 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4140 BLOCK_INPUT;
4142 /* Destroy the Mac scroll bar control */
4143 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4145 /* Disassociate this scroll bar from its window. */
4146 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4148 UNBLOCK_INPUT;
4151 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4152 that we are displaying PORTION characters out of a total of WHOLE
4153 characters, starting at POSITION. If WINDOW has no scroll bar,
4154 create one. */
4155 static void
4156 XTset_vertical_scroll_bar (w, portion, whole, position)
4157 struct window *w;
4158 int portion, whole, position;
4160 struct frame *f = XFRAME (w->frame);
4161 struct scroll_bar *bar;
4162 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4163 int window_y, window_height;
4165 /* Get window dimensions. */
4166 window_box (w, -1, 0, &window_y, 0, &window_height);
4167 top = window_y;
4168 #ifdef MAC_OSX
4169 width = 16;
4170 #else
4171 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4172 #endif
4173 height = window_height;
4175 /* Compute the left edge of the scroll bar area. */
4176 left = WINDOW_SCROLL_BAR_AREA_X (w);
4178 /* Compute the width of the scroll bar which might be less than
4179 the width of the area reserved for the scroll bar. */
4180 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4181 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4182 else
4183 sb_width = width;
4185 /* Compute the left edge of the scroll bar. */
4186 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4187 sb_left = left + width - sb_width - (width - sb_width) / 2;
4188 else
4189 sb_left = left + (width - sb_width) / 2;
4191 /* Adjustments according to Inside Macintosh to make it look nice */
4192 disp_top = top;
4193 disp_height = height;
4194 if (disp_top == 0)
4196 disp_top = -1;
4197 disp_height++;
4199 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4201 disp_top++;
4202 disp_height--;
4205 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4206 sb_left++;
4208 /* Does the scroll bar exist yet? */
4209 if (NILP (w->vertical_scroll_bar))
4211 BLOCK_INPUT;
4212 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4213 left, top, width, height, 0);
4214 UNBLOCK_INPUT;
4215 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4216 disp_height);
4217 XSETVECTOR (w->vertical_scroll_bar, bar);
4219 else
4221 /* It may just need to be moved and resized. */
4222 ControlHandle ch;
4224 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4225 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4227 BLOCK_INPUT;
4229 /* If already correctly positioned, do nothing. */
4230 if (XINT (bar->left) == sb_left
4231 && XINT (bar->top) == top
4232 && XINT (bar->width) == sb_width
4233 && XINT (bar->height) == height)
4234 Draw1Control (ch);
4235 else
4237 /* Clear areas not covered by the scroll bar because it's not as
4238 wide as the area reserved for it . This makes sure a
4239 previous mode line display is cleared after C-x 2 C-x 1, for
4240 example. */
4241 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4242 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4243 left, top, area_width, height, 0);
4245 #if 0
4246 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4247 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4248 sb_left - 1, top, 1, height, 0);
4249 #endif
4251 HideControl (ch);
4252 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4253 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4254 disp_height);
4255 ShowControl (ch);
4257 /* Remember new settings. */
4258 XSETINT (bar->left, sb_left);
4259 XSETINT (bar->top, top);
4260 XSETINT (bar->width, sb_width);
4261 XSETINT (bar->height, height);
4264 UNBLOCK_INPUT;
4267 /* Set the scroll bar's current state, unless we're currently being
4268 dragged. */
4269 if (NILP (bar->dragging))
4271 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4273 if (whole == 0)
4274 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4275 else
4277 int start = ((double) position * top_range) / whole;
4278 int end = ((double) (position + portion) * top_range) / whole;
4279 x_scroll_bar_set_handle (bar, start, end, 0);
4285 /* The following three hooks are used when we're doing a thorough
4286 redisplay of the frame. We don't explicitly know which scroll bars
4287 are going to be deleted, because keeping track of when windows go
4288 away is a real pain - "Can you say set-window-configuration, boys
4289 and girls?" Instead, we just assert at the beginning of redisplay
4290 that *all* scroll bars are to be removed, and then save a scroll bar
4291 from the fiery pit when we actually redisplay its window. */
4293 /* Arrange for all scroll bars on FRAME to be removed at the next call
4294 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4295 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4297 static void
4298 XTcondemn_scroll_bars (frame)
4299 FRAME_PTR frame;
4301 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4302 while (! NILP (FRAME_SCROLL_BARS (frame)))
4304 Lisp_Object bar;
4305 bar = FRAME_SCROLL_BARS (frame);
4306 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4307 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4308 XSCROLL_BAR (bar)->prev = Qnil;
4309 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4310 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4311 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4316 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4317 Note that WINDOW isn't necessarily condemned at all. */
4319 static void
4320 XTredeem_scroll_bar (window)
4321 struct window *window;
4323 struct scroll_bar *bar;
4325 /* We can't redeem this window's scroll bar if it doesn't have one. */
4326 if (NILP (window->vertical_scroll_bar))
4327 abort ();
4329 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4331 /* Unlink it from the condemned list. */
4333 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4335 if (NILP (bar->prev))
4337 /* If the prev pointer is nil, it must be the first in one of
4338 the lists. */
4339 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4340 /* It's not condemned. Everything's fine. */
4341 return;
4342 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4343 window->vertical_scroll_bar))
4344 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4345 else
4346 /* If its prev pointer is nil, it must be at the front of
4347 one or the other! */
4348 abort ();
4350 else
4351 XSCROLL_BAR (bar->prev)->next = bar->next;
4353 if (! NILP (bar->next))
4354 XSCROLL_BAR (bar->next)->prev = bar->prev;
4356 bar->next = FRAME_SCROLL_BARS (f);
4357 bar->prev = Qnil;
4358 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4359 if (! NILP (bar->next))
4360 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4364 /* Remove all scroll bars on FRAME that haven't been saved since the
4365 last call to `*condemn_scroll_bars_hook'. */
4367 static void
4368 XTjudge_scroll_bars (f)
4369 FRAME_PTR f;
4371 Lisp_Object bar, next;
4373 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4375 /* Clear out the condemned list now so we won't try to process any
4376 more events on the hapless scroll bars. */
4377 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4379 for (; ! NILP (bar); bar = next)
4381 struct scroll_bar *b = XSCROLL_BAR (bar);
4383 x_scroll_bar_remove (b);
4385 next = b->next;
4386 b->next = b->prev = Qnil;
4389 /* Now there should be no references to the condemned scroll bars,
4390 and they should get garbage-collected. */
4394 void
4395 activate_scroll_bars (frame)
4396 FRAME_PTR frame;
4398 Lisp_Object bar;
4399 ControlHandle ch;
4401 bar = FRAME_SCROLL_BARS (frame);
4402 while (! NILP (bar))
4404 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4405 #if 1 /* TARGET_API_MAC_CARBON */
4406 ActivateControl (ch);
4407 #else
4408 SetControlMaximum (ch,
4409 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4410 XINT (XSCROLL_BAR (bar)
4411 ->height)) - 1);
4412 #endif
4413 bar = XSCROLL_BAR (bar)->next;
4418 void
4419 deactivate_scroll_bars (frame)
4420 FRAME_PTR frame;
4422 Lisp_Object bar;
4423 ControlHandle ch;
4425 bar = FRAME_SCROLL_BARS (frame);
4426 while (! NILP (bar))
4428 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4429 #if 1 /* TARGET_API_MAC_CARBON */
4430 DeactivateControl (ch);
4431 #else
4432 SetControlMaximum (ch, -1);
4433 #endif
4434 bar = XSCROLL_BAR (bar)->next;
4438 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4439 is set to something other than NO_EVENT, it is enqueued.
4441 This may be called from a signal handler, so we have to ignore GC
4442 mark bits. */
4444 static void
4445 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4446 struct scroll_bar *bar;
4447 int part_code;
4448 EventRecord *er;
4449 struct input_event *bufp;
4451 int win_y, top_range;
4453 if (! GC_WINDOWP (bar->window))
4454 abort ();
4456 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4457 bufp->frame_or_window = bar->window;
4458 bufp->arg = Qnil;
4460 bar->dragging = Qnil;
4462 switch (part_code)
4464 case kControlUpButtonPart:
4465 bufp->part = scroll_bar_up_arrow;
4466 break;
4467 case kControlDownButtonPart:
4468 bufp->part = scroll_bar_down_arrow;
4469 break;
4470 case kControlPageUpPart:
4471 bufp->part = scroll_bar_above_handle;
4472 break;
4473 case kControlPageDownPart:
4474 bufp->part = scroll_bar_below_handle;
4475 break;
4476 #if TARGET_API_MAC_CARBON
4477 default:
4478 #else
4479 case kControlIndicatorPart:
4480 #endif
4481 if (er->what == mouseDown)
4482 bar->dragging = make_number (0);
4483 XSETVECTOR (last_mouse_scroll_bar, bar);
4484 bufp->part = scroll_bar_handle;
4485 break;
4488 win_y = XINT (bufp->y) - XINT (bar->top);
4489 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4491 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4493 win_y -= 24;
4495 if (! NILP (bar->dragging))
4496 win_y -= XINT (bar->dragging);
4498 if (win_y < 0)
4499 win_y = 0;
4500 if (win_y > top_range)
4501 win_y = top_range;
4503 XSETINT (bufp->x, win_y);
4504 XSETINT (bufp->y, top_range);
4508 /* Handle some mouse motion while someone is dragging the scroll bar.
4510 This may be called from a signal handler, so we have to ignore GC
4511 mark bits. */
4513 static void
4514 x_scroll_bar_note_movement (bar, y_pos, t)
4515 struct scroll_bar *bar;
4516 int y_pos;
4517 Time t;
4519 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4521 last_mouse_movement_time = t;
4523 f->mouse_moved = 1;
4524 XSETVECTOR (last_mouse_scroll_bar, bar);
4526 /* If we're dragging the bar, display it. */
4527 if (! GC_NILP (bar->dragging))
4529 /* Where should the handle be now? */
4530 int new_start = y_pos - 24;
4532 if (new_start != XINT (bar->start))
4534 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4536 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4542 /* Return information to the user about the current position of the
4543 mouse on the scroll bar. */
4545 static void
4546 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4547 FRAME_PTR *fp;
4548 Lisp_Object *bar_window;
4549 enum scroll_bar_part *part;
4550 Lisp_Object *x, *y;
4551 unsigned long *time;
4553 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4554 WindowPtr wp = front_emacs_window ();
4555 Point mouse_pos;
4556 struct frame *f = mac_window_to_frame (wp);
4557 int win_y, top_range;
4559 SetPortWindowPort (wp);
4561 GetMouse (&mouse_pos);
4563 win_y = mouse_pos.v - XINT (bar->top);
4564 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4566 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4568 win_y -= 24;
4570 if (! NILP (bar->dragging))
4571 win_y -= XINT (bar->dragging);
4573 if (win_y < 0)
4574 win_y = 0;
4575 if (win_y > top_range)
4576 win_y = top_range;
4578 *fp = f;
4579 *bar_window = bar->window;
4581 if (! NILP (bar->dragging))
4582 *part = scroll_bar_handle;
4583 else if (win_y < XINT (bar->start))
4584 *part = scroll_bar_above_handle;
4585 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4586 *part = scroll_bar_handle;
4587 else
4588 *part = scroll_bar_below_handle;
4590 XSETINT (*x, win_y);
4591 XSETINT (*y, top_range);
4593 f->mouse_moved = 0;
4594 last_mouse_scroll_bar = Qnil;
4596 *time = last_mouse_movement_time;
4599 /***********************************************************************
4600 Text Cursor
4601 ***********************************************************************/
4603 /* Set clipping for output in glyph row ROW. W is the window in which
4604 we operate. GC is the graphics context to set clipping in.
4606 ROW may be a text row or, e.g., a mode line. Text rows must be
4607 clipped to the interior of the window dedicated to text display,
4608 mode lines must be clipped to the whole window. */
4610 static void
4611 x_clip_to_row (w, row, area, gc)
4612 struct window *w;
4613 struct glyph_row *row;
4614 int area;
4615 GC gc;
4617 struct frame *f = XFRAME (WINDOW_FRAME (w));
4618 Rect clip_rect;
4619 int window_x, window_y, window_width;
4621 window_box (w, area, &window_x, &window_y, &window_width, 0);
4623 clip_rect.left = window_x;
4624 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4625 clip_rect.top = max (clip_rect.top, window_y);
4626 clip_rect.right = clip_rect.left + window_width;
4627 clip_rect.bottom = clip_rect.top + row->visible_height;
4629 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4633 /* Draw a hollow box cursor on window W in glyph row ROW. */
4635 static void
4636 x_draw_hollow_cursor (w, row)
4637 struct window *w;
4638 struct glyph_row *row;
4640 struct frame *f = XFRAME (WINDOW_FRAME (w));
4641 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4642 Display *dpy = FRAME_MAC_DISPLAY (f);
4643 int x, y, wd, h;
4644 XGCValues xgcv;
4645 struct glyph *cursor_glyph;
4646 GC gc;
4648 /* Get the glyph the cursor is on. If we can't tell because
4649 the current matrix is invalid or such, give up. */
4650 cursor_glyph = get_phys_cursor_glyph (w);
4651 if (cursor_glyph == NULL)
4652 return;
4654 /* Compute the width of the rectangle to draw. If on a stretch
4655 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4656 rectangle as wide as the glyph, but use a canonical character
4657 width instead. */
4658 wd = cursor_glyph->pixel_width - 1;
4659 if (cursor_glyph->type == STRETCH_GLYPH
4660 && !x_stretch_cursor_p)
4661 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4662 w->phys_cursor_width = wd;
4664 /* Compute frame-relative coordinates from window-relative
4665 coordinates. */
4666 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4667 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4669 /* Compute the proper height and ascent of the rectangle, based
4670 on the actual glyph. Using the full height of the row looks
4671 bad when there are tall images on that row. */
4672 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4673 cursor_glyph->ascent + cursor_glyph->descent);
4674 if (h < row->height)
4675 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4676 h--;
4678 /* The foreground of cursor_gc is typically the same as the normal
4679 background color, which can cause the cursor box to be invisible. */
4680 xgcv.foreground = f->output_data.mac->cursor_pixel;
4681 if (dpyinfo->scratch_cursor_gc)
4682 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4683 else
4684 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4685 GCForeground, &xgcv);
4686 gc = dpyinfo->scratch_cursor_gc;
4688 /* Set clipping, draw the rectangle, and reset clipping again. */
4689 x_clip_to_row (w, row, TEXT_AREA, gc);
4690 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4691 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4695 /* Draw a bar cursor on window W in glyph row ROW.
4697 Implementation note: One would like to draw a bar cursor with an
4698 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4699 Unfortunately, I didn't find a font yet that has this property set.
4700 --gerd. */
4702 static void
4703 x_draw_bar_cursor (w, row, width, kind)
4704 struct window *w;
4705 struct glyph_row *row;
4706 int width;
4707 enum text_cursor_kinds kind;
4709 struct frame *f = XFRAME (w->frame);
4710 struct glyph *cursor_glyph;
4712 /* If cursor is out of bounds, don't draw garbage. This can happen
4713 in mini-buffer windows when switching between echo area glyphs
4714 and mini-buffer. */
4715 cursor_glyph = get_phys_cursor_glyph (w);
4716 if (cursor_glyph == NULL)
4717 return;
4719 /* If on an image, draw like a normal cursor. That's usually better
4720 visible than drawing a bar, esp. if the image is large so that
4721 the bar might not be in the window. */
4722 if (cursor_glyph->type == IMAGE_GLYPH)
4724 struct glyph_row *row;
4725 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4726 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4728 else
4730 Display *dpy = FRAME_MAC_DISPLAY (f);
4731 Window window = FRAME_MAC_WINDOW (f);
4732 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4733 unsigned long mask = GCForeground | GCBackground;
4734 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4735 XGCValues xgcv;
4737 /* If the glyph's background equals the color we normally draw
4738 the bar cursor in, the bar cursor in its normal color is
4739 invisible. Use the glyph's foreground color instead in this
4740 case, on the assumption that the glyph's colors are chosen so
4741 that the glyph is legible. */
4742 if (face->background == f->output_data.mac->cursor_pixel)
4743 xgcv.background = xgcv.foreground = face->foreground;
4744 else
4745 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4747 if (gc)
4748 XChangeGC (dpy, gc, mask, &xgcv);
4749 else
4751 gc = XCreateGC (dpy, window, mask, &xgcv);
4752 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4755 if (width < 0)
4756 width = FRAME_CURSOR_WIDTH (f);
4757 width = min (cursor_glyph->pixel_width, width);
4759 w->phys_cursor_width = width;
4760 x_clip_to_row (w, row, TEXT_AREA, gc);
4762 if (kind == BAR_CURSOR)
4763 XFillRectangle (dpy, window, gc,
4764 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4765 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4766 width, row->height);
4767 else
4768 XFillRectangle (dpy, window, gc,
4769 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4770 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4771 row->height - width),
4772 cursor_glyph->pixel_width,
4773 width);
4775 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4780 /* RIF: Define cursor CURSOR on frame F. */
4782 static void
4783 mac_define_frame_cursor (f, cursor)
4784 struct frame *f;
4785 Cursor cursor;
4787 #if TARGET_API_MAC_CARBON
4788 SetThemeCursor (cursor);
4789 #else
4790 SetCursor (*cursor);
4791 #endif
4795 /* RIF: Clear area on frame F. */
4797 static void
4798 mac_clear_frame_area (f, x, y, width, height)
4799 struct frame *f;
4800 int x, y, width, height;
4802 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4803 x, y, width, height, 0);
4807 /* RIF: Draw cursor on window W. */
4809 static void
4810 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4811 struct window *w;
4812 struct glyph_row *glyph_row;
4813 int x, y;
4814 int cursor_type, cursor_width;
4815 int on_p, active_p;
4817 if (on_p)
4819 w->phys_cursor_type = cursor_type;
4820 w->phys_cursor_on_p = 1;
4822 if (glyph_row->exact_window_width_line_p
4823 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4825 glyph_row->cursor_in_fringe_p = 1;
4826 draw_fringe_bitmap (w, glyph_row, 0);
4828 else
4829 switch (cursor_type)
4831 case HOLLOW_BOX_CURSOR:
4832 x_draw_hollow_cursor (w, glyph_row);
4833 break;
4835 case FILLED_BOX_CURSOR:
4836 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4837 break;
4839 case BAR_CURSOR:
4840 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4841 break;
4843 case HBAR_CURSOR:
4844 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4845 break;
4847 case NO_CURSOR:
4848 w->phys_cursor_width = 0;
4849 break;
4851 default:
4852 abort ();
4858 /* Icons. */
4860 #if 0 /* MAC_TODO: no icon support yet. */
4862 x_bitmap_icon (f, icon)
4863 struct frame *f;
4864 Lisp_Object icon;
4866 HANDLE hicon;
4868 if (FRAME_W32_WINDOW (f) == 0)
4869 return 1;
4871 if (NILP (icon))
4872 hicon = LoadIcon (hinst, EMACS_CLASS);
4873 else if (STRINGP (icon))
4874 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4875 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4876 else if (SYMBOLP (icon))
4878 LPCTSTR name;
4880 if (EQ (icon, intern ("application")))
4881 name = (LPCTSTR) IDI_APPLICATION;
4882 else if (EQ (icon, intern ("hand")))
4883 name = (LPCTSTR) IDI_HAND;
4884 else if (EQ (icon, intern ("question")))
4885 name = (LPCTSTR) IDI_QUESTION;
4886 else if (EQ (icon, intern ("exclamation")))
4887 name = (LPCTSTR) IDI_EXCLAMATION;
4888 else if (EQ (icon, intern ("asterisk")))
4889 name = (LPCTSTR) IDI_ASTERISK;
4890 else if (EQ (icon, intern ("winlogo")))
4891 name = (LPCTSTR) IDI_WINLOGO;
4892 else
4893 return 1;
4895 hicon = LoadIcon (NULL, name);
4897 else
4898 return 1;
4900 if (hicon == NULL)
4901 return 1;
4903 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4904 (LPARAM) hicon);
4906 return 0;
4908 #endif /* MAC_TODO */
4910 /************************************************************************
4911 Handling X errors
4912 ************************************************************************/
4914 /* Display Error Handling functions not used on W32. Listing them here
4915 helps diff stay in step when comparing w32term.c with xterm.c.
4917 x_error_catcher (display, error)
4918 x_catch_errors (dpy)
4919 x_catch_errors_unwind (old_val)
4920 x_check_errors (dpy, format)
4921 x_had_errors_p (dpy)
4922 x_clear_errors (dpy)
4923 x_uncatch_errors (dpy, count)
4924 x_trace_wire ()
4925 x_connection_signal (signalnum)
4926 x_connection_closed (dpy, error_message)
4927 x_error_quitter (display, error)
4928 x_error_handler (display, error)
4929 x_io_error_quitter (display)
4934 /* Changing the font of the frame. */
4936 /* Give frame F the font named FONTNAME as its default font, and
4937 return the full name of that font. FONTNAME may be a wildcard
4938 pattern; in that case, we choose some font that fits the pattern.
4939 The return value shows which font we chose. */
4941 Lisp_Object
4942 x_new_font (f, fontname)
4943 struct frame *f;
4944 register char *fontname;
4946 struct font_info *fontp
4947 = FS_LOAD_FONT (f, 0, fontname, -1);
4949 if (!fontp)
4950 return Qnil;
4952 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4953 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4954 FRAME_FONTSET (f) = -1;
4956 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
4957 FRAME_SPACE_WIDTH (f) = fontp->space_width;
4958 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4960 compute_fringe_widths (f, 1);
4962 /* Compute the scroll bar width in character columns. */
4963 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4965 int wid = FRAME_COLUMN_WIDTH (f);
4966 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4967 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4969 else
4971 int wid = FRAME_COLUMN_WIDTH (f);
4972 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4975 /* Now make the frame display the given font. */
4976 if (FRAME_MAC_WINDOW (f) != 0)
4978 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4979 FRAME_FONT (f));
4980 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4981 FRAME_FONT (f));
4982 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4983 FRAME_FONT (f));
4985 /* Don't change the size of a tip frame; there's no point in
4986 doing it because it's done in Fx_show_tip, and it leads to
4987 problems because the tip frame has no widget. */
4988 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4989 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4992 return build_string (fontp->full_name);
4995 /* Give frame F the fontset named FONTSETNAME as its default font, and
4996 return the full name of that fontset. FONTSETNAME may be a wildcard
4997 pattern; in that case, we choose some fontset that fits the pattern.
4998 The return value shows which fontset we chose. */
5000 Lisp_Object
5001 x_new_fontset (f, fontsetname)
5002 struct frame *f;
5003 char *fontsetname;
5005 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5006 Lisp_Object result;
5008 if (fontset < 0)
5009 return Qnil;
5011 if (FRAME_FONTSET (f) == fontset)
5012 /* This fontset is already set in frame F. There's nothing more
5013 to do. */
5014 return fontset_name (fontset);
5016 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5018 if (!STRINGP (result))
5019 /* Can't load ASCII font. */
5020 return Qnil;
5022 /* Since x_new_font doesn't update any fontset information, do it now. */
5023 FRAME_FONTSET(f) = fontset;
5025 return build_string (fontsetname);
5029 /***********************************************************************
5030 TODO: W32 Input Methods
5031 ***********************************************************************/
5032 /* Listing missing functions from xterm.c helps diff stay in step.
5034 xim_destroy_callback (xim, client_data, call_data)
5035 xim_open_dpy (dpyinfo, resource_name)
5036 struct xim_inst_t
5037 xim_instantiate_callback (display, client_data, call_data)
5038 xim_initialize (dpyinfo, resource_name)
5039 xim_close_dpy (dpyinfo)
5044 void
5045 mac_get_window_bounds (f, inner, outer)
5046 struct frame *f;
5047 Rect *inner, *outer;
5049 #if TARGET_API_MAC_CARBON
5050 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5051 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5052 #else /* not TARGET_API_MAC_CARBON */
5053 RgnHandle region = NewRgn ();
5055 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5056 *inner = (*region)->rgnBBox;
5057 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5058 *outer = (*region)->rgnBBox;
5059 DisposeRgn (region);
5060 #endif /* not TARGET_API_MAC_CARBON */
5064 /* Calculate the absolute position in frame F
5065 from its current recorded position values and gravity. */
5067 void
5068 x_calc_absolute_position (f)
5069 struct frame *f;
5071 int width_diff = 0, height_diff = 0;
5072 int flags = f->size_hint_flags;
5073 Rect inner, outer;
5075 /* We have nothing to do if the current position
5076 is already for the top-left corner. */
5077 if (! ((flags & XNegative) || (flags & YNegative)))
5078 return;
5080 /* Find the offsets of the outside upper-left corner of
5081 the inner window, with respect to the outer window. */
5082 mac_get_window_bounds (f, &inner, &outer);
5084 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5085 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5087 /* Treat negative positions as relative to the leftmost bottommost
5088 position that fits on the screen. */
5089 if (flags & XNegative)
5090 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5091 - width_diff
5092 - FRAME_PIXEL_WIDTH (f)
5093 + f->left_pos);
5095 if (flags & YNegative)
5096 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5097 - height_diff
5098 - FRAME_PIXEL_HEIGHT (f)
5099 + f->top_pos);
5101 /* The left_pos and top_pos
5102 are now relative to the top and left screen edges,
5103 so the flags should correspond. */
5104 f->size_hint_flags &= ~ (XNegative | YNegative);
5107 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5108 to really change the position, and 0 when calling from
5109 x_make_frame_visible (in that case, XOFF and YOFF are the current
5110 position values). It is -1 when calling from x_set_frame_parameters,
5111 which means, do adjust for borders but don't change the gravity. */
5113 void
5114 x_set_offset (f, xoff, yoff, change_gravity)
5115 struct frame *f;
5116 register int xoff, yoff;
5117 int change_gravity;
5119 if (change_gravity > 0)
5121 f->top_pos = yoff;
5122 f->left_pos = xoff;
5123 f->size_hint_flags &= ~ (XNegative | YNegative);
5124 if (xoff < 0)
5125 f->size_hint_flags |= XNegative;
5126 if (yoff < 0)
5127 f->size_hint_flags |= YNegative;
5128 f->win_gravity = NorthWestGravity;
5130 x_calc_absolute_position (f);
5132 BLOCK_INPUT;
5133 x_wm_set_size_hint (f, (long) 0, 0);
5135 #if TARGET_API_MAC_CARBON
5136 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5137 /* If the title bar is completely outside the screen, adjust the
5138 position. */
5139 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5140 kWindowConstrainMoveRegardlessOfFit
5141 | kWindowConstrainAllowPartial, NULL, NULL);
5142 x_real_positions (f, &f->left_pos, &f->top_pos);
5143 #else
5145 Rect inner, outer, screen_rect, dummy;
5146 RgnHandle region = NewRgn ();
5148 mac_get_window_bounds (f, &inner, &outer);
5149 f->x_pixels_diff = inner.left - outer.left;
5150 f->y_pixels_diff = inner.top - outer.top;
5151 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5152 f->top_pos + f->y_pixels_diff, false);
5154 /* If the title bar is completely outside the screen, adjust the
5155 position. The variable `outer' holds the title bar rectangle.
5156 The variable `inner' holds slightly smaller one than `outer',
5157 so that the calculation of overlapping may not become too
5158 strict. */
5159 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5160 outer = (*region)->rgnBBox;
5161 DisposeRgn (region);
5162 inner = outer;
5163 InsetRect (&inner, 8, 8);
5164 screen_rect = qd.screenBits.bounds;
5165 screen_rect.top += GetMBarHeight ();
5167 if (!SectRect (&inner, &screen_rect, &dummy))
5169 if (inner.right <= screen_rect.left)
5170 f->left_pos = screen_rect.left;
5171 else if (inner.left >= screen_rect.right)
5172 f->left_pos = screen_rect.right - (outer.right - outer.left);
5174 if (inner.bottom <= screen_rect.top)
5175 f->top_pos = screen_rect.top;
5176 else if (inner.top >= screen_rect.bottom)
5177 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5179 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5180 f->top_pos + f->y_pixels_diff, false);
5183 #endif
5185 UNBLOCK_INPUT;
5188 /* Call this to change the size of frame F's x-window.
5189 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5190 for this size change and subsequent size changes.
5191 Otherwise we leave the window gravity unchanged. */
5193 void
5194 x_set_window_size (f, change_gravity, cols, rows)
5195 struct frame *f;
5196 int change_gravity;
5197 int cols, rows;
5199 int pixelwidth, pixelheight;
5201 BLOCK_INPUT;
5203 check_frame_size (f, &rows, &cols);
5204 f->scroll_bar_actual_width
5205 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5207 compute_fringe_widths (f, 0);
5209 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5210 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5212 f->win_gravity = NorthWestGravity;
5213 x_wm_set_size_hint (f, (long) 0, 0);
5215 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5217 /* Now, strictly speaking, we can't be sure that this is accurate,
5218 but the window manager will get around to dealing with the size
5219 change request eventually, and we'll hear how it went when the
5220 ConfigureNotify event gets here.
5222 We could just not bother storing any of this information here,
5223 and let the ConfigureNotify event set everything up, but that
5224 might be kind of confusing to the Lisp code, since size changes
5225 wouldn't be reported in the frame parameters until some random
5226 point in the future when the ConfigureNotify event arrives.
5228 We pass 1 for DELAY since we can't run Lisp code inside of
5229 a BLOCK_INPUT. */
5230 change_frame_size (f, rows, cols, 0, 1, 0);
5231 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5232 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5234 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5235 receive in the ConfigureNotify event; if we get what we asked
5236 for, then the event won't cause the screen to become garbaged, so
5237 we have to make sure to do it here. */
5238 SET_FRAME_GARBAGED (f);
5240 XFlush (FRAME_X_DISPLAY (f));
5242 /* If cursor was outside the new size, mark it as off. */
5243 mark_window_cursors_off (XWINDOW (f->root_window));
5245 /* Clear out any recollection of where the mouse highlighting was,
5246 since it might be in a place that's outside the new frame size.
5247 Actually checking whether it is outside is a pain in the neck,
5248 so don't try--just let the highlighting be done afresh with new size. */
5249 cancel_mouse_face (f);
5251 UNBLOCK_INPUT;
5254 /* Mouse warping. */
5256 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5258 void
5259 x_set_mouse_position (f, x, y)
5260 struct frame *f;
5261 int x, y;
5263 int pix_x, pix_y;
5265 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5266 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5268 if (pix_x < 0) pix_x = 0;
5269 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5271 if (pix_y < 0) pix_y = 0;
5272 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5274 x_set_mouse_pixel_position (f, pix_x, pix_y);
5277 void
5278 x_set_mouse_pixel_position (f, pix_x, pix_y)
5279 struct frame *f;
5280 int pix_x, pix_y;
5282 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5283 BLOCK_INPUT;
5285 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5286 0, 0, 0, 0, pix_x, pix_y);
5287 UNBLOCK_INPUT;
5288 #endif
5292 /* focus shifting, raising and lowering. */
5294 void
5295 x_focus_on_frame (f)
5296 struct frame *f;
5298 #if 0 /* This proves to be unpleasant. */
5299 x_raise_frame (f);
5300 #endif
5301 #if 0
5302 /* I don't think that the ICCCM allows programs to do things like this
5303 without the interaction of the window manager. Whatever you end up
5304 doing with this code, do it to x_unfocus_frame too. */
5305 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5306 RevertToPointerRoot, CurrentTime);
5307 #endif /* ! 0 */
5310 void
5311 x_unfocus_frame (f)
5312 struct frame *f;
5316 /* Raise frame F. */
5317 void
5318 x_raise_frame (f)
5319 struct frame *f;
5321 if (f->async_visible)
5323 BLOCK_INPUT;
5324 SelectWindow (FRAME_MAC_WINDOW (f));
5325 UNBLOCK_INPUT;
5329 /* Lower frame F. */
5330 void
5331 x_lower_frame (f)
5332 struct frame *f;
5334 if (f->async_visible)
5336 BLOCK_INPUT;
5337 SendBehind (FRAME_MAC_WINDOW (f), nil);
5338 UNBLOCK_INPUT;
5342 static void
5343 XTframe_raise_lower (f, raise_flag)
5344 FRAME_PTR f;
5345 int raise_flag;
5347 if (raise_flag)
5348 x_raise_frame (f);
5349 else
5350 x_lower_frame (f);
5353 /* Change of visibility. */
5355 /* This tries to wait until the frame is really visible.
5356 However, if the window manager asks the user where to position
5357 the frame, this will return before the user finishes doing that.
5358 The frame will not actually be visible at that time,
5359 but it will become visible later when the window manager
5360 finishes with it. */
5362 void
5363 x_make_frame_visible (f)
5364 struct frame *f;
5366 Lisp_Object type;
5367 int original_top, original_left;
5369 BLOCK_INPUT;
5371 if (! FRAME_VISIBLE_P (f))
5373 /* We test FRAME_GARBAGED_P here to make sure we don't
5374 call x_set_offset a second time
5375 if we get to x_make_frame_visible a second time
5376 before the window gets really visible. */
5377 if (! FRAME_ICONIFIED_P (f)
5378 && ! f->output_data.mac->asked_for_visible)
5379 x_set_offset (f, f->left_pos, f->top_pos, 0);
5381 f->output_data.mac->asked_for_visible = 1;
5383 #if TARGET_API_MAC_CARBON
5384 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5386 struct frame *sf = SELECTED_FRAME ();
5387 if (!FRAME_MAC_P (sf))
5388 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5389 kWindowCenterOnMainScreen);
5390 else
5391 RepositionWindow (FRAME_MAC_WINDOW (f),
5392 FRAME_MAC_WINDOW (sf),
5393 #ifdef MAC_OS_X_VERSION_10_2
5394 kWindowCascadeStartAtParentWindowScreen
5395 #else
5396 kWindowCascadeOnParentWindowScreen
5397 #endif
5399 x_real_positions (f, &f->left_pos, &f->top_pos);
5401 #endif
5402 ShowWindow (FRAME_MAC_WINDOW (f));
5405 XFlush (FRAME_MAC_DISPLAY (f));
5407 /* Synchronize to ensure Emacs knows the frame is visible
5408 before we do anything else. We do this loop with input not blocked
5409 so that incoming events are handled. */
5411 Lisp_Object frame;
5412 int count;
5414 /* This must come after we set COUNT. */
5415 UNBLOCK_INPUT;
5417 XSETFRAME (frame, f);
5419 /* Wait until the frame is visible. Process X events until a
5420 MapNotify event has been seen, or until we think we won't get a
5421 MapNotify at all.. */
5422 for (count = input_signal_count + 10;
5423 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5425 /* Force processing of queued events. */
5426 x_sync (f);
5428 /* Machines that do polling rather than SIGIO have been
5429 observed to go into a busy-wait here. So we'll fake an
5430 alarm signal to let the handler know that there's something
5431 to be read. We used to raise a real alarm, but it seems
5432 that the handler isn't always enabled here. This is
5433 probably a bug. */
5434 if (input_polling_used ())
5436 /* It could be confusing if a real alarm arrives while
5437 processing the fake one. Turn it off and let the
5438 handler reset it. */
5439 extern void poll_for_input_1 P_ ((void));
5440 int old_poll_suppress_count = poll_suppress_count;
5441 poll_suppress_count = 1;
5442 poll_for_input_1 ();
5443 poll_suppress_count = old_poll_suppress_count;
5446 /* See if a MapNotify event has been processed. */
5447 FRAME_SAMPLE_VISIBILITY (f);
5452 /* Change from mapped state to withdrawn state. */
5454 /* Make the frame visible (mapped and not iconified). */
5456 void
5457 x_make_frame_invisible (f)
5458 struct frame *f;
5460 /* Don't keep the highlight on an invisible frame. */
5461 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5462 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5464 BLOCK_INPUT;
5466 HideWindow (FRAME_MAC_WINDOW (f));
5468 /* We can't distinguish this from iconification
5469 just by the event that we get from the server.
5470 So we can't win using the usual strategy of letting
5471 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5472 and synchronize with the server to make sure we agree. */
5473 f->visible = 0;
5474 FRAME_ICONIFIED_P (f) = 0;
5475 f->async_visible = 0;
5476 f->async_iconified = 0;
5478 UNBLOCK_INPUT;
5481 /* Change window state from mapped to iconified. */
5483 void
5484 x_iconify_frame (f)
5485 struct frame *f;
5487 /* Don't keep the highlight on an invisible frame. */
5488 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5489 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5491 #if 0
5492 /* Review: Since window is still visible in dock, still allow updates? */
5493 if (f->async_iconified)
5494 return;
5495 #endif
5497 BLOCK_INPUT;
5499 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5501 UNBLOCK_INPUT;
5505 /* Free X resources of frame F. */
5507 void
5508 x_free_frame_resources (f)
5509 struct frame *f;
5511 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5512 WindowPtr wp = FRAME_MAC_WINDOW (f);
5514 BLOCK_INPUT;
5516 DisposeWindow (wp);
5517 if (wp == tip_window)
5518 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5519 closed' event. So we reset tip_window here. */
5520 tip_window = NULL;
5522 free_frame_menubar (f);
5524 if (FRAME_FACE_CACHE (f))
5525 free_frame_faces (f);
5527 x_free_gcs (f);
5529 if (FRAME_SIZE_HINTS (f))
5530 xfree (FRAME_SIZE_HINTS (f));
5532 xfree (f->output_data.mac);
5533 f->output_data.mac = NULL;
5535 if (f == dpyinfo->x_focus_frame)
5536 dpyinfo->x_focus_frame = 0;
5537 if (f == dpyinfo->x_focus_event_frame)
5538 dpyinfo->x_focus_event_frame = 0;
5539 if (f == dpyinfo->x_highlight_frame)
5540 dpyinfo->x_highlight_frame = 0;
5542 if (f == dpyinfo->mouse_face_mouse_frame)
5544 dpyinfo->mouse_face_beg_row
5545 = dpyinfo->mouse_face_beg_col = -1;
5546 dpyinfo->mouse_face_end_row
5547 = dpyinfo->mouse_face_end_col = -1;
5548 dpyinfo->mouse_face_window = Qnil;
5549 dpyinfo->mouse_face_deferred_gc = 0;
5550 dpyinfo->mouse_face_mouse_frame = 0;
5553 UNBLOCK_INPUT;
5557 /* Destroy the X window of frame F. */
5559 void
5560 x_destroy_window (f)
5561 struct frame *f;
5563 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5565 x_free_frame_resources (f);
5567 dpyinfo->reference_count--;
5571 /* Setting window manager hints. */
5573 /* Set the normal size hints for the window manager, for frame F.
5574 FLAGS is the flags word to use--or 0 meaning preserve the flags
5575 that the window now has.
5576 If USER_POSITION is nonzero, we set the USPosition
5577 flag (this is useful when FLAGS is 0). */
5578 void
5579 x_wm_set_size_hint (f, flags, user_position)
5580 struct frame *f;
5581 long flags;
5582 int user_position;
5584 int base_width, base_height, width_inc, height_inc;
5585 int min_rows = 0, min_cols = 0;
5586 XSizeHints *size_hints;
5588 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5589 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5590 width_inc = FRAME_COLUMN_WIDTH (f);
5591 height_inc = FRAME_LINE_HEIGHT (f);
5593 check_frame_size (f, &min_rows, &min_cols);
5595 size_hints = FRAME_SIZE_HINTS (f);
5596 if (size_hints == NULL)
5598 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
5599 bzero (size_hints, sizeof (XSizeHints));
5602 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
5603 size_hints->width_inc = width_inc;
5604 size_hints->height_inc = height_inc;
5605 size_hints->min_width = base_width + min_cols * width_inc;
5606 size_hints->min_height = base_height + min_rows * height_inc;
5607 size_hints->base_width = base_width;
5608 size_hints->base_height = base_height;
5610 if (flags)
5611 size_hints->flags = flags;
5612 else if (user_position)
5614 size_hints->flags &= ~ PPosition;
5615 size_hints->flags |= USPosition;
5619 #if 0 /* MAC_TODO: hide application instead of iconify? */
5620 /* Used for IconicState or NormalState */
5622 void
5623 x_wm_set_window_state (f, state)
5624 struct frame *f;
5625 int state;
5627 #ifdef USE_X_TOOLKIT
5628 Arg al[1];
5630 XtSetArg (al[0], XtNinitialState, state);
5631 XtSetValues (f->output_data.x->widget, al, 1);
5632 #else /* not USE_X_TOOLKIT */
5633 Window window = FRAME_X_WINDOW (f);
5635 f->output_data.x->wm_hints.flags |= StateHint;
5636 f->output_data.x->wm_hints.initial_state = state;
5638 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5639 #endif /* not USE_X_TOOLKIT */
5642 void
5643 x_wm_set_icon_pixmap (f, pixmap_id)
5644 struct frame *f;
5645 int pixmap_id;
5647 Pixmap icon_pixmap;
5649 #ifndef USE_X_TOOLKIT
5650 Window window = FRAME_X_WINDOW (f);
5651 #endif
5653 if (pixmap_id > 0)
5655 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5656 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5658 else
5660 /* It seems there is no way to turn off use of an icon pixmap.
5661 The following line does it, only if no icon has yet been created,
5662 for some window managers. But with mwm it crashes.
5663 Some people say it should clear the IconPixmapHint bit in this case,
5664 but that doesn't work, and the X consortium said it isn't the
5665 right thing at all. Since there is no way to win,
5666 best to explicitly give up. */
5667 #if 0
5668 f->output_data.x->wm_hints.icon_pixmap = None;
5669 #else
5670 return;
5671 #endif
5674 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5677 Arg al[1];
5678 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5679 XtSetValues (f->output_data.x->widget, al, 1);
5682 #else /* not USE_X_TOOLKIT */
5684 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5685 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5687 #endif /* not USE_X_TOOLKIT */
5690 #endif /* MAC_TODO */
5692 void
5693 x_wm_set_icon_position (f, icon_x, icon_y)
5694 struct frame *f;
5695 int icon_x, icon_y;
5697 #if 0 /* MAC_TODO: no icons on Mac */
5698 #ifdef USE_X_TOOLKIT
5699 Window window = XtWindow (f->output_data.x->widget);
5700 #else
5701 Window window = FRAME_X_WINDOW (f);
5702 #endif
5704 f->output_data.x->wm_hints.flags |= IconPositionHint;
5705 f->output_data.x->wm_hints.icon_x = icon_x;
5706 f->output_data.x->wm_hints.icon_y = icon_y;
5708 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5709 #endif /* MAC_TODO */
5713 /***********************************************************************
5714 Fonts
5715 ***********************************************************************/
5717 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5719 struct font_info *
5720 x_get_font_info (f, font_idx)
5721 FRAME_PTR f;
5722 int font_idx;
5724 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5727 /* the global font name table */
5728 char **font_name_table = NULL;
5729 int font_name_table_size = 0;
5730 int font_name_count = 0;
5732 #if 0
5733 /* compare two strings ignoring case */
5734 static int
5735 stricmp (const char *s, const char *t)
5737 for ( ; tolower (*s) == tolower (*t); s++, t++)
5738 if (*s == '\0')
5739 return 0;
5740 return tolower (*s) - tolower (*t);
5743 /* compare two strings ignoring case and handling wildcard */
5744 static int
5745 wildstrieq (char *s1, char *s2)
5747 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5748 return true;
5750 return stricmp (s1, s2) == 0;
5753 /* Assume parameter 1 is fully qualified, no wildcards. */
5754 static int
5755 mac_font_pattern_match (fontname, pattern)
5756 char * fontname;
5757 char * pattern;
5759 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5760 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5761 char *ptr;
5763 /* Copy fontname so we can modify it during comparison. */
5764 strcpy (font_name_copy, fontname);
5766 ptr = regex;
5767 *ptr++ = '^';
5769 /* Turn pattern into a regexp and do a regexp match. */
5770 for (; *pattern; pattern++)
5772 if (*pattern == '?')
5773 *ptr++ = '.';
5774 else if (*pattern == '*')
5776 *ptr++ = '.';
5777 *ptr++ = '*';
5779 else
5780 *ptr++ = *pattern;
5782 *ptr = '$';
5783 *(ptr + 1) = '\0';
5785 return (fast_c_string_match_ignore_case (build_string (regex),
5786 font_name_copy) >= 0);
5789 /* Two font specs are considered to match if their foundry, family,
5790 weight, slant, and charset match. */
5791 static int
5792 mac_font_match (char *mf, char *xf)
5794 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5795 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5797 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5798 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5799 return mac_font_pattern_match (mf, xf);
5801 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5802 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5803 return mac_font_pattern_match (mf, xf);
5805 return (wildstrieq (m_foundry, x_foundry)
5806 && wildstrieq (m_family, x_family)
5807 && wildstrieq (m_weight, x_weight)
5808 && wildstrieq (m_slant, x_slant)
5809 && wildstrieq (m_charset, x_charset))
5810 || mac_font_pattern_match (mf, xf);
5812 #endif
5814 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5816 static void
5817 decode_mac_font_name (name, size, scriptcode)
5818 char *name;
5819 int size;
5820 #if TARGET_API_MAC_CARBON
5821 int scriptcode;
5822 #else
5823 short scriptcode;
5824 #endif
5826 Lisp_Object coding_system;
5827 struct coding_system coding;
5828 char *buf;
5830 switch (scriptcode)
5832 case smTradChinese:
5833 coding_system = Qbig5;
5834 break;
5835 case smSimpChinese:
5836 coding_system = Qcn_gb;
5837 break;
5838 case smJapanese:
5839 coding_system = Qsjis;
5840 break;
5841 case smKorean:
5842 coding_system = Qeuc_kr;
5843 break;
5844 default:
5845 return;
5848 setup_coding_system (coding_system, &coding);
5849 coding.src_multibyte = 0;
5850 coding.dst_multibyte = 1;
5851 coding.mode |= CODING_MODE_LAST_BLOCK;
5852 coding.composing = COMPOSITION_DISABLED;
5853 buf = (char *) alloca (size);
5855 decode_coding (&coding, name, buf, strlen (name), size - 1);
5856 bcopy (buf, name, coding.produced);
5857 name[coding.produced] = '\0';
5861 static char *
5862 mac_to_x_fontname (name, size, style, scriptcode, encoding_base)
5863 char *name;
5864 int size;
5865 Style style;
5866 #if TARGET_API_MAC_CARBON
5867 int scriptcode;
5868 #else
5869 short scriptcode;
5870 #endif
5872 char foundry[32], family[32], cs[32];
5873 char xf[256], *result, *p;
5875 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5877 strcpy(foundry, "Apple");
5878 strcpy(family, name);
5880 switch (scriptcode)
5882 case smTradChinese: /* == kTextEncodingMacChineseTrad */
5883 strcpy(cs, "big5-0");
5884 break;
5885 case smSimpChinese: /* == kTextEncodingMacChineseSimp */
5886 strcpy(cs, "gb2312.1980-0");
5887 break;
5888 case smJapanese: /* == kTextEncodingMacJapanese */
5889 strcpy(cs, "jisx0208.1983-sjis");
5890 break;
5891 case -smJapanese:
5892 /* Each Apple Japanese font is entered into the font table
5893 twice: once as a jisx0208.1983-sjis font and once as a
5894 jisx0201.1976-0 font. The latter can be used to display
5895 the ascii charset and katakana-jisx0201 charset. A
5896 negative script code signals that the name of this latter
5897 font is being built. */
5898 strcpy(cs, "jisx0201.1976-0");
5899 break;
5900 case smKorean: /* == kTextEncodingMacKorean */
5901 strcpy(cs, "ksc5601.1989-0");
5902 break;
5903 #if TARGET_API_MAC_CARBON
5904 case kTextEncodingMacCyrillic:
5905 strcpy(cs, "mac-cyrillic");
5906 break;
5907 case kTextEncodingMacCentralEurRoman:
5908 strcpy(cs, "mac-centraleurroman");
5909 break;
5910 case kTextEncodingMacSymbol:
5911 case kTextEncodingMacDingbats:
5912 strcpy(cs, "adobe-fontspecific");
5913 break;
5914 #endif
5915 default:
5916 strcpy(cs, "mac-roman");
5917 break;
5921 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5922 foundry, family, style & bold ? "bold" : "medium",
5923 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5925 result = (char *) xmalloc (strlen (xf) + 1);
5926 strcpy (result, xf);
5927 for (p = result; *p; p++)
5928 *p = tolower(*p);
5929 return result;
5933 /* Convert an X font spec to the corresponding mac font name, which
5934 can then be passed to GetFNum after conversion to a Pascal string.
5935 For ordinary Mac fonts, this should just be their names, like
5936 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5937 collection contain their charset designation in their names, like
5938 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5939 names are handled accordingly. */
5940 static void
5941 x_font_name_to_mac_font_name (char *xf, char *mf)
5943 char foundry[32], family[32], weight[20], slant[2], cs[32];
5944 Lisp_Object coding_system = Qnil;
5945 struct coding_system coding;
5947 strcpy (mf, "");
5949 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5950 foundry, family, weight, slant, cs) != 5 &&
5951 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5952 foundry, family, weight, slant, cs) != 5)
5953 return;
5955 if (strcmp (cs, "big5-0") == 0)
5956 coding_system = Qbig5;
5957 else if (strcmp (cs, "gb2312.1980-0") == 0)
5958 coding_system = Qcn_gb;
5959 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
5960 || strcmp (cs, "jisx0201.1976-0") == 0)
5961 coding_system = Qsjis;
5962 else if (strcmp (cs, "ksc5601.1989-0") == 0)
5963 coding_system = Qeuc_kr;
5964 else if (strcmp (cs, "mac-roman") == 0
5965 || strcmp (cs, "mac-cyrillic") == 0
5966 || strcmp (cs, "mac-centraleurroman") == 0
5967 || strcmp (cs, "adobe-fontspecific") == 0)
5968 strcpy (mf, family);
5969 else
5970 sprintf (mf, "%s-%s-%s", foundry, family, cs);
5972 if (!NILP (coding_system))
5974 setup_coding_system (coding_system, &coding);
5975 coding.src_multibyte = 1;
5976 coding.dst_multibyte = 1;
5977 coding.mode |= CODING_MODE_LAST_BLOCK;
5978 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
5979 mf[coding.produced] = '\0';
5984 static void
5985 add_font_name_table_entry (char *font_name)
5987 if (font_name_table_size == 0)
5989 font_name_table_size = 16;
5990 font_name_table = (char **)
5991 xmalloc (font_name_table_size * sizeof (char *));
5993 else if (font_name_count + 1 >= font_name_table_size)
5995 font_name_table_size += 16;
5996 font_name_table = (char **)
5997 xrealloc (font_name_table,
5998 font_name_table_size * sizeof (char *));
6001 font_name_table[font_name_count++] = font_name;
6004 /* Sets up the table font_name_table to contain the list of all fonts
6005 in the system the first time the table is used so that the Resource
6006 Manager need not be accessed every time this information is
6007 needed. */
6009 static void
6010 init_font_name_table ()
6012 #if TARGET_API_MAC_CARBON
6013 SInt32 sv;
6015 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6017 FMFontFamilyIterator ffi;
6018 FMFontFamilyInstanceIterator ffii;
6019 FMFontFamily ff;
6021 /* Create a dummy instance iterator here to avoid creating and
6022 destroying it in the loop. */
6023 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6024 return;
6025 /* Create an iterator to enumerate the font families. */
6026 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6027 != noErr)
6029 FMDisposeFontFamilyInstanceIterator (&ffii);
6030 return;
6033 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6035 Str255 name;
6036 FMFont font;
6037 FMFontStyle style;
6038 FMFontSize size;
6039 TextEncoding encoding;
6040 TextEncodingBase sc;
6042 if (FMGetFontFamilyName (ff, name) != noErr)
6043 break;
6044 p2cstr (name);
6045 if (*name == '.')
6046 continue;
6048 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6049 break;
6050 sc = GetTextEncodingBase (encoding);
6051 decode_mac_font_name (name, sizeof (name), sc);
6053 /* Point the instance iterator at the current font family. */
6054 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6055 break;
6057 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6058 == noErr)
6060 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6061 contained in Apple Japanese (SJIS) font. */
6062 again:
6063 if (size == 0)
6065 add_font_name_table_entry (mac_to_x_fontname (name, size,
6066 style, sc));
6067 add_font_name_table_entry (mac_to_x_fontname (name, size,
6068 italic, sc));
6069 add_font_name_table_entry (mac_to_x_fontname (name, size,
6070 bold, sc));
6071 add_font_name_table_entry (mac_to_x_fontname (name, size,
6072 italic | bold,
6073 sc));
6075 else
6076 add_font_name_table_entry (mac_to_x_fontname (name, size,
6077 style, sc));
6078 if (sc == smJapanese)
6080 sc = -smJapanese;
6081 goto again;
6083 else if (sc == -smJapanese)
6084 sc = smJapanese;
6088 /* Dispose of the iterators. */
6089 FMDisposeFontFamilyIterator (&ffi);
6090 FMDisposeFontFamilyInstanceIterator (&ffii);
6092 else
6094 #endif /* TARGET_API_MAC_CARBON */
6095 GrafPtr port;
6096 SInt16 fontnum, old_fontnum;
6097 int num_mac_fonts = CountResources('FOND');
6098 int i, j;
6099 Handle font_handle, font_handle_2;
6100 short id, scriptcode;
6101 ResType type;
6102 Str32 name;
6103 struct FontAssoc *fat;
6104 struct AsscEntry *assc_entry;
6106 GetPort (&port); /* save the current font number used */
6107 #if TARGET_API_MAC_CARBON
6108 old_fontnum = GetPortTextFont (port);
6109 #else
6110 old_fontnum = port->txFont;
6111 #endif
6113 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6115 font_handle = GetIndResource ('FOND', i);
6116 if (!font_handle)
6117 continue;
6119 GetResInfo (font_handle, &id, &type, name);
6120 GetFNum (name, &fontnum);
6121 p2cstr (name);
6122 if (fontnum == 0)
6123 continue;
6125 TextFont (fontnum);
6126 scriptcode = FontToScript (fontnum);
6127 decode_mac_font_name (name, sizeof (name), scriptcode);
6130 HLock (font_handle);
6132 if (GetResourceSizeOnDisk (font_handle)
6133 >= sizeof (struct FamRec))
6135 fat = (struct FontAssoc *) (*font_handle
6136 + sizeof (struct FamRec));
6137 assc_entry
6138 = (struct AsscEntry *) (*font_handle
6139 + sizeof (struct FamRec)
6140 + sizeof (struct FontAssoc));
6142 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6144 if (font_name_table_size == 0)
6146 font_name_table_size = 16;
6147 font_name_table = (char **)
6148 xmalloc (font_name_table_size * sizeof (char *));
6150 else if (font_name_count >= font_name_table_size)
6152 font_name_table_size += 16;
6153 font_name_table = (char **)
6154 xrealloc (font_name_table,
6155 font_name_table_size * sizeof (char *));
6157 font_name_table[font_name_count++]
6158 = mac_to_x_fontname (name,
6159 assc_entry->fontSize,
6160 assc_entry->fontStyle,
6161 scriptcode);
6162 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6163 parts are contained in Apple Japanese (SJIS)
6164 font. */
6165 if (smJapanese == scriptcode)
6167 font_name_table[font_name_count++]
6168 = mac_to_x_fontname (name,
6169 assc_entry->fontSize,
6170 assc_entry->fontStyle,
6171 -smJapanese);
6176 HUnlock (font_handle);
6177 font_handle_2 = GetNextFOND (font_handle);
6178 ReleaseResource (font_handle);
6179 font_handle = font_handle_2;
6181 while (ResError () == noErr && font_handle);
6184 TextFont (old_fontnum);
6185 #if TARGET_API_MAC_CARBON
6187 #endif /* TARGET_API_MAC_CARBON */
6191 void
6192 mac_clear_font_name_table ()
6194 int i;
6196 for (i = 0; i < font_name_count; i++)
6197 xfree (font_name_table[i]);
6198 xfree (font_name_table);
6199 font_name_table = NULL;
6200 font_name_table_size = font_name_count = 0;
6204 enum xlfd_scalable_field_index
6206 XLFD_SCL_PIXEL_SIZE,
6207 XLFD_SCL_POINT_SIZE,
6208 XLFD_SCL_AVGWIDTH,
6209 XLFD_SCL_LAST
6212 static int xlfd_scalable_fields[] =
6214 6, /* PIXEL_SIZE */
6215 7, /* POINT_SIZE */
6216 11, /* AVGWIDTH */
6220 static Lisp_Object
6221 mac_c_string_match (regexp, string, nonspecial, exact)
6222 Lisp_Object regexp;
6223 const char *string, *nonspecial;
6224 int exact;
6226 if (exact)
6228 if (strcmp (string, nonspecial) == 0)
6229 return build_string (string);
6231 else if (strstr (string, nonspecial))
6233 Lisp_Object str = build_string (string);
6235 if (fast_string_match (regexp, str) >= 0)
6236 return str;
6239 return Qnil;
6242 static Lisp_Object
6243 mac_do_list_fonts (pattern, maxnames)
6244 char *pattern;
6245 int maxnames;
6247 int i, n_fonts = 0;
6248 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6249 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6250 char scaled[256];
6251 char *ptr;
6252 int scl_val[XLFD_SCL_LAST], *field, *val;
6253 char *longest_start, *cur_start, *nonspecial;
6254 int longest_len, exact;
6256 if (font_name_table == NULL) /* Initialize when first used. */
6257 init_font_name_table ();
6259 for (i = 0; i < XLFD_SCL_LAST; i++)
6260 scl_val[i] = -1;
6262 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6263 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6264 fonts are scaled according to the specified size. */
6265 ptr = pattern;
6266 i = 0;
6267 field = xlfd_scalable_fields;
6268 val = scl_val;
6269 if (*ptr == '-')
6272 ptr++;
6273 if (i == *field)
6275 if ('1' <= *ptr && *ptr <= '9')
6277 *val = *ptr++ - '0';
6278 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6279 *val = *val * 10 + *ptr++ - '0';
6280 if (*ptr != '-')
6281 *val = -1;
6283 field++;
6284 val++;
6286 ptr = strchr (ptr, '-');
6287 i++;
6289 while (ptr && i < 14);
6291 if (i == 14 && ptr == NULL)
6293 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6295 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6296 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6298 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6300 scl_val[XLFD_SCL_POINT_SIZE] =
6301 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6303 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6305 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6306 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6309 else
6310 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6312 ptr = regex;
6313 *ptr++ = '^';
6315 longest_start = cur_start = ptr;
6316 longest_len = 0;
6317 exact = 1;
6319 /* Turn pattern into a regexp and do a regexp match. Also find the
6320 longest substring containing no special characters. */
6321 for (; *pattern; pattern++)
6323 if (*pattern == '?' || *pattern == '*')
6325 if (ptr - cur_start > longest_len)
6327 longest_start = cur_start;
6328 longest_len = ptr - cur_start;
6330 exact = 0;
6332 if (*pattern == '?')
6333 *ptr++ = '.';
6334 else /* if (*pattern == '*') */
6336 *ptr++ = '.';
6337 *ptr++ = '*';
6339 cur_start = ptr;
6341 else
6342 *ptr++ = tolower (*pattern);
6345 if (ptr - cur_start > longest_len)
6347 longest_start = cur_start;
6348 longest_len = ptr - cur_start;
6351 *ptr = '$';
6352 *(ptr + 1) = '\0';
6354 nonspecial = xmalloc (longest_len + 1);
6355 strncpy (nonspecial, longest_start, longest_len);
6356 nonspecial[longest_len] = '\0';
6358 pattern_regex = build_string (regex);
6360 for (i = 0; i < font_name_count; i++)
6362 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6363 nonspecial, exact);
6364 if (!NILP (fontname))
6366 font_list = Fcons (fontname, font_list);
6367 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6368 break;
6370 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6371 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6373 int former_len = ptr - font_name_table[i];
6375 memcpy (scaled, font_name_table[i], former_len);
6376 sprintf (scaled + former_len,
6377 "-%d-%d-75-75-m-%d-%s",
6378 scl_val[XLFD_SCL_PIXEL_SIZE],
6379 scl_val[XLFD_SCL_POINT_SIZE],
6380 scl_val[XLFD_SCL_AVGWIDTH],
6381 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6382 fontname = mac_c_string_match (pattern_regex, scaled,
6383 nonspecial, exact);
6384 if (!NILP (fontname))
6386 font_list = Fcons (fontname, font_list);
6387 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6388 break;
6393 xfree (nonspecial);
6395 return font_list;
6398 /* Return a list of at most MAXNAMES font specs matching the one in
6399 PATTERN. Cache matching fonts for patterns in
6400 dpyinfo->name_list_element to avoid looking them up again by
6401 calling mac_font_pattern_match (slow). Return as many matching
6402 fonts as possible if MAXNAMES = -1. */
6404 Lisp_Object
6405 x_list_fonts (struct frame *f,
6406 Lisp_Object pattern,
6407 int size,
6408 int maxnames)
6410 Lisp_Object newlist = Qnil, tem, key;
6411 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6413 if (dpyinfo)
6415 tem = XCDR (dpyinfo->name_list_element);
6416 key = Fcons (pattern, make_number (maxnames));
6418 newlist = Fassoc (key, tem);
6419 if (!NILP (newlist))
6421 newlist = Fcdr_safe (newlist);
6422 goto label_cached;
6426 BLOCK_INPUT;
6427 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6428 UNBLOCK_INPUT;
6430 /* MAC_TODO: add code for matching outline fonts here */
6432 if (dpyinfo)
6434 XSETCDR (dpyinfo->name_list_element,
6435 Fcons (Fcons (key, newlist),
6436 XCDR (dpyinfo->name_list_element)));
6438 label_cached:
6440 return newlist;
6444 #if GLYPH_DEBUG
6446 /* Check that FONT is valid on frame F. It is if it can be found in F's
6447 font table. */
6449 static void
6450 x_check_font (f, font)
6451 struct frame *f;
6452 XFontStruct *font;
6454 int i;
6455 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6457 xassert (font != NULL);
6459 for (i = 0; i < dpyinfo->n_fonts; i++)
6460 if (dpyinfo->font_table[i].name
6461 && font == dpyinfo->font_table[i].font)
6462 break;
6464 xassert (i < dpyinfo->n_fonts);
6467 #endif /* GLYPH_DEBUG != 0 */
6469 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6470 Note: There are (broken) X fonts out there with invalid XFontStruct
6471 min_bounds contents. For example, handa@etl.go.jp reports that
6472 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6473 have font->min_bounds.width == 0. */
6475 static INLINE void
6476 x_font_min_bounds (font, w, h)
6477 MacFontStruct *font;
6478 int *w, *h;
6480 *h = FONT_HEIGHT (font);
6481 *w = font->min_bounds.width;
6485 /* Compute the smallest character width and smallest font height over
6486 all fonts available on frame F. Set the members smallest_char_width
6487 and smallest_font_height in F's x_display_info structure to
6488 the values computed. Value is non-zero if smallest_font_height or
6489 smallest_char_width become smaller than they were before. */
6492 x_compute_min_glyph_bounds (f)
6493 struct frame *f;
6495 int i;
6496 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6497 MacFontStruct *font;
6498 int old_width = dpyinfo->smallest_char_width;
6499 int old_height = dpyinfo->smallest_font_height;
6501 dpyinfo->smallest_font_height = 100000;
6502 dpyinfo->smallest_char_width = 100000;
6504 for (i = 0; i < dpyinfo->n_fonts; ++i)
6505 if (dpyinfo->font_table[i].name)
6507 struct font_info *fontp = dpyinfo->font_table + i;
6508 int w, h;
6510 font = (MacFontStruct *) fontp->font;
6511 xassert (font != (MacFontStruct *) ~0);
6512 x_font_min_bounds (font, &w, &h);
6514 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6515 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6518 xassert (dpyinfo->smallest_char_width > 0
6519 && dpyinfo->smallest_font_height > 0);
6521 return (dpyinfo->n_fonts == 1
6522 || dpyinfo->smallest_char_width < old_width
6523 || dpyinfo->smallest_font_height < old_height);
6527 /* Determine whether given string is a fully-specified XLFD: all 14
6528 fields are present, none is '*'. */
6530 static int
6531 is_fully_specified_xlfd (char *p)
6533 int i;
6534 char *q;
6536 if (*p != '-')
6537 return 0;
6539 for (i = 0; i < 13; i++)
6541 q = strchr (p + 1, '-');
6542 if (q == NULL)
6543 return 0;
6544 if (q - p == 2 && *(p + 1) == '*')
6545 return 0;
6546 p = q;
6549 if (strchr (p + 1, '-') != NULL)
6550 return 0;
6552 if (*(p + 1) == '*' && *(p + 2) == '\0')
6553 return 0;
6555 return 1;
6559 const int kDefaultFontSize = 9;
6562 /* XLoadQueryFont creates and returns an internal representation for a
6563 font in a MacFontStruct struct. There is really no concept
6564 corresponding to "loading" a font on the Mac. But we check its
6565 existence and find the font number and all other information for it
6566 and store them in the returned MacFontStruct. */
6568 static MacFontStruct *
6569 XLoadQueryFont (Display *dpy, char *fontname)
6571 int i, size, is_two_byte_font, char_width;
6572 char *name;
6573 GrafPtr port;
6574 SInt16 old_fontnum, old_fontsize;
6575 Style old_fontface;
6576 Str32 mfontname;
6577 SInt16 fontnum;
6578 Style fontface = normal;
6579 MacFontStruct *font;
6580 FontInfo the_fontinfo;
6581 char s_weight[7], c_slant;
6583 if (is_fully_specified_xlfd (fontname))
6584 name = fontname;
6585 else
6587 Lisp_Object matched_fonts;
6589 matched_fonts = mac_do_list_fonts (fontname, 1);
6590 if (NILP (matched_fonts))
6591 return NULL;
6592 name = SDATA (XCAR (matched_fonts));
6595 GetPort (&port); /* save the current font number used */
6596 #if TARGET_API_MAC_CARBON
6597 old_fontnum = GetPortTextFont (port);
6598 old_fontsize = GetPortTextSize (port);
6599 old_fontface = GetPortTextFace (port);
6600 #else
6601 old_fontnum = port->txFont;
6602 old_fontsize = port->txSize;
6603 old_fontface = port->txFace;
6604 #endif
6606 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6607 size = kDefaultFontSize;
6609 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6610 if (strcmp (s_weight, "bold") == 0)
6611 fontface |= bold;
6613 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6614 if (c_slant == 'i')
6615 fontface |= italic;
6617 x_font_name_to_mac_font_name (name, mfontname);
6618 c2pstr (mfontname);
6619 GetFNum (mfontname, &fontnum);
6620 if (fontnum == 0)
6621 return NULL;
6623 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6625 font->fontname = (char *) xmalloc (strlen (name) + 1);
6626 bcopy (name, font->fontname, strlen (name) + 1);
6628 font->mac_fontnum = fontnum;
6629 font->mac_fontsize = size;
6630 font->mac_fontface = fontface;
6631 font->mac_scriptcode = FontToScript (fontnum);
6633 /* Apple Japanese (SJIS) font is listed as both
6634 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6635 (Roman script) in init_font_name_table (). The latter should be
6636 treated as a one-byte font. */
6638 char cs[32];
6640 if (sscanf (name,
6641 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6642 cs) == 1
6643 && 0 == strcmp (cs, "jisx0201.1976-0"))
6644 font->mac_scriptcode = smRoman;
6647 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6648 font->mac_scriptcode == smTradChinese ||
6649 font->mac_scriptcode == smSimpChinese ||
6650 font->mac_scriptcode == smKorean;
6652 TextFont (fontnum);
6653 TextSize (size);
6654 TextFace (fontface);
6656 GetFontInfo (&the_fontinfo);
6658 font->ascent = the_fontinfo.ascent;
6659 font->descent = the_fontinfo.descent;
6661 font->min_byte1 = 0;
6662 if (is_two_byte_font)
6663 font->max_byte1 = 1;
6664 else
6665 font->max_byte1 = 0;
6666 font->min_char_or_byte2 = 0x20;
6667 font->max_char_or_byte2 = 0xff;
6669 if (is_two_byte_font)
6671 /* Use the width of an "ideographic space" of that font because
6672 the_fontinfo.widMax returns the wrong width for some fonts. */
6673 switch (font->mac_scriptcode)
6675 case smJapanese:
6676 char_width = StringWidth("\p\x81\x40");
6677 break;
6678 case smTradChinese:
6679 char_width = StringWidth("\p\xa1\x40");
6680 break;
6681 case smSimpChinese:
6682 char_width = StringWidth("\p\xa1\xa1");
6683 break;
6684 case smKorean:
6685 char_width = StringWidth("\p\xa1\xa1");
6686 break;
6689 else
6690 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6691 returns 15 for 12-point Monaco! */
6692 char_width = CharWidth ('m');
6694 font->max_bounds.rbearing = char_width;
6695 font->max_bounds.lbearing = 0;
6696 font->max_bounds.width = char_width;
6697 font->max_bounds.ascent = the_fontinfo.ascent;
6698 font->max_bounds.descent = the_fontinfo.descent;
6700 font->min_bounds = font->max_bounds;
6702 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6703 font->per_char = NULL;
6704 else
6706 font->per_char = (XCharStruct *)
6707 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6709 int c, min_width, max_width;
6711 min_width = max_width = char_width;
6712 for (c = 0x20; c <= 0xff; c++)
6714 font->per_char[c - 0x20] = font->max_bounds;
6715 char_width = CharWidth (c);
6716 font->per_char[c - 0x20].width = char_width;
6717 font->per_char[c - 0x20].rbearing = char_width;
6718 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6719 character width of 0x7f. */
6720 if (char_width > 0)
6722 min_width = min (min_width, char_width);
6723 max_width = max (max_width, char_width);
6726 font->min_bounds.width = min_width;
6727 font->max_bounds.width = max_width;
6731 TextFont (old_fontnum); /* restore previous font number, size and face */
6732 TextSize (old_fontsize);
6733 TextFace (old_fontface);
6735 return font;
6739 void
6740 mac_unload_font (dpyinfo, font)
6741 struct mac_display_info *dpyinfo;
6742 XFontStruct *font;
6744 xfree (font->fontname);
6745 if (font->per_char)
6746 xfree (font->per_char);
6747 xfree (font);
6751 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6752 pointer to the structure font_info while allocating it dynamically.
6753 If SIZE is 0, load any size of font.
6754 If loading is failed, return NULL. */
6756 struct font_info *
6757 x_load_font (f, fontname, size)
6758 struct frame *f;
6759 register char *fontname;
6760 int size;
6762 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6763 Lisp_Object font_names;
6765 /* Get a list of all the fonts that match this name. Once we
6766 have a list of matching fonts, we compare them against the fonts
6767 we already have by comparing names. */
6768 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6770 if (!NILP (font_names))
6772 Lisp_Object tail;
6773 int i;
6775 for (i = 0; i < dpyinfo->n_fonts; i++)
6776 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6777 if (dpyinfo->font_table[i].name
6778 && (!strcmp (dpyinfo->font_table[i].name,
6779 SDATA (XCAR (tail)))
6780 || !strcmp (dpyinfo->font_table[i].full_name,
6781 SDATA (XCAR (tail)))))
6782 return (dpyinfo->font_table + i);
6785 /* Load the font and add it to the table. */
6787 char *full_name;
6788 struct MacFontStruct *font;
6789 struct font_info *fontp;
6790 unsigned long value;
6791 int i;
6793 /* If we have found fonts by x_list_font, load one of them. If
6794 not, we still try to load a font by the name given as FONTNAME
6795 because XListFonts (called in x_list_font) of some X server has
6796 a bug of not finding a font even if the font surely exists and
6797 is loadable by XLoadQueryFont. */
6798 if (size > 0 && !NILP (font_names))
6799 fontname = (char *) SDATA (XCAR (font_names));
6801 BLOCK_INPUT;
6802 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6803 UNBLOCK_INPUT;
6804 if (!font)
6805 return NULL;
6807 /* Find a free slot in the font table. */
6808 for (i = 0; i < dpyinfo->n_fonts; ++i)
6809 if (dpyinfo->font_table[i].name == NULL)
6810 break;
6812 /* If no free slot found, maybe enlarge the font table. */
6813 if (i == dpyinfo->n_fonts
6814 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6816 int sz;
6817 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6818 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6819 dpyinfo->font_table
6820 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6823 fontp = dpyinfo->font_table + i;
6824 if (i == dpyinfo->n_fonts)
6825 ++dpyinfo->n_fonts;
6827 /* Now fill in the slots of *FONTP. */
6828 BLOCK_INPUT;
6829 bzero (fontp, sizeof (*fontp));
6830 fontp->font = font;
6831 fontp->font_idx = i;
6832 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6833 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6835 if (font->min_bounds.width == font->max_bounds.width)
6837 /* Fixed width font. */
6838 fontp->average_width = fontp->space_width = font->min_bounds.width;
6840 else
6842 XChar2b char2b;
6843 XCharStruct *pcm;
6845 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
6846 pcm = mac_per_char_metric (font, &char2b, 0);
6847 if (pcm)
6848 fontp->space_width = pcm->width;
6849 else
6850 fontp->space_width = FONT_WIDTH (font);
6852 if (pcm)
6854 int width = pcm->width;
6855 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
6856 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
6857 width += pcm->width;
6858 fontp->average_width = width / 95;
6860 else
6861 fontp->average_width = FONT_WIDTH (font);
6864 fontp->full_name = fontp->name;
6866 fontp->size = font->max_bounds.width;
6867 fontp->height = FONT_HEIGHT (font);
6869 /* For some font, ascent and descent in max_bounds field is
6870 larger than the above value. */
6871 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6872 if (max_height > fontp->height)
6873 fontp->height = max_height;
6876 /* The slot `encoding' specifies how to map a character
6877 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6878 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6879 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6880 2:0xA020..0xFF7F). For the moment, we don't know which charset
6881 uses this font. So, we set information in fontp->encoding[1]
6882 which is never used by any charset. If mapping can't be
6883 decided, set FONT_ENCODING_NOT_DECIDED. */
6884 if (font->mac_scriptcode == smJapanese)
6885 fontp->encoding[1] = 4;
6886 else
6888 fontp->encoding[1]
6889 = (font->max_byte1 == 0
6890 /* 1-byte font */
6891 ? (font->min_char_or_byte2 < 0x80
6892 ? (font->max_char_or_byte2 < 0x80
6893 ? 0 /* 0x20..0x7F */
6894 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6895 : 1) /* 0xA0..0xFF */
6896 /* 2-byte font */
6897 : (font->min_byte1 < 0x80
6898 ? (font->max_byte1 < 0x80
6899 ? (font->min_char_or_byte2 < 0x80
6900 ? (font->max_char_or_byte2 < 0x80
6901 ? 0 /* 0x2020..0x7F7F */
6902 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6903 : 3) /* 0x20A0..0x7FFF */
6904 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6905 : (font->min_char_or_byte2 < 0x80
6906 ? (font->max_char_or_byte2 < 0x80
6907 ? 2 /* 0xA020..0xFF7F */
6908 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6909 : 1))); /* 0xA0A0..0xFFFF */
6912 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6913 fontp->baseline_offset
6914 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6915 ? (long) value : 0);
6916 fontp->relative_compose
6917 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6918 ? (long) value : 0);
6919 fontp->default_ascent
6920 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6921 ? (long) value : 0);
6922 #else
6923 fontp->baseline_offset = 0;
6924 fontp->relative_compose = 0;
6925 fontp->default_ascent = 0;
6926 #endif
6928 /* Set global flag fonts_changed_p to non-zero if the font loaded
6929 has a character with a smaller width than any other character
6930 before, or if the font loaded has a smalle>r height than any
6931 other font loaded before. If this happens, it will make a
6932 glyph matrix reallocation necessary. */
6933 fonts_changed_p = x_compute_min_glyph_bounds (f);
6934 UNBLOCK_INPUT;
6935 return fontp;
6940 /* Return a pointer to struct font_info of a font named FONTNAME for
6941 frame F. If no such font is loaded, return NULL. */
6943 struct font_info *
6944 x_query_font (f, fontname)
6945 struct frame *f;
6946 register char *fontname;
6948 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6949 int i;
6951 for (i = 0; i < dpyinfo->n_fonts; i++)
6952 if (dpyinfo->font_table[i].name
6953 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6954 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6955 return (dpyinfo->font_table + i);
6956 return NULL;
6960 /* Find a CCL program for a font specified by FONTP, and set the member
6961 `encoder' of the structure. */
6963 void
6964 x_find_ccl_program (fontp)
6965 struct font_info *fontp;
6967 Lisp_Object list, elt;
6969 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6971 elt = XCAR (list);
6972 if (CONSP (elt)
6973 && STRINGP (XCAR (elt))
6974 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6975 >= 0))
6976 break;
6978 if (! NILP (list))
6980 struct ccl_program *ccl
6981 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6983 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6984 xfree (ccl);
6985 else
6986 fontp->font_encoder = ccl;
6992 /* The Mac Event loop code */
6994 #ifndef MAC_OSX
6995 #include <Events.h>
6996 #include <Quickdraw.h>
6997 #include <Balloons.h>
6998 #include <Devices.h>
6999 #include <Fonts.h>
7000 #include <Gestalt.h>
7001 #include <Menus.h>
7002 #include <Processes.h>
7003 #include <Sound.h>
7004 #include <ToolUtils.h>
7005 #include <TextUtils.h>
7006 #include <Dialogs.h>
7007 #include <Script.h>
7008 #include <Types.h>
7009 #include <TextEncodingConverter.h>
7010 #include <Resources.h>
7012 #if __MWERKS__
7013 #include <unix.h>
7014 #endif
7015 #endif /* ! MAC_OSX */
7017 #define M_APPLE 128
7018 #define I_ABOUT 1
7020 #define WINDOW_RESOURCE 128
7021 #define TERM_WINDOW_RESOURCE 129
7023 #define DEFAULT_NUM_COLS 80
7025 #define MIN_DOC_SIZE 64
7026 #define MAX_DOC_SIZE 32767
7028 /* sleep time for WaitNextEvent */
7029 #define WNE_SLEEP_AT_SUSPEND 10
7030 #define WNE_SLEEP_AT_RESUME 1
7032 /* true when cannot handle any Mac OS events */
7033 static int handling_window_update = 0;
7035 #if 0
7036 /* the flag appl_is_suspended is used both for determining the sleep
7037 time to be passed to WaitNextEvent and whether the cursor should be
7038 drawn when updating the display. The cursor is turned off when
7039 Emacs is suspended. Redrawing it is unnecessary and what needs to
7040 be done depends on whether the cursor lies inside or outside the
7041 redraw region. So we might as well skip drawing it when Emacs is
7042 suspended. */
7043 static Boolean app_is_suspended = false;
7044 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
7045 #endif
7047 #define EXTRA_STACK_ALLOC (256 * 1024)
7049 #define ARGV_STRING_LIST_ID 129
7050 #define ABOUT_ALERT_ID 128
7051 #define RAM_TOO_LARGE_ALERT_ID 129
7053 Boolean terminate_flag = false;
7055 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7056 Lisp_Object Qreverse;
7058 /* True if using command key as meta key. */
7059 Lisp_Object Vmac_command_key_is_meta;
7061 /* Modifier associated with the option key, or nil for normal behavior. */
7062 Lisp_Object Vmac_option_modifier;
7064 /* True if the ctrl and meta keys should be reversed. */
7065 Lisp_Object Vmac_reverse_ctrl_meta;
7067 /* True if the option and command modifiers should be used to emulate
7068 a three button mouse */
7069 Lisp_Object Vmac_emulate_three_button_mouse;
7071 #if USE_CARBON_EVENTS
7072 /* True if the mouse wheel button (i.e. button 4) should map to
7073 mouse-2, instead of mouse-3. */
7074 Lisp_Object Vmac_wheel_button_is_mouse_2;
7076 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7077 for processing before Emacs sees it. */
7078 Lisp_Object Vmac_pass_command_to_system;
7080 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7081 for processing before Emacs sees it. */
7082 Lisp_Object Vmac_pass_control_to_system;
7083 #endif
7085 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7086 to this text encoding */
7087 int mac_keyboard_text_encoding;
7088 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7090 /* Set in term/mac-win.el to indicate that event loop can now generate
7091 drag and drop events. */
7092 Lisp_Object Qmac_ready_for_drag_n_drop;
7094 Lisp_Object drag_and_drop_file_list;
7096 Point saved_menu_event_location;
7098 #if !TARGET_API_MAC_CARBON
7099 /* Place holder for the default arrow cursor. */
7100 CursPtr arrow_cursor;
7101 #endif
7103 /* Apple Events */
7104 static void init_required_apple_events (void);
7105 static pascal OSErr
7106 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7107 static pascal OSErr
7108 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7109 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7110 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7112 #if TARGET_API_MAC_CARBON
7113 /* Drag and Drop */
7114 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
7115 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7116 #endif
7118 #if USE_CARBON_EVENTS
7119 /* Preliminary Support for the OSX Services Menu */
7120 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7121 static void init_service_handler ();
7122 /* Window Event Handler */
7123 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7124 EventRef, void *);
7125 #endif
7126 OSErr install_window_handler (WindowPtr);
7128 extern void init_emacs_passwd_dir ();
7129 extern int emacs_main (int, char **, char **);
7130 extern void check_alarm ();
7132 extern void initialize_applescript();
7133 extern void terminate_applescript();
7135 static unsigned int
7136 #if USE_CARBON_EVENTS
7137 mac_to_emacs_modifiers (UInt32 mods)
7138 #else
7139 mac_to_emacs_modifiers (EventModifiers mods)
7140 #endif
7142 unsigned int result = 0;
7143 if (mods & macShiftKey)
7144 result |= shift_modifier;
7145 if (mods & macCtrlKey)
7146 result |= ctrl_modifier;
7147 if (mods & macMetaKey)
7148 result |= meta_modifier;
7149 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7150 result |= alt_modifier;
7151 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7152 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7153 if (!NILP(val))
7154 result |= XUINT(val);
7157 return result;
7160 static int
7161 mac_get_emulated_btn ( UInt32 modifiers )
7163 int result = 0;
7164 if (!NILP (Vmac_emulate_three_button_mouse)) {
7165 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7166 if (modifiers & cmdKey)
7167 result = cmdIs3 ? 2 : 1;
7168 else if (modifiers & optionKey)
7169 result = cmdIs3 ? 1 : 2;
7171 return result;
7174 #if USE_CARBON_EVENTS
7175 /* Obtains the event modifiers from the event ref and then calls
7176 mac_to_emacs_modifiers. */
7177 static int
7178 mac_event_to_emacs_modifiers (EventRef eventRef)
7180 UInt32 mods = 0;
7181 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7182 sizeof (UInt32), NULL, &mods);
7183 if (!NILP (Vmac_emulate_three_button_mouse) &&
7184 GetEventClass(eventRef) == kEventClassMouse)
7186 mods &= ~(optionKey | cmdKey);
7188 return mac_to_emacs_modifiers (mods);
7191 /* Given an event ref, return the code to use for the mouse button
7192 code in the emacs input_event. */
7193 static int
7194 mac_get_mouse_btn (EventRef ref)
7196 EventMouseButton result = kEventMouseButtonPrimary;
7197 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7198 sizeof (EventMouseButton), NULL, &result);
7199 switch (result)
7201 case kEventMouseButtonPrimary:
7202 if (NILP (Vmac_emulate_three_button_mouse))
7203 return 0;
7204 else {
7205 UInt32 mods = 0;
7206 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7207 sizeof (UInt32), NULL, &mods);
7208 return mac_get_emulated_btn(mods);
7210 case kEventMouseButtonSecondary:
7211 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7212 case kEventMouseButtonTertiary:
7213 case 4: /* 4 is the number for the mouse wheel button */
7214 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7215 default:
7216 return 0;
7220 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7221 events. However the click of the mouse wheel is not converted to a
7222 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7223 checks to see if it is a mouse up or down carbon event that has not
7224 been converted, and if so, converts it by hand (to be picked up in
7225 the XTread_socket loop). */
7226 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7228 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7229 /* Do special case for mouse wheel button. */
7230 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7232 UInt32 kind = GetEventKind (eventRef);
7233 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7235 eventRec->what = mouseDown;
7236 result=1;
7238 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7240 eventRec->what = mouseUp;
7241 result=1;
7243 if (result)
7245 /* Need where and when. */
7246 UInt32 mods;
7247 GetEventParameter (eventRef, kEventParamMouseLocation,
7248 typeQDPoint, NULL, sizeof (Point),
7249 NULL, &eventRec->where);
7250 /* Use two step process because new event modifiers are
7251 32-bit and old are 16-bit. Currently, only loss is
7252 NumLock & Fn. */
7253 GetEventParameter (eventRef, kEventParamKeyModifiers,
7254 typeUInt32, NULL, sizeof (UInt32),
7255 NULL, &mods);
7256 eventRec->modifiers = mods;
7258 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7261 return result;
7264 #endif
7266 static void
7267 do_get_menus (void)
7269 Handle menubar_handle;
7270 MenuHandle menu_handle;
7272 menubar_handle = GetNewMBar (128);
7273 if(menubar_handle == NULL)
7274 abort ();
7275 SetMenuBar (menubar_handle);
7276 DrawMenuBar ();
7278 menu_handle = GetMenuHandle (M_APPLE);
7279 if(menu_handle != NULL)
7280 AppendResMenu (menu_handle,'DRVR');
7281 else
7282 abort ();
7286 static void
7287 do_init_managers (void)
7289 #if !TARGET_API_MAC_CARBON
7290 InitGraf (&qd.thePort);
7291 InitFonts ();
7292 FlushEvents (everyEvent, 0);
7293 InitWindows ();
7294 InitMenus ();
7295 TEInit ();
7296 InitDialogs (NULL);
7297 #endif /* !TARGET_API_MAC_CARBON */
7298 InitCursor ();
7300 #if !TARGET_API_MAC_CARBON
7301 arrow_cursor = &qd.arrow;
7303 /* set up some extra stack space for use by emacs */
7304 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7306 /* MaxApplZone must be called for AppleScript to execute more
7307 complicated scripts */
7308 MaxApplZone ();
7309 MoreMasters ();
7310 #endif /* !TARGET_API_MAC_CARBON */
7313 static void
7314 do_check_ram_size (void)
7316 SInt32 physical_ram_size, logical_ram_size;
7318 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7319 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7320 || physical_ram_size > (1 << VALBITS)
7321 || logical_ram_size > (1 << VALBITS))
7323 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7324 exit (1);
7328 static void
7329 do_window_update (WindowPtr win)
7331 struct frame *f = mac_window_to_frame (win);
7333 BeginUpdate (win);
7335 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7336 below. */
7337 if (win != tip_window)
7339 if (f->async_visible == 0)
7341 f->async_visible = 1;
7342 f->async_iconified = 0;
7343 SET_FRAME_GARBAGED (f);
7345 /* An update event is equivalent to MapNotify on X, so report
7346 visibility changes properly. */
7347 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7348 /* Force a redisplay sooner or later to update the
7349 frame titles in case this is the second frame. */
7350 record_asynch_buffer_change ();
7352 else
7354 Rect r;
7356 handling_window_update = 1;
7358 #if TARGET_API_MAC_CARBON
7360 RgnHandle region = NewRgn ();
7362 GetPortVisibleRegion (GetWindowPort (win), region);
7363 UpdateControls (win, region);
7364 GetRegionBounds (region, &r);
7365 DisposeRgn (region);
7367 #else
7368 UpdateControls (win, win->visRgn);
7369 r = (*win->visRgn)->rgnBBox;
7370 #endif
7371 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7373 handling_window_update = 0;
7377 EndUpdate (win);
7380 static int
7381 is_emacs_window (WindowPtr win)
7383 Lisp_Object tail, frame;
7385 if (!win)
7386 return 0;
7388 FOR_EACH_FRAME (tail, frame)
7389 if (FRAME_MAC_P (XFRAME (frame)))
7390 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7391 return 1;
7393 return 0;
7396 static void
7397 do_app_resume ()
7399 /* Window-activate events will do the job. */
7400 #if 0
7401 WindowPtr wp;
7402 struct frame *f;
7404 wp = front_emacs_window ();
7405 if (wp)
7407 f = mac_window_to_frame (wp);
7409 if (f)
7411 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7412 activate_scroll_bars (f);
7416 app_is_suspended = false;
7417 app_sleep_time = WNE_SLEEP_AT_RESUME;
7418 #endif
7421 static void
7422 do_app_suspend ()
7424 /* Window-deactivate events will do the job. */
7425 #if 0
7426 WindowPtr wp;
7427 struct frame *f;
7429 wp = front_emacs_window ();
7430 if (wp)
7432 f = mac_window_to_frame (wp);
7434 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7436 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7437 deactivate_scroll_bars (f);
7441 app_is_suspended = true;
7442 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7443 #endif
7447 static void
7448 do_mouse_moved (mouse_pos, f)
7449 Point mouse_pos;
7450 FRAME_PTR *f;
7452 WindowPtr wp = front_emacs_window ();
7453 struct x_display_info *dpyinfo;
7455 if (wp)
7457 *f = mac_window_to_frame (wp);
7458 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7460 if (dpyinfo->mouse_face_hidden)
7462 dpyinfo->mouse_face_hidden = 0;
7463 clear_mouse_face (dpyinfo);
7466 SetPortWindowPort (wp);
7468 GlobalToLocal (&mouse_pos);
7470 if (dpyinfo->grabbed && tracked_scroll_bar)
7471 x_scroll_bar_note_movement (tracked_scroll_bar,
7472 mouse_pos.v
7473 - XINT (tracked_scroll_bar->top),
7474 TickCount() * (1000 / 60));
7475 else
7476 note_mouse_movement (*f, &mouse_pos);
7481 static void
7482 do_apple_menu (SInt16 menu_item)
7484 #if !TARGET_API_MAC_CARBON
7485 Str255 item_name;
7486 SInt16 da_driver_refnum;
7488 if (menu_item == I_ABOUT)
7489 NoteAlert (ABOUT_ALERT_ID, NULL);
7490 else
7492 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7493 da_driver_refnum = OpenDeskAcc (item_name);
7495 #endif /* !TARGET_API_MAC_CARBON */
7498 void
7499 do_menu_choice (SInt32 menu_choice)
7501 SInt16 menu_id, menu_item;
7503 menu_id = HiWord (menu_choice);
7504 menu_item = LoWord (menu_choice);
7506 if (menu_id == 0)
7507 return;
7509 switch (menu_id)
7511 case M_APPLE:
7512 do_apple_menu (menu_item);
7513 break;
7515 default:
7517 struct frame *f = mac_window_to_frame (front_emacs_window ());
7518 MenuHandle menu = GetMenuHandle (menu_id);
7519 if (menu)
7521 UInt32 refcon;
7523 GetMenuItemRefCon (menu, menu_item, &refcon);
7524 menubar_selection_callback (f, refcon);
7529 HiliteMenu (0);
7533 /* Handle drags in size box. Based on code contributed by Ben
7534 Mesander and IM - Window Manager A. */
7536 static void
7537 do_grow_window (WindowPtr w, EventRecord *e)
7539 Rect limit_rect;
7540 int rows, columns, width, height;
7541 struct frame *f = mac_window_to_frame (w);
7542 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7543 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7544 #if TARGET_API_MAC_CARBON
7545 Rect new_rect;
7546 #else
7547 long grow_size;
7548 #endif
7550 if (size_hints->flags & PMinSize)
7552 min_width = size_hints->min_width;
7553 min_height = size_hints->min_height;
7555 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
7557 #if TARGET_API_MAC_CARBON
7558 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7559 return;
7560 height = new_rect.bottom - new_rect.top;
7561 width = new_rect.right - new_rect.left;
7562 #else
7563 grow_size = GrowWindow (w, e->where, &limit_rect);
7564 /* see if it really changed size */
7565 if (grow_size == 0)
7566 return;
7567 height = HiWord (grow_size);
7568 width = LoWord (grow_size);
7569 #endif
7571 if (width != FRAME_PIXEL_WIDTH (f)
7572 || height != FRAME_PIXEL_HEIGHT (f))
7574 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7575 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7577 x_set_window_size (f, 0, columns, rows);
7582 /* Handle clicks in zoom box. Calculation of "standard state" based
7583 on code in IM - Window Manager A and code contributed by Ben
7584 Mesander. The standard state of an Emacs window is 80-characters
7585 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7587 static void
7588 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7590 GrafPtr save_port;
7591 Rect zoom_rect, port_rect;
7592 Point top_left;
7593 int w_title_height, columns, rows, width, height;
7594 struct frame *f = mac_window_to_frame (w);
7596 #if TARGET_API_MAC_CARBON
7598 Point standard_size;
7600 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7601 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7603 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7604 zoom_in_or_out = inZoomIn;
7605 else
7607 /* Adjust the standard size according to character boundaries. */
7609 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7610 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7611 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7612 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7613 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7614 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7615 && port_rect.left == zoom_rect.left
7616 && port_rect.top == zoom_rect.top)
7617 zoom_in_or_out = inZoomIn;
7618 else
7619 zoom_in_or_out = inZoomOut;
7622 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7624 #else /* not TARGET_API_MAC_CARBON */
7625 GetPort (&save_port);
7627 SetPortWindowPort (w);
7629 /* Clear window to avoid flicker. */
7630 EraseRect (&(w->portRect));
7631 if (zoom_in_or_out == inZoomOut)
7633 SetPt (&top_left, w->portRect.left, w->portRect.top);
7634 LocalToGlobal (&top_left);
7636 /* calculate height of window's title bar */
7637 w_title_height = top_left.v - 1
7638 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7640 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7641 zoom_rect = qd.screenBits.bounds;
7642 zoom_rect.top += w_title_height;
7643 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7645 zoom_rect.right = zoom_rect.left
7646 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7648 /* Adjust the standard size according to character boundaries. */
7649 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7650 zoom_rect.bottom =
7651 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7653 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7654 = zoom_rect;
7657 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7659 SetPort (save_port);
7660 #endif /* not TARGET_API_MAC_CARBON */
7662 /* retrieve window size and update application values */
7663 #if TARGET_API_MAC_CARBON
7664 GetWindowPortBounds (w, &port_rect);
7665 #else
7666 port_rect = w->portRect;
7667 #endif
7668 height = port_rect.bottom - port_rect.top;
7669 width = port_rect.right - port_rect.left;
7671 if (width != FRAME_PIXEL_WIDTH (f)
7672 || height != FRAME_PIXEL_HEIGHT (f))
7674 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7675 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7677 change_frame_size (f, rows, columns, 0, 1, 0);
7678 SET_FRAME_GARBAGED (f);
7679 cancel_mouse_face (f);
7681 FRAME_PIXEL_WIDTH (f) = width;
7682 FRAME_PIXEL_HEIGHT (f) = height;
7684 x_real_positions (f, &f->left_pos, &f->top_pos);
7687 /* Intialize AppleEvent dispatcher table for the required events. */
7688 void
7689 init_required_apple_events ()
7691 OSErr err;
7692 long result;
7694 /* Make sure we have apple events before starting. */
7695 err = Gestalt (gestaltAppleEventsAttr, &result);
7696 if (err != noErr)
7697 abort ();
7699 if (!(result & (1 << gestaltAppleEventsPresent)))
7700 abort ();
7702 #if TARGET_API_MAC_CARBON
7703 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7704 NewAEEventHandlerUPP
7705 ((AEEventHandlerProcPtr) do_ae_open_application),
7706 0L, false);
7707 #else
7708 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7709 NewAEEventHandlerProc
7710 ((AEEventHandlerProcPtr) do_ae_open_application),
7711 0L, false);
7712 #endif
7713 if (err != noErr)
7714 abort ();
7716 #if TARGET_API_MAC_CARBON
7717 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7718 NewAEEventHandlerUPP
7719 ((AEEventHandlerProcPtr) do_ae_open_documents),
7720 0L, false);
7721 #else
7722 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7723 NewAEEventHandlerProc
7724 ((AEEventHandlerProcPtr) do_ae_open_documents),
7725 0L, false);
7726 #endif
7727 if (err != noErr)
7728 abort ();
7730 #if TARGET_API_MAC_CARBON
7731 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7732 NewAEEventHandlerUPP
7733 ((AEEventHandlerProcPtr) do_ae_print_documents),
7734 0L, false);
7735 #else
7736 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7737 NewAEEventHandlerProc
7738 ((AEEventHandlerProcPtr) do_ae_print_documents),
7739 0L, false);
7740 #endif
7741 if (err != noErr)
7742 abort ();
7744 #if TARGET_API_MAC_CARBON
7745 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7746 NewAEEventHandlerUPP
7747 ((AEEventHandlerProcPtr) do_ae_quit_application),
7748 0L, false);
7749 #else
7750 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7751 NewAEEventHandlerProc
7752 ((AEEventHandlerProcPtr) do_ae_quit_application),
7753 0L, false);
7754 #endif
7755 if (err != noErr)
7756 abort ();
7759 #if USE_CARBON_EVENTS
7761 void
7762 init_service_handler ()
7764 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7765 {kEventClassService, kEventServiceCopy},
7766 {kEventClassService, kEventServicePaste}};
7767 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7768 3, specs, NULL, NULL);
7772 MAC_TODO: Check to see if this is called by AEProcessDesc...
7774 OSStatus
7775 mac_handle_service_event (EventHandlerCallRef callRef,
7776 EventRef event, void *data)
7778 OSStatus err = noErr;
7779 switch (GetEventKind (event))
7781 case kEventServiceGetTypes:
7783 CFMutableArrayRef copyTypes, pasteTypes;
7784 CFStringRef type;
7785 Boolean selection = true;
7787 GetEventParameter(event, kEventParamServicePasteTypes,
7788 typeCFMutableArrayRef, NULL,
7789 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7791 GetEventParameter(event, kEventParamServiceCopyTypes,
7792 typeCFMutableArrayRef, NULL,
7793 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7794 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7795 if (type) {
7796 CFArrayAppendValue (copyTypes, type);
7797 //CFArrayAppendValue (pasteTypes, type);
7798 CFRelease (type);
7801 case kEventServiceCopy:
7803 ScrapRef currentScrap, specificScrap;
7804 char * buf = "";
7805 Size byteCount = 0;
7807 GetCurrentScrap (&currentScrap);
7809 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7810 if (err == noErr)
7812 void *buffer = xmalloc (byteCount);
7813 if (buffer != NULL)
7815 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7816 sizeof (ScrapRef), NULL, &specificScrap);
7818 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7819 &byteCount, buffer);
7820 if (err == noErr)
7821 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7822 kScrapFlavorMaskNone, byteCount, buffer);
7823 xfree (buffer);
7826 err = noErr;
7828 case kEventServicePaste:
7831 // Get the current location
7832 Size byteCount;
7833 ScrapRef specificScrap;
7834 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7835 sizeof(ScrapRef), NULL, &specificScrap);
7836 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7837 if (err == noErr) {
7838 void * buffer = xmalloc(byteCount);
7839 if (buffer != NULL ) {
7840 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7841 &byteCount, buffer);
7842 if (err == noErr) {
7843 // Actually place in the buffer
7844 BLOCK_INPUT;
7845 // Get the current "selection" string here
7846 UNBLOCK_INPUT;
7849 xfree(buffer);
7854 return err;
7858 static pascal OSStatus
7859 mac_handle_window_event (next_handler, event, data)
7860 EventHandlerCallRef next_handler;
7861 EventRef event;
7862 void *data;
7864 extern Lisp_Object Qcontrol;
7866 WindowPtr wp;
7867 OSStatus result;
7868 UInt32 attributes;
7869 XSizeHints *size_hints;
7871 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
7872 NULL, sizeof (WindowPtr), NULL, &wp);
7874 switch (GetEventKind (event))
7876 case kEventWindowUpdate:
7877 result = CallNextEventHandler (next_handler, event);
7878 if (result != eventNotHandledErr)
7879 return result;
7881 do_window_update (wp);
7882 break;
7884 case kEventWindowBoundsChanging:
7885 result = CallNextEventHandler (next_handler, event);
7886 if (result != eventNotHandledErr)
7887 return result;
7889 GetEventParameter (event, kEventParamAttributes, typeUInt32,
7890 NULL, sizeof (UInt32), NULL, &attributes);
7891 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
7892 if ((attributes & kWindowBoundsChangeUserResize)
7893 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
7894 == (PResizeInc | PBaseSize | PMinSize)))
7896 Rect bounds;
7897 int width, height;
7899 GetEventParameter (event, kEventParamCurrentBounds,
7900 typeQDRectangle,
7901 NULL, sizeof (Rect), NULL, &bounds);
7902 width = bounds.right - bounds.left;
7903 height = bounds.bottom - bounds.top;
7905 if (width < size_hints->min_width)
7906 width = size_hints->min_width;
7907 else
7908 width = size_hints->base_width
7909 + (int) ((width - size_hints->base_width)
7910 / (float) size_hints->width_inc + .5)
7911 * size_hints->width_inc;
7913 if (height < size_hints->min_height)
7914 height = size_hints->min_height;
7915 else
7916 height = size_hints->base_height
7917 + (int) ((height - size_hints->base_height)
7918 / (float) size_hints->height_inc + .5)
7919 * size_hints->height_inc;
7921 bounds.right = bounds.left + width;
7922 bounds.bottom = bounds.top + height;
7923 SetEventParameter (event, kEventParamCurrentBounds,
7924 typeQDRectangle, sizeof (Rect), &bounds);
7925 return noErr;
7927 break;
7930 return eventNotHandledErr;
7932 #endif /* USE_CARBON_EVENTS */
7935 OSErr
7936 install_window_handler (window)
7937 WindowPtr window;
7939 OSErr err = noErr;
7940 #if USE_CARBON_EVENTS
7941 EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate},
7942 {kEventClassWindow, kEventWindowBoundsChanging}};
7943 static EventHandlerUPP handle_window_event_UPP = NULL;
7945 if (handle_window_event_UPP == NULL)
7946 handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
7948 err = InstallWindowEventHandler (window, handle_window_event_UPP,
7949 GetEventTypeCount (specs), specs,
7950 NULL, NULL);
7951 #endif
7952 #if TARGET_API_MAC_CARBON
7953 if (err == noErr)
7954 err = InstallTrackingHandler (mac_do_track_drag, window, NULL);
7955 if (err == noErr)
7956 err = InstallReceiveHandler (mac_do_receive_drag, window, NULL);
7957 #endif
7958 return err;
7962 /* Open Application Apple Event */
7963 static pascal OSErr
7964 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7966 return noErr;
7970 /* Defined in mac.c. */
7971 extern int
7972 path_from_vol_dir_name (char *, int, short, long, char *);
7975 /* Called when we receive an AppleEvent with an ID of
7976 "kAEOpenDocuments". This routine gets the direct parameter,
7977 extracts the FSSpecs in it, and puts their names on a list. */
7978 #pragma options align=mac68k
7979 typedef struct SelectionRange {
7980 short unused1; // 0 (not used)
7981 short lineNum; // line to select (<0 to specify range)
7982 long startRange; // start of selection range (if line < 0)
7983 long endRange; // end of selection range (if line < 0)
7984 long unused2; // 0 (not used)
7985 long theDate; // modification date/time
7986 } SelectionRange;
7987 #pragma options align=reset
7989 static pascal OSErr
7990 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7992 OSErr err, err2;
7993 AEDesc the_desc;
7994 AEKeyword keyword;
7995 DescType actual_type;
7996 Size actual_size;
7997 SelectionRange position;
7999 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
8000 if (err != noErr)
8001 goto descriptor_error_exit;
8003 err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
8004 if (err == noErr)
8005 drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1),
8006 make_number (position.startRange + 1),
8007 make_number (position.endRange + 1)),
8008 drag_and_drop_file_list);
8010 /* Check to see that we got all of the required parameters from the
8011 event descriptor. For an 'odoc' event this should just be the
8012 file list. */
8013 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
8014 &actual_type, (Ptr) &keyword,
8015 sizeof (keyword), &actual_size);
8016 /* No error means that we found some unused parameters.
8017 errAEDescNotFound means that there are no more parameters. If we
8018 get an error code other than that, flag it. */
8019 if ((err == noErr) || (err != errAEDescNotFound))
8021 err = errAEEventNotHandled;
8022 goto error_exit;
8024 err = noErr;
8026 /* Got all the parameters we need. Now, go through the direct
8027 object list and parse it up. */
8029 long num_files_to_open;
8031 err = AECountItems (&the_desc, &num_files_to_open);
8032 if (err == noErr)
8034 int i;
8036 /* AE file list is one based so just use that for indexing here. */
8037 for (i = 1; i <= num_files_to_open; i++)
8039 #ifdef MAC_OSX
8040 FSRef fref;
8041 char unix_path_name[MAXPATHLEN];
8043 err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
8044 &actual_type, &fref, sizeof (FSRef),
8045 &actual_size);
8046 if (err != noErr || actual_type != typeFSRef)
8047 continue;
8049 if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
8050 == noErr)
8051 #else
8052 FSSpec fs;
8053 Str255 path_name, unix_path_name;
8055 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
8056 (Ptr) &fs, sizeof (fs), &actual_size);
8057 if (err != noErr) continue;
8059 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
8060 fs.name) &&
8061 mac_to_posix_pathname (path_name, unix_path_name, 255))
8062 #endif
8063 /* x-dnd functions expect undecoded filenames. */
8064 drag_and_drop_file_list =
8065 Fcons (make_unibyte_string (unix_path_name,
8066 strlen (unix_path_name)),
8067 drag_and_drop_file_list);
8072 error_exit:
8073 /* Nuke the coerced file list in any case */
8074 err2 = AEDisposeDesc(&the_desc);
8076 descriptor_error_exit:
8077 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8078 return err;
8082 #if TARGET_API_MAC_CARBON
8083 static pascal OSErr
8084 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
8085 void *handlerRefCon, DragReference theDrag)
8087 static int can_accept;
8088 short items;
8089 short index;
8090 ItemReference theItem;
8091 FlavorFlags theFlags;
8092 OSErr result;
8094 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8095 return dragNotAcceptedErr;
8097 switch (message)
8099 case kDragTrackingEnterHandler:
8100 CountDragItems (theDrag, &items);
8101 can_accept = 0;
8102 for (index = 1; index <= items; index++)
8104 GetDragItemReferenceNumber (theDrag, index, &theItem);
8105 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8106 if (result == noErr)
8108 can_accept = 1;
8109 break;
8112 break;
8114 case kDragTrackingEnterWindow:
8115 if (can_accept)
8117 RgnHandle hilite_rgn = NewRgn ();
8118 Rect r;
8119 struct frame *f = mac_window_to_frame (window);
8121 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
8122 GetWindowPortBounds (window, &r);
8123 OffsetRect (&r, -r.left, -r.top);
8124 RectRgn (hilite_rgn, &r);
8125 ShowDragHilite (theDrag, hilite_rgn, true);
8126 DisposeRgn (hilite_rgn);
8127 SetThemeCursor (kThemeCopyArrowCursor);
8129 break;
8131 case kDragTrackingInWindow:
8132 break;
8134 case kDragTrackingLeaveWindow:
8135 if (can_accept)
8137 struct frame *f = mac_window_to_frame (window);
8139 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
8140 HideDragHilite (theDrag);
8141 SetThemeCursor (kThemeArrowCursor);
8143 break;
8145 case kDragTrackingLeaveHandler:
8146 break;
8149 return noErr;
8152 static pascal OSErr
8153 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8154 DragReference theDrag)
8156 short items;
8157 short index;
8158 FlavorFlags theFlags;
8159 Point mouse;
8160 OSErr result;
8161 ItemReference theItem;
8162 HFSFlavor data;
8163 Size size = sizeof (HFSFlavor);
8165 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8166 return dragNotAcceptedErr;
8168 drag_and_drop_file_list = Qnil;
8169 GetDragMouse (theDrag, &mouse, 0L);
8170 CountDragItems (theDrag, &items);
8171 for (index = 1; index <= items; index++)
8173 /* Only handle file references. */
8174 GetDragItemReferenceNumber (theDrag, index, &theItem);
8175 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8176 if (result == noErr)
8178 #ifdef MAC_OSX
8179 FSRef fref;
8180 char unix_path_name[MAXPATHLEN];
8181 #else
8182 Str255 path_name, unix_path_name;
8183 #endif
8184 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8185 #ifdef MAC_OSX
8186 /* Use Carbon routines, otherwise it converts the file name
8187 to /Macintosh HD/..., which is not correct. */
8188 FSpMakeFSRef (&data.fileSpec, &fref);
8189 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8190 #else
8191 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
8192 data.fileSpec.parID, data.fileSpec.name) &&
8193 mac_to_posix_pathname (path_name, unix_path_name, 255))
8194 #endif
8195 /* x-dnd functions expect undecoded filenames. */
8196 drag_and_drop_file_list =
8197 Fcons (make_unibyte_string (unix_path_name,
8198 strlen (unix_path_name)),
8199 drag_and_drop_file_list);
8202 /* If there are items in the list, construct an event and post it to
8203 the queue like an interrupt using kbd_buffer_store_event. */
8204 if (!NILP (drag_and_drop_file_list))
8206 struct input_event event;
8207 Lisp_Object frame;
8208 struct frame *f = mac_window_to_frame (window);
8209 SInt16 modifiers;
8211 GlobalToLocal (&mouse);
8212 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
8214 event.kind = DRAG_N_DROP_EVENT;
8215 event.code = 0;
8216 event.modifiers = mac_to_emacs_modifiers (modifiers);
8217 event.timestamp = TickCount () * (1000 / 60);
8218 XSETINT (event.x, mouse.h);
8219 XSETINT (event.y, mouse.v);
8220 XSETFRAME (frame, f);
8221 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8222 event.arg = Qnil;
8223 /* Post to the interrupt queue */
8224 kbd_buffer_store_event (&event);
8225 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8227 ProcessSerialNumber psn;
8228 GetCurrentProcess (&psn);
8229 SetFrontProcess (&psn);
8232 return noErr;
8234 else
8235 return dragNotAcceptedErr;
8237 #endif
8240 /* Print Document Apple Event */
8241 static pascal OSErr
8242 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8244 return errAEEventNotHandled;
8248 static pascal OSErr
8249 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8251 /* FixMe: Do we need an unwind-protect or something here? And what
8252 do we do about unsaved files. Currently just forces quit rather
8253 than doing recursive callback to get user input. */
8255 terminate_flag = true;
8257 /* Fkill_emacs doesn't return. We have to return. (TI) */
8258 return noErr;
8262 #if __profile__
8263 void
8264 profiler_exit_proc ()
8266 ProfilerDump ("\pEmacs.prof");
8267 ProfilerTerm ();
8269 #endif
8271 /* These few functions implement Emacs as a normal Mac application
8272 (almost): set up the heap and the Toolbox, handle necessary
8273 system events plus a few simple menu events. They also set up
8274 Emacs's access to functions defined in the rest of this file.
8275 Emacs uses function hooks to perform all its terminal I/O. A
8276 complete list of these functions appear in termhooks.h. For what
8277 they do, read the comments there and see also w32term.c and
8278 xterm.c. What's noticeably missing here is the event loop, which
8279 is normally present in most Mac application. After performing the
8280 necessary Mac initializations, main passes off control to
8281 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8282 mac_read_socket (defined further below) to read input. This is
8283 where WaitNextEvent is called to process Mac events. This is also
8284 where check_alarm in sysdep.c is called to simulate alarm signals.
8285 This makes the cursor jump back to its correct position after
8286 briefly jumping to that of the matching parenthesis, print useful
8287 hints and prompts in the minibuffer after the user stops typing for
8288 a wait, etc. */
8290 #if !TARGET_API_MAC_CARBON
8291 #undef main
8293 main (void)
8295 #if __profile__ /* is the profiler on? */
8296 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8297 exit(1);
8298 #endif
8300 #if __MWERKS__
8301 /* set creator and type for files created by MSL */
8302 _fcreator = 'EMAx';
8303 _ftype = 'TEXT';
8304 #endif
8306 do_init_managers ();
8308 do_get_menus ();
8310 #ifndef USE_LSB_TAG
8311 do_check_ram_size ();
8312 #endif
8314 init_emacs_passwd_dir ();
8316 init_environ ();
8318 initialize_applescript ();
8320 init_required_apple_events ();
8323 char **argv;
8324 int argc = 0;
8326 /* set up argv array from STR# resource */
8327 get_string_list (&argv, ARGV_STRING_LIST_ID);
8328 while (argv[argc])
8329 argc++;
8331 /* free up AppleScript resources on exit */
8332 atexit (terminate_applescript);
8334 #if __profile__ /* is the profiler on? */
8335 atexit (profiler_exit_proc);
8336 #endif
8338 /* 3rd param "envp" never used in emacs_main */
8339 (void) emacs_main (argc, argv, 0);
8342 /* Never reached - real exit in Fkill_emacs */
8343 return 0;
8345 #endif
8347 /* Table for translating Mac keycode to X keysym values. Contributed
8348 by Sudhir Shenoy. */
8349 static unsigned char keycode_to_xkeysym_table[] = {
8350 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8351 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8352 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8354 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8355 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8356 /*0x38*/ 0, 0, 0, 0,
8357 /*0x3C*/ 0, 0, 0, 0,
8359 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8360 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8361 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8362 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8364 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8365 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8366 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8367 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8369 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8370 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8371 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8372 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8374 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8375 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8376 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8377 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8380 static int
8381 keycode_to_xkeysym (int keyCode, int *xKeySym)
8383 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8384 return *xKeySym != 0;
8387 #if !USE_CARBON_EVENTS
8388 static RgnHandle mouse_region = NULL;
8390 Boolean
8391 mac_wait_next_event (er, sleep_time, dequeue)
8392 EventRecord *er;
8393 UInt32 sleep_time;
8394 Boolean dequeue;
8396 static EventRecord er_buf = {nullEvent};
8397 UInt32 target_tick, current_tick;
8398 EventMask event_mask;
8400 if (mouse_region == NULL)
8401 mouse_region = NewRgn ();
8403 event_mask = everyEvent;
8404 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8405 event_mask -= highLevelEventMask;
8407 current_tick = TickCount ();
8408 target_tick = current_tick + sleep_time;
8410 if (er_buf.what == nullEvent)
8411 while (!WaitNextEvent (event_mask, &er_buf,
8412 target_tick - current_tick, mouse_region))
8414 current_tick = TickCount ();
8415 if (target_tick <= current_tick)
8416 return false;
8419 *er = er_buf;
8420 if (dequeue)
8421 er_buf.what = nullEvent;
8422 return true;
8424 #endif /* not USE_CARBON_EVENTS */
8426 /* Emacs calls this whenever it wants to read an input event from the
8427 user. */
8429 XTread_socket (sd, expected, hold_quit)
8430 int sd, expected;
8431 struct input_event *hold_quit;
8433 struct input_event inev;
8434 int count = 0;
8435 #if USE_CARBON_EVENTS
8436 EventRef eventRef;
8437 EventTargetRef toolbox_dispatcher;
8438 #endif
8439 EventRecord er;
8440 struct mac_display_info *dpyinfo = &one_mac_display_info;
8442 if (interrupt_input_blocked)
8444 interrupt_input_pending = 1;
8445 return -1;
8448 interrupt_input_pending = 0;
8449 BLOCK_INPUT;
8451 /* So people can tell when we have read the available input. */
8452 input_signal_count++;
8454 /* Don't poll for events to process (specifically updateEvt) if
8455 window update currently already in progress. A call to redisplay
8456 (in do_window_update) can be preempted by another call to
8457 redisplay, causing blank regions to be left on the screen and the
8458 cursor to be left at strange places. */
8459 if (handling_window_update)
8461 UNBLOCK_INPUT;
8462 return 0;
8465 if (terminate_flag)
8466 Fkill_emacs (make_number (1));
8468 #if USE_CARBON_EVENTS
8469 toolbox_dispatcher = GetEventDispatcherTarget ();
8471 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8472 kEventRemoveFromQueue, &eventRef))
8473 #else /* !USE_CARBON_EVENTS */
8474 while (mac_wait_next_event (&er, 0, true))
8475 #endif /* !USE_CARBON_EVENTS */
8477 int do_help = 0;
8478 struct frame *f;
8480 /* It is necessary to set this (additional) argument slot of an
8481 event to nil because keyboard.c protects incompletely
8482 processed event from being garbage collected by placing them
8483 in the kbd_buffer_gcpro vector. */
8484 EVENT_INIT (inev);
8485 inev.kind = NO_EVENT;
8486 inev.arg = Qnil;
8488 #if USE_CARBON_EVENTS
8489 /* Handle new events */
8490 if (!mac_convert_event_ref (eventRef, &er))
8491 switch (GetEventClass (eventRef))
8493 case kEventClassWindow:
8494 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8496 WindowPtr window_ptr;
8497 GetEventParameter(eventRef, kEventParamDirectObject,
8498 typeWindowRef, NULL, sizeof(WindowPtr),
8499 NULL, &window_ptr);
8500 f = mac_window_to_frame (window_ptr);
8501 if (f && !f->async_iconified)
8502 x_real_positions (f, &f->left_pos, &f->top_pos);
8503 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8505 break;
8506 case kEventClassMouse:
8507 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8509 SInt32 delta;
8510 Point point;
8511 WindowPtr window_ptr = front_emacs_window ();
8513 if (!IsValidWindowPtr (window_ptr))
8515 SysBeep(1);
8516 break;
8519 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8520 typeSInt32, NULL, sizeof (SInt32),
8521 NULL, &delta);
8522 GetEventParameter(eventRef, kEventParamMouseLocation,
8523 typeQDPoint, NULL, sizeof (Point),
8524 NULL, &point);
8525 inev.kind = WHEEL_EVENT;
8526 inev.code = 0;
8527 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8528 | ((delta < 0) ? down_modifier
8529 : up_modifier));
8530 SetPortWindowPort (window_ptr);
8531 GlobalToLocal (&point);
8532 XSETINT (inev.x, point.h);
8533 XSETINT (inev.y, point.v);
8534 XSETFRAME (inev.frame_or_window,
8535 mac_window_to_frame (window_ptr));
8536 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8538 else
8539 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8541 break;
8543 default:
8544 /* Send the event to the appropriate receiver. */
8545 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8547 else
8548 #endif /* USE_CARBON_EVENTS */
8549 switch (er.what)
8551 case mouseDown:
8552 case mouseUp:
8554 WindowPtr window_ptr;
8555 SInt16 part_code;
8556 int tool_bar_p = 0;
8558 #if USE_CARBON_EVENTS
8559 /* This is needed to send mouse events like aqua window
8560 buttons to the correct handler. */
8561 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8562 != eventNotHandledErr)
8563 break;
8564 #endif
8566 if (dpyinfo->grabbed && last_mouse_frame
8567 && FRAME_LIVE_P (last_mouse_frame))
8569 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8570 part_code = inContent;
8572 else
8574 part_code = FindWindow (er.where, &window_ptr);
8575 if (tip_window && window_ptr == tip_window)
8577 HideWindow (tip_window);
8578 part_code = FindWindow (er.where, &window_ptr);
8582 if (er.what != mouseDown && part_code != inContent)
8583 break;
8585 switch (part_code)
8587 case inMenuBar:
8588 f = mac_window_to_frame (front_emacs_window ());
8589 saved_menu_event_location = er.where;
8590 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8591 XSETFRAME (inev.frame_or_window, f);
8592 break;
8594 case inContent:
8595 if (window_ptr != front_emacs_window ())
8596 SelectWindow (window_ptr);
8597 else
8599 SInt16 control_part_code;
8600 ControlHandle ch;
8601 Point mouse_loc = er.where;
8603 f = mac_window_to_frame (window_ptr);
8604 /* convert to local coordinates of new window */
8605 SetPortWindowPort (window_ptr);
8607 GlobalToLocal (&mouse_loc);
8608 #if TARGET_API_MAC_CARBON
8609 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8610 &control_part_code);
8611 #else
8612 control_part_code = FindControl (mouse_loc, window_ptr,
8613 &ch);
8614 #endif
8616 #if USE_CARBON_EVENTS
8617 inev.code = mac_get_mouse_btn (eventRef);
8618 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8619 #else
8620 inev.code = mac_get_emulated_btn (er.modifiers);
8621 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8622 #endif
8623 XSETINT (inev.x, mouse_loc.h);
8624 XSETINT (inev.y, mouse_loc.v);
8625 inev.timestamp = er.when * (1000 / 60);
8626 /* ticks to milliseconds */
8628 if (dpyinfo->grabbed && tracked_scroll_bar
8629 #if TARGET_API_MAC_CARBON
8630 || ch != 0
8631 #else
8632 || control_part_code != 0
8633 #endif
8636 struct scroll_bar *bar;
8638 if (dpyinfo->grabbed && tracked_scroll_bar)
8640 bar = tracked_scroll_bar;
8641 control_part_code = kControlIndicatorPart;
8643 else
8644 bar = (struct scroll_bar *) GetControlReference (ch);
8645 x_scroll_bar_handle_click (bar, control_part_code,
8646 &er, &inev);
8647 if (er.what == mouseDown
8648 && control_part_code == kControlIndicatorPart)
8649 tracked_scroll_bar = bar;
8650 else
8651 tracked_scroll_bar = NULL;
8653 else
8655 Lisp_Object window;
8656 int x = mouse_loc.h;
8657 int y = mouse_loc.v;
8659 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8660 if (EQ (window, f->tool_bar_window))
8662 if (er.what == mouseDown)
8663 handle_tool_bar_click (f, x, y, 1, 0);
8664 else
8665 handle_tool_bar_click (f, x, y, 0,
8666 inev.modifiers);
8667 tool_bar_p = 1;
8669 else
8671 XSETFRAME (inev.frame_or_window, f);
8672 inev.kind = MOUSE_CLICK_EVENT;
8676 if (er.what == mouseDown)
8678 dpyinfo->grabbed |= (1 << inev.code);
8679 last_mouse_frame = f;
8680 /* Ignore any mouse motion that happened
8681 before this event; any subsequent
8682 mouse-movement Emacs events should reflect
8683 only motion after the ButtonPress. */
8684 if (f != 0)
8685 f->mouse_moved = 0;
8687 if (!tool_bar_p)
8688 last_tool_bar_item = -1;
8690 else
8692 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8693 /* If a button is released though it was not
8694 previously pressed, that would be because
8695 of multi-button emulation. */
8696 dpyinfo->grabbed = 0;
8697 else
8698 dpyinfo->grabbed &= ~(1 << inev.code);
8701 switch (er.what)
8703 case mouseDown:
8704 inev.modifiers |= down_modifier;
8705 break;
8706 case mouseUp:
8707 inev.modifiers |= up_modifier;
8708 break;
8711 break;
8713 case inDrag:
8714 #if TARGET_API_MAC_CARBON
8715 DragWindow (window_ptr, er.where, NULL);
8716 #else /* not TARGET_API_MAC_CARBON */
8717 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8718 #endif /* not TARGET_API_MAC_CARBON */
8719 /* Update the frame parameters. */
8721 struct frame *f = mac_window_to_frame (window_ptr);
8723 if (f && !f->async_iconified)
8724 x_real_positions (f, &f->left_pos, &f->top_pos);
8726 break;
8728 case inGoAway:
8729 if (TrackGoAway (window_ptr, er.where))
8731 inev.kind = DELETE_WINDOW_EVENT;
8732 XSETFRAME (inev.frame_or_window,
8733 mac_window_to_frame (window_ptr));
8735 break;
8737 /* window resize handling added --ben */
8738 case inGrow:
8739 do_grow_window (window_ptr, &er);
8740 break;
8742 /* window zoom handling added --ben */
8743 case inZoomIn:
8744 case inZoomOut:
8745 if (TrackBox (window_ptr, er.where, part_code))
8746 do_zoom_window (window_ptr, part_code);
8747 break;
8749 default:
8750 break;
8753 break;
8755 case updateEvt:
8756 #if USE_CARBON_EVENTS
8757 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8758 != eventNotHandledErr)
8759 break;
8760 #else
8761 do_window_update ((WindowPtr) er.message);
8762 #endif
8763 break;
8765 case osEvt:
8766 #if USE_CARBON_EVENTS
8767 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8768 != eventNotHandledErr)
8769 break;
8770 #endif
8771 switch ((er.message >> 24) & 0x000000FF)
8773 case suspendResumeMessage:
8774 if ((er.message & resumeFlag) == 1)
8775 do_app_resume ();
8776 else
8777 do_app_suspend ();
8778 break;
8780 case mouseMovedMessage:
8781 #if !USE_CARBON_EVENTS
8782 SetRectRgn (mouse_region, er.where.h, er.where.v,
8783 er.where.h + 1, er.where.v + 1);
8784 #endif
8785 previous_help_echo_string = help_echo_string;
8786 help_echo_string = help_echo_object = help_echo_window = Qnil;
8787 help_echo_pos = -1;
8789 do_mouse_moved (er.where, &f);
8791 /* If the contents of the global variable
8792 help_echo_string has changed, generate a
8793 HELP_EVENT. */
8794 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8795 do_help = 1;
8796 break;
8798 break;
8800 case activateEvt:
8802 WindowPtr window_ptr = (WindowPtr) er.message;
8804 #if USE_CARBON_EVENTS
8805 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8806 != eventNotHandledErr)
8807 break;
8808 #endif
8809 if (window_ptr == tip_window)
8811 HideWindow (tip_window);
8812 break;
8815 if (!is_emacs_window (window_ptr))
8816 break;
8818 f = mac_window_to_frame (window_ptr);
8820 if ((er.modifiers & activeFlag) != 0)
8822 /* A window has been activated */
8823 Point mouse_loc = er.where;
8825 x_new_focus_frame (dpyinfo, f);
8826 activate_scroll_bars (f);
8828 SetPortWindowPort (window_ptr);
8829 GlobalToLocal (&mouse_loc);
8830 /* Window-activated event counts as mouse movement,
8831 so update things that depend on mouse position. */
8832 note_mouse_movement (mac_window_to_frame (window_ptr),
8833 &mouse_loc);
8835 else
8837 /* A window has been deactivated */
8838 dpyinfo->grabbed = 0;
8840 if (f == dpyinfo->x_focus_frame)
8842 x_new_focus_frame (dpyinfo, 0);
8843 deactivate_scroll_bars (f);
8847 if (f == dpyinfo->mouse_face_mouse_frame)
8849 /* If we move outside the frame, then we're
8850 certainly no longer on any text in the
8851 frame. */
8852 clear_mouse_face (dpyinfo);
8853 dpyinfo->mouse_face_mouse_frame = 0;
8856 /* Generate a nil HELP_EVENT to cancel a help-echo.
8857 Do it only if there's something to cancel.
8858 Otherwise, the startup message is cleared when the
8859 mouse leaves the frame. */
8860 if (any_help_event_p)
8861 do_help = -1;
8864 break;
8866 case keyDown:
8867 case autoKey:
8869 int keycode = (er.message & keyCodeMask) >> 8;
8870 int xkeysym;
8872 #if USE_CARBON_EVENTS
8873 /* When using Carbon Events, we need to pass raw keyboard
8874 events to the TSM ourselves. If TSM handles it, it
8875 will pass back noErr, otherwise it will pass back
8876 "eventNotHandledErr" and we can process it
8877 normally. */
8878 if ((!NILP (Vmac_pass_command_to_system)
8879 || !(er.modifiers & cmdKey))
8880 && (!NILP (Vmac_pass_control_to_system)
8881 || !(er.modifiers & controlKey)))
8882 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8883 != eventNotHandledErr)
8884 break;
8885 #endif
8887 #if TARGET_API_MAC_CARBON
8888 if (!IsValidWindowPtr (front_emacs_window ()))
8890 SysBeep (1);
8891 break;
8893 #endif
8895 ObscureCursor ();
8897 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8899 clear_mouse_face (dpyinfo);
8900 dpyinfo->mouse_face_hidden = 1;
8903 if (keycode_to_xkeysym (keycode, &xkeysym))
8905 inev.code = 0xff00 | xkeysym;
8906 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8908 else
8910 if (er.modifiers & (controlKey |
8911 (NILP (Vmac_command_key_is_meta) ? optionKey
8912 : cmdKey)))
8914 /* This code comes from Keyboard Resource,
8915 Appendix C of IM - Text. This is necessary
8916 since shift is ignored in KCHR table
8917 translation when option or command is pressed.
8918 It also does not translate correctly
8919 control-shift chars like C-% so mask off shift
8920 here also */
8921 int new_modifiers = er.modifiers & 0xe600;
8922 /* mask off option and command */
8923 int new_keycode = keycode | new_modifiers;
8924 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8925 unsigned long some_state = 0;
8926 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8927 &some_state) & 0xff;
8928 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
8930 /* When using the option key as an emacs modifier, convert
8931 the pressed key code back to one without the Mac option
8932 modifier applied. */
8933 int new_modifiers = er.modifiers & ~optionKey;
8934 int new_keycode = keycode | new_modifiers;
8935 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8936 unsigned long some_state = 0;
8937 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8938 &some_state) & 0xff;
8940 else
8941 inev.code = er.message & charCodeMask;
8942 inev.kind = ASCII_KEYSTROKE_EVENT;
8946 /* If variable mac-convert-keyboard-input-to-latin-1 is
8947 non-nil, convert non-ASCII characters typed at the Mac
8948 keyboard (presumed to be in the Mac Roman encoding) to
8949 iso-latin-1 encoding before they are passed to Emacs.
8950 This enables the Mac keyboard to be used to enter
8951 non-ASCII iso-latin-1 characters directly. */
8952 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
8953 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
8955 static TECObjectRef converter = NULL;
8956 OSStatus the_err = noErr;
8957 OSStatus convert_status = noErr;
8959 if (converter == NULL)
8961 the_err = TECCreateConverter (&converter,
8962 kTextEncodingMacRoman,
8963 mac_keyboard_text_encoding);
8964 current_mac_keyboard_text_encoding
8965 = mac_keyboard_text_encoding;
8967 else if (mac_keyboard_text_encoding
8968 != current_mac_keyboard_text_encoding)
8970 /* Free the converter for the current encoding
8971 before creating a new one. */
8972 TECDisposeConverter (converter);
8973 the_err = TECCreateConverter (&converter,
8974 kTextEncodingMacRoman,
8975 mac_keyboard_text_encoding);
8976 current_mac_keyboard_text_encoding
8977 = mac_keyboard_text_encoding;
8980 if (the_err == noErr)
8982 unsigned char ch = inev.code;
8983 ByteCount actual_input_length, actual_output_length;
8984 unsigned char outbuf[32];
8986 convert_status = TECConvertText (converter, &ch, 1,
8987 &actual_input_length,
8988 outbuf, 1,
8989 &actual_output_length);
8990 if (convert_status == noErr
8991 && actual_input_length == 1
8992 && actual_output_length == 1)
8993 inev.code = *outbuf;
8995 /* Reset internal states of the converter object.
8996 If it fails, create another one. */
8997 convert_status = TECFlushText (converter, outbuf,
8998 sizeof (outbuf),
8999 &actual_output_length);
9000 if (convert_status != noErr)
9002 TECDisposeConverter (converter);
9003 TECCreateConverter (&converter,
9004 kTextEncodingMacRoman,
9005 mac_keyboard_text_encoding);
9010 #if USE_CARBON_EVENTS
9011 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9012 #else
9013 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9014 #endif
9015 XSETFRAME (inev.frame_or_window,
9016 mac_window_to_frame (front_emacs_window ()));
9017 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
9018 break;
9020 case kHighLevelEvent:
9021 drag_and_drop_file_list = Qnil;
9023 AEProcessAppleEvent(&er);
9025 /* Build a DRAG_N_DROP_EVENT type event as is done in
9026 constuct_drag_n_drop in w32term.c. */
9027 if (!NILP (drag_and_drop_file_list))
9029 struct frame *f = NULL;
9030 WindowPtr wp;
9031 Lisp_Object frame;
9033 wp = front_emacs_window ();
9035 if (!wp)
9037 struct frame *f = XFRAME (XCAR (Vframe_list));
9038 CollapseWindow (FRAME_MAC_WINDOW (f), false);
9039 wp = front_emacs_window ();
9042 if (wp)
9043 f = mac_window_to_frame (wp);
9045 inev.kind = DRAG_N_DROP_EVENT;
9046 inev.code = 0;
9047 inev.timestamp = er.when * (1000 / 60);
9048 /* ticks to milliseconds */
9049 #if USE_CARBON_EVENTS
9050 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9051 #else
9052 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9053 #endif
9055 XSETINT (inev.x, 0);
9056 XSETINT (inev.y, 0);
9058 XSETFRAME (frame, f);
9059 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
9061 /* Regardless of whether Emacs was suspended or in the
9062 foreground, ask it to redraw its entire screen.
9063 Otherwise parts of the screen can be left in an
9064 inconsistent state. */
9065 if (wp)
9066 #if TARGET_API_MAC_CARBON
9068 Rect r;
9070 GetWindowPortBounds (wp, &r);
9071 InvalWindowRect (wp, &r);
9073 #else /* not TARGET_API_MAC_CARBON */
9074 InvalRect (&(wp->portRect));
9075 #endif /* not TARGET_API_MAC_CARBON */
9077 default:
9078 break;
9080 #if USE_CARBON_EVENTS
9081 ReleaseEvent (eventRef);
9082 #endif
9084 if (inev.kind != NO_EVENT)
9086 kbd_buffer_store_event_hold (&inev, hold_quit);
9087 count++;
9090 if (do_help
9091 && !(hold_quit && hold_quit->kind != NO_EVENT))
9093 Lisp_Object frame;
9095 if (f)
9096 XSETFRAME (frame, f);
9097 else
9098 frame = Qnil;
9100 if (do_help > 0)
9102 any_help_event_p = 1;
9103 gen_help_event (help_echo_string, frame, help_echo_window,
9104 help_echo_object, help_echo_pos);
9106 else
9108 help_echo_string = Qnil;
9109 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9111 count++;
9116 /* If the focus was just given to an autoraising frame,
9117 raise it now. */
9118 /* ??? This ought to be able to handle more than one such frame. */
9119 if (pending_autoraise_frame)
9121 x_raise_frame (pending_autoraise_frame);
9122 pending_autoraise_frame = 0;
9125 #if !TARGET_API_MAC_CARBON
9126 check_alarm (); /* simulate the handling of a SIGALRM */
9127 #endif
9129 UNBLOCK_INPUT;
9130 return count;
9134 /* Need to override CodeWarrior's input function so no conversion is
9135 done on newlines Otherwise compiled functions in .elc files will be
9136 read incorrectly. Defined in ...:MSL C:MSL
9137 Common:Source:buffer_io.c. */
9138 #ifdef __MWERKS__
9139 void
9140 __convert_to_newlines (unsigned char * p, size_t * n)
9142 #pragma unused(p,n)
9145 void
9146 __convert_from_newlines (unsigned char * p, size_t * n)
9148 #pragma unused(p,n)
9150 #endif
9152 #ifdef MAC_OS8
9153 void
9154 make_mac_terminal_frame (struct frame *f)
9156 Lisp_Object frame;
9157 Rect r;
9159 XSETFRAME (frame, f);
9161 f->output_method = output_mac;
9162 f->output_data.mac = (struct mac_output *)
9163 xmalloc (sizeof (struct mac_output));
9164 bzero (f->output_data.mac, sizeof (struct mac_output));
9166 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9168 FRAME_COLS (f) = 96;
9169 FRAME_LINES (f) = 4;
9171 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9172 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9174 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9176 f->output_data.mac->cursor_pixel = 0;
9177 f->output_data.mac->border_pixel = 0x00ff00;
9178 f->output_data.mac->mouse_pixel = 0xff00ff;
9179 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9181 f->output_data.mac->text_cursor = GetCursor (iBeamCursor);
9182 f->output_data.mac->nontext_cursor = &arrow_cursor;
9183 f->output_data.mac->modeline_cursor = &arrow_cursor;
9184 f->output_data.mac->hand_cursor = &arrow_cursor;
9185 f->output_data.mac->hourglass_cursor = GetCursor (watchCursor);
9186 f->output_data.mac->horizontal_drag_cursor = &arrow_cursor;
9188 FRAME_FONTSET (f) = -1;
9189 f->output_data.mac->explicit_parent = 0;
9190 f->left_pos = 8;
9191 f->top_pos = 32;
9192 f->border_width = 0;
9194 f->internal_border_width = 0;
9196 f->auto_raise = 1;
9197 f->auto_lower = 1;
9199 f->new_text_cols = 0;
9200 f->new_text_lines = 0;
9202 SetRect (&r, f->left_pos, f->top_pos,
9203 f->left_pos + FRAME_PIXEL_WIDTH (f),
9204 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9206 BLOCK_INPUT;
9208 if (!(FRAME_MAC_WINDOW (f) =
9209 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9210 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9211 abort ();
9212 /* so that update events can find this mac_output struct */
9213 f->output_data.mac->mFP = f; /* point back to emacs frame */
9215 UNBLOCK_INPUT;
9217 x_make_gc (f);
9219 /* Need to be initialized for unshow_buffer in window.c. */
9220 selected_window = f->selected_window;
9222 Fmodify_frame_parameters (frame,
9223 Fcons (Fcons (Qfont,
9224 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9225 Fmodify_frame_parameters (frame,
9226 Fcons (Fcons (Qforeground_color,
9227 build_string ("black")), Qnil));
9228 Fmodify_frame_parameters (frame,
9229 Fcons (Fcons (Qbackground_color,
9230 build_string ("white")), Qnil));
9232 #endif
9235 /***********************************************************************
9236 Initialization
9237 ***********************************************************************/
9239 int mac_initialized = 0;
9241 void
9242 mac_initialize_display_info ()
9244 struct mac_display_info *dpyinfo = &one_mac_display_info;
9245 GDHandle main_device_handle;
9247 bzero (dpyinfo, sizeof (*dpyinfo));
9249 #ifdef MAC_OSX
9250 dpyinfo->mac_id_name
9251 = (char *) xmalloc (SCHARS (Vinvocation_name)
9252 + SCHARS (Vsystem_name)
9253 + 2);
9254 sprintf (dpyinfo->mac_id_name, "%s@%s",
9255 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9256 #else
9257 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9258 strcpy (dpyinfo->mac_id_name, "Mac Display");
9259 #endif
9261 main_device_handle = LMGetMainDevice();
9263 dpyinfo->reference_count = 0;
9264 dpyinfo->resx = 75.0;
9265 dpyinfo->resy = 75.0;
9266 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
9267 #ifdef MAC_OSX
9268 /* HasDepth returns true if it is possible to have a 32 bit display,
9269 but this may not be what is actually used. Mac OSX can do better.
9270 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9271 header for CGGetActiveDisplayList says that the first display returned
9272 is the active one, so we use that. */
9274 CGDirectDisplayID disp_id[1];
9275 CGDisplayCount disp_count;
9276 CGDisplayErr error_code;
9278 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9279 if (error_code != 0)
9280 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9282 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9284 #else
9285 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9286 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9287 gdDevType, dpyinfo->color_p))
9288 break;
9289 #endif
9290 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9291 dpyinfo->width = (**main_device_handle).gdRect.right;
9292 dpyinfo->grabbed = 0;
9293 dpyinfo->root_window = NULL;
9294 dpyinfo->image_cache = make_image_cache ();
9296 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9297 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9298 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9299 dpyinfo->mouse_face_window = Qnil;
9300 dpyinfo->mouse_face_overlay = Qnil;
9301 dpyinfo->mouse_face_hidden = 0;
9304 /* Create an xrdb-style database of resources to supercede registry settings.
9305 The database is just a concatenation of C strings, finished by an additional
9306 \0. The string are submitted to some basic normalization, so
9308 [ *]option[ *]:[ *]value...
9310 becomes
9312 option:value...
9314 but any whitespace following value is not removed. */
9316 static char *
9317 mac_make_rdb (xrm_option)
9318 char *xrm_option;
9320 char *buffer = xmalloc (strlen (xrm_option) + 2);
9321 char *current = buffer;
9322 char ch;
9323 int in_option = 1;
9324 int before_value = 0;
9326 do {
9327 ch = *xrm_option++;
9329 if (ch == '\n')
9331 *current++ = '\0';
9332 in_option = 1;
9333 before_value = 0;
9335 else if (ch != ' ')
9337 *current++ = ch;
9338 if (in_option && (ch == ':'))
9340 in_option = 0;
9341 before_value = 1;
9343 else if (before_value)
9345 before_value = 0;
9348 else if (!(in_option || before_value))
9350 *current++ = ch;
9352 } while (ch);
9354 *current = '\0';
9356 return buffer;
9359 struct mac_display_info *
9360 mac_term_init (display_name, xrm_option, resource_name)
9361 Lisp_Object display_name;
9362 char *xrm_option;
9363 char *resource_name;
9365 struct mac_display_info *dpyinfo;
9367 BLOCK_INPUT;
9369 if (!mac_initialized)
9371 mac_initialize ();
9372 mac_initialized = 1;
9375 if (x_display_list)
9376 error ("Sorry, this version can only handle one display");
9378 mac_initialize_display_info ();
9380 dpyinfo = &one_mac_display_info;
9382 dpyinfo->xrdb = xrm_option ? mac_make_rdb (xrm_option) : NULL;
9384 /* Put this display on the chain. */
9385 dpyinfo->next = x_display_list;
9386 x_display_list = dpyinfo;
9388 /* Put it on x_display_name_list. */
9389 x_display_name_list = Fcons (Fcons (display_name, Qnil),
9390 x_display_name_list);
9391 dpyinfo->name_list_element = XCAR (x_display_name_list);
9393 UNBLOCK_INPUT;
9395 return dpyinfo;
9397 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9399 void
9400 x_delete_display (dpyinfo)
9401 struct mac_display_info *dpyinfo;
9403 int i;
9405 /* Discard this display from x_display_name_list and x_display_list.
9406 We can't use Fdelq because that can quit. */
9407 if (! NILP (x_display_name_list)
9408 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9409 x_display_name_list = XCDR (x_display_name_list);
9410 else
9412 Lisp_Object tail;
9414 tail = x_display_name_list;
9415 while (CONSP (tail) && CONSP (XCDR (tail)))
9417 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9419 XSETCDR (tail, XCDR (XCDR (tail)));
9420 break;
9422 tail = XCDR (tail);
9426 if (x_display_list == dpyinfo)
9427 x_display_list = dpyinfo->next;
9428 else
9430 struct x_display_info *tail;
9432 for (tail = x_display_list; tail; tail = tail->next)
9433 if (tail->next == dpyinfo)
9434 tail->next = tail->next->next;
9437 /* Free the font names in the font table. */
9438 for (i = 0; i < dpyinfo->n_fonts; i++)
9439 if (dpyinfo->font_table[i].name)
9441 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9442 xfree (dpyinfo->font_table[i].full_name);
9443 xfree (dpyinfo->font_table[i].name);
9446 if (dpyinfo->font_table->font_encoder)
9447 xfree (dpyinfo->font_table->font_encoder);
9449 xfree (dpyinfo->font_table);
9450 xfree (dpyinfo->mac_id_name);
9452 if (x_display_list == 0)
9454 mac_clear_font_name_table ();
9455 bzero (dpyinfo, sizeof (*dpyinfo));
9460 #ifdef MAC_OSX
9461 void
9462 mac_check_bundle()
9464 extern int inhibit_window_system;
9465 extern int noninteractive;
9466 CFBundleRef appsBundle;
9467 pid_t child;
9469 /* No need to test if already -nw*/
9470 if (inhibit_window_system || noninteractive)
9471 return;
9473 appsBundle = CFBundleGetMainBundle();
9474 if (appsBundle != NULL)
9476 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9477 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9478 /* We found the bundle identifier, now we know we are valid. */
9479 if (res != NULL)
9481 CFRelease(res);
9482 return;
9485 /* MAC_TODO: Have this start the bundled executable */
9487 /* For now, prevent the fatal error by bringing it up in the terminal */
9488 inhibit_window_system = 1;
9491 void
9492 MakeMeTheFrontProcess ()
9494 ProcessSerialNumber psn;
9495 OSErr err;
9497 err = GetCurrentProcess (&psn);
9498 if (err == noErr)
9499 (void) SetFrontProcess (&psn);
9502 /***** Code to handle C-g testing *****/
9504 /* Contains the Mac modifier formed from quit_char */
9505 static mac_quit_char_modifiers = 0;
9506 static mac_quit_char_keycode;
9507 extern int quit_char;
9509 static void
9510 mac_determine_quit_char_modifiers()
9512 /* Todo: Determine modifiers from quit_char. */
9513 UInt32 qc_modifiers = ctrl_modifier;
9515 /* Map modifiers */
9516 mac_quit_char_modifiers = 0;
9517 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9518 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9519 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9520 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9523 static void
9524 init_quit_char_handler ()
9526 /* TODO: Let this support keys other the 'g' */
9527 mac_quit_char_keycode = 5;
9528 /* Look at <architecture/adb_kb_map.h> for details */
9529 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9531 mac_determine_quit_char_modifiers();
9534 static Boolean
9535 quit_char_comp (EventRef inEvent, void *inCompData)
9537 if (GetEventClass(inEvent) != kEventClassKeyboard)
9538 return false;
9539 if (GetEventKind(inEvent) != kEventRawKeyDown)
9540 return false;
9542 UInt32 keyCode;
9543 UInt32 keyModifiers;
9544 GetEventParameter(inEvent, kEventParamKeyCode,
9545 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9546 if (keyCode != mac_quit_char_keycode)
9547 return false;
9548 GetEventParameter(inEvent, kEventParamKeyModifiers,
9549 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9550 if (keyModifiers != mac_quit_char_modifiers)
9551 return false;
9553 return true;
9556 void
9557 mac_check_for_quit_char ()
9559 EventRef event;
9560 static EMACS_TIME last_check_time = { 0, 0 };
9561 static EMACS_TIME one_second = { 1, 0 };
9562 EMACS_TIME now, t;
9564 /* If windows are not initialized, return immediately (keep it bouncin'). */
9565 if (!mac_quit_char_modifiers)
9566 return;
9568 /* Don't check if last check is less than a second ago. */
9569 EMACS_GET_TIME (now);
9570 EMACS_SUB_TIME (t, now, last_check_time);
9571 if (EMACS_TIME_LT (t, one_second))
9572 return;
9573 last_check_time = now;
9575 /* Redetermine modifiers because they are based on lisp variables */
9576 mac_determine_quit_char_modifiers ();
9578 /* Fill the queue with events */
9579 BLOCK_INPUT;
9580 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9581 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9582 NULL);
9583 UNBLOCK_INPUT;
9584 if (event)
9586 struct input_event e;
9588 /* Use an input_event to emulate what the interrupt handler does. */
9589 EVENT_INIT (e);
9590 e.kind = ASCII_KEYSTROKE_EVENT;
9591 e.code = quit_char;
9592 e.arg = Qnil;
9593 e.modifiers = NULL;
9594 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9595 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9596 /* Remove event from queue to prevent looping. */
9597 RemoveEventFromQueue (GetMainEventQueue (), event);
9598 ReleaseEvent (event);
9599 kbd_buffer_store_event (&e);
9603 #endif /* MAC_OSX */
9605 /* Set up use of X before we make the first connection. */
9607 extern frame_parm_handler mac_frame_parm_handlers[];
9609 static struct redisplay_interface x_redisplay_interface =
9611 mac_frame_parm_handlers,
9612 x_produce_glyphs,
9613 x_write_glyphs,
9614 x_insert_glyphs,
9615 x_clear_end_of_line,
9616 x_scroll_run,
9617 x_after_update_window_line,
9618 x_update_window_begin,
9619 x_update_window_end,
9620 x_cursor_to,
9621 x_flush,
9622 0, /* flush_display_optional */
9623 x_clear_window_mouse_face,
9624 x_get_glyph_overhangs,
9625 x_fix_overlapping_area,
9626 x_draw_fringe_bitmap,
9627 0, /* define_fringe_bitmap */
9628 0, /* destroy_fringe_bitmap */
9629 mac_per_char_metric,
9630 mac_encode_char,
9631 NULL, /* mac_compute_glyph_string_overhangs */
9632 x_draw_glyph_string,
9633 mac_define_frame_cursor,
9634 mac_clear_frame_area,
9635 mac_draw_window_cursor,
9636 mac_draw_vertical_window_border,
9637 mac_shift_glyphs_for_insert
9640 void
9641 mac_initialize ()
9643 rif = &x_redisplay_interface;
9645 clear_frame_hook = x_clear_frame;
9646 ins_del_lines_hook = x_ins_del_lines;
9647 delete_glyphs_hook = x_delete_glyphs;
9648 ring_bell_hook = XTring_bell;
9649 reset_terminal_modes_hook = XTreset_terminal_modes;
9650 set_terminal_modes_hook = XTset_terminal_modes;
9651 update_begin_hook = x_update_begin;
9652 update_end_hook = x_update_end;
9653 set_terminal_window_hook = XTset_terminal_window;
9654 read_socket_hook = XTread_socket;
9655 frame_up_to_date_hook = XTframe_up_to_date;
9656 mouse_position_hook = XTmouse_position;
9657 frame_rehighlight_hook = XTframe_rehighlight;
9658 frame_raise_lower_hook = XTframe_raise_lower;
9660 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9661 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9662 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9663 judge_scroll_bars_hook = XTjudge_scroll_bars;
9665 scroll_region_ok = 1; /* we'll scroll partial frames */
9666 char_ins_del_ok = 1;
9667 line_ins_del_ok = 1; /* we'll just blt 'em */
9668 fast_clear_end_of_line = 1; /* X does this well */
9669 memory_below_frame = 0; /* we don't remember what scrolls
9670 off the bottom */
9671 baud_rate = 19200;
9673 x_noop_count = 0;
9674 last_tool_bar_item = -1;
9675 any_help_event_p = 0;
9677 /* Try to use interrupt input; if we can't, then start polling. */
9678 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9680 #ifdef USE_X_TOOLKIT
9681 XtToolkitInitialize ();
9682 Xt_app_con = XtCreateApplicationContext ();
9683 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9685 /* Install an asynchronous timer that processes Xt timeout events
9686 every 0.1s. This is necessary because some widget sets use
9687 timeouts internally, for example the LessTif menu bar, or the
9688 Xaw3d scroll bar. When Xt timouts aren't processed, these
9689 widgets don't behave normally. */
9691 EMACS_TIME interval;
9692 EMACS_SET_SECS_USECS (interval, 0, 100000);
9693 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9695 #endif
9697 #if USE_TOOLKIT_SCROLL_BARS
9698 xaw3d_arrow_scroll = False;
9699 xaw3d_pick_top = True;
9700 #endif
9702 #if 0
9703 /* Note that there is no real way portable across R3/R4 to get the
9704 original error handler. */
9705 XSetErrorHandler (x_error_handler);
9706 XSetIOErrorHandler (x_io_error_quitter);
9708 /* Disable Window Change signals; they are handled by X events. */
9709 #ifdef SIGWINCH
9710 signal (SIGWINCH, SIG_DFL);
9711 #endif /* ! defined (SIGWINCH) */
9713 signal (SIGPIPE, x_connection_signal);
9714 #endif
9716 BLOCK_INPUT;
9718 #if TARGET_API_MAC_CARBON
9719 init_required_apple_events ();
9721 #if USE_CARBON_EVENTS
9722 init_service_handler ();
9724 init_quit_char_handler ();
9725 #endif
9727 DisableMenuCommand (NULL, kHICommandQuit);
9729 if (!inhibit_window_system)
9730 MakeMeTheFrontProcess ();
9731 #endif
9732 UNBLOCK_INPUT;
9736 void
9737 syms_of_macterm ()
9739 #if 0
9740 staticpro (&x_error_message_string);
9741 x_error_message_string = Qnil;
9742 #endif
9744 Qmodifier_value = intern ("modifier-value");
9745 Qalt = intern ("alt");
9746 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9747 Qhyper = intern ("hyper");
9748 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9749 Qsuper = intern ("super");
9750 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9752 #ifdef MAC_OSX
9753 Fprovide (intern ("mac-carbon"), Qnil);
9754 #endif
9756 staticpro (&Qreverse);
9757 Qreverse = intern ("reverse");
9759 staticpro (&x_display_name_list);
9760 x_display_name_list = Qnil;
9762 staticpro (&last_mouse_scroll_bar);
9763 last_mouse_scroll_bar = Qnil;
9765 staticpro (&Qvendor_specific_keysyms);
9766 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9768 staticpro (&last_mouse_press_frame);
9769 last_mouse_press_frame = Qnil;
9771 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9772 staticpro (&Qmac_ready_for_drag_n_drop);
9774 Qbig5 = intern ("big5");
9775 staticpro (&Qbig5);
9777 Qcn_gb = intern ("cn-gb");
9778 staticpro (&Qcn_gb);
9780 Qsjis = intern ("sjis");
9781 staticpro (&Qsjis);
9783 Qeuc_kr = intern ("euc-kr");
9784 staticpro (&Qeuc_kr);
9786 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9787 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9788 x_autoselect_window_p = 0;
9790 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9791 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9792 Vx_toolkit_scroll_bars = Qt;
9794 DEFVAR_BOOL ("x-use-underline-position-properties",
9795 &x_use_underline_position_properties,
9796 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9797 nil means ignore them. If you encounter fonts with bogus
9798 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9799 to 4.1, set this to nil. */);
9800 x_use_underline_position_properties = 0;
9802 staticpro (&last_mouse_motion_frame);
9803 last_mouse_motion_frame = Qnil;
9805 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9806 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9807 Otherwise the option key is used. */);
9808 Vmac_command_key_is_meta = Qt;
9810 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9811 doc: /* Modifier to use for the Mac alt/option key. The value can
9812 be alt, hyper, or super for the respective modifier. If the value is
9813 nil then the key will act as the normal Mac option modifier. */);
9814 Vmac_option_modifier = Qnil;
9816 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9817 doc: /* Non-nil means that the control and meta keys are reversed. This is
9818 useful for non-standard keyboard layouts. */);
9819 Vmac_reverse_ctrl_meta = Qnil;
9821 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9822 &Vmac_emulate_three_button_mouse,
9823 doc: /* t means that when the option-key is held down while pressing the
9824 mouse button, the click will register as mouse-2 and while the
9825 command-key is held down, the click will register as mouse-3.
9826 'reverse means that the the option-key will register for mouse-3
9827 and the command-key will register for mouse-2. nil means that
9828 not emulation should be done and the modifiers should be placed
9829 on the mouse-1 event. */);
9830 Vmac_emulate_three_button_mouse = Qnil;
9832 #if USE_CARBON_EVENTS
9833 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9834 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9835 the right click will be mouse-3.
9836 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9837 Vmac_wheel_button_is_mouse_2 = Qt;
9839 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9840 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9841 Toolbox for processing before Emacs sees it. */);
9842 Vmac_pass_command_to_system = Qt;
9844 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9845 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9846 Toolbox for processing before Emacs sees it. */);
9847 Vmac_pass_control_to_system = Qt;
9848 #endif
9850 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9851 doc: /* One of the Text Encoding Base constant values defined in the
9852 Basic Text Constants section of Inside Macintosh - Text Encoding
9853 Conversion Manager. Its value determines the encoding characters
9854 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9855 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9856 its default value, no conversion takes place. If it is set to
9857 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9858 characters typed on Mac keyboard are first converted into the
9859 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9860 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9861 command, this enables the Mac keyboard to be used to enter non-ASCII
9862 characters directly. */);
9863 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9866 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9867 (do not change this comment) */