(enriched-mode): Specify :group.
[emacs.git] / src / macterm.c
blob67a3f1e010734eaa0698c72ff7fb463d810939af
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
31 #include "macterm.h"
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
37 #if TARGET_API_MAC_CARBON
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 TARGET_API_MAC_CARBON */
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 TARGET_API_MAC_CARBON */
63 #include "systty.h"
64 #include "systime.h"
65 #include "atimer.h"
66 #include "keymap.h"
68 #include <ctype.h>
69 #include <errno.h>
70 #include <setjmp.h>
71 #include <sys/stat.h>
72 #include <sys/param.h>
74 #include "keyboard.h"
75 #include "frame.h"
76 #include "dispextern.h"
77 #include "fontset.h"
78 #include "termhooks.h"
79 #include "termopts.h"
80 #include "termchar.h"
81 #include "gnu.h"
82 #include "disptab.h"
83 #include "buffer.h"
84 #include "window.h"
85 #include "intervals.h"
86 #include "composite.h"
87 #include "coding.h"
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
95 : controlKey)
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
100 /* Non-nil means Emacs uses toolkit scroll bars. */
102 Lisp_Object Vx_toolkit_scroll_bars;
104 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
105 Lisp_Object Vmac_use_core_graphics;
108 /* Non-zero means that a HELP_EVENT has been generated since Emacs
109 start. */
111 static int any_help_event_p;
113 /* Non-zero means autoselect window with the mouse cursor. */
115 int x_autoselect_window_p;
117 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
119 int x_use_underline_position_properties;
121 /* Non-zero means draw block and hollow cursor as wide as the glyph
122 under it. For example, if a block cursor is over a tab, it will be
123 drawn as wide as that tab on the display. */
126 /* This is a chain of structures for all the X displays currently in
127 use. */
129 struct x_display_info *x_display_list;
131 /* This is a list of cons cells, each of the form (NAME
132 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
133 x_display_list and in the same order. NAME is the name of the
134 frame. FONT-LIST-CACHE records previous values returned by
135 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
136 equivalent, which is implemented with a Lisp object, for the
137 display. */
139 Lisp_Object x_display_name_list;
141 /* This is display since Mac does not support multiple ones. */
142 struct mac_display_info one_mac_display_info;
144 /* Frame being updated by update_frame. This is declared in term.c.
145 This is set by update_begin and looked at by all the XT functions.
146 It is zero while not inside an update. In that case, the XT
147 functions assume that `selected_frame' is the frame to apply to. */
149 extern struct frame *updating_frame;
151 extern int waiting_for_input;
153 /* This is a frame waiting to be auto-raised, within XTread_socket. */
155 struct frame *pending_autoraise_frame;
157 /* Non-zero means user is interacting with a toolkit scroll bar. */
159 static int toolkit_scroll_bar_interaction;
161 /* Mouse movement.
163 Formerly, we used PointerMotionHintMask (in standard_event_mask)
164 so that we would have to call XQueryPointer after each MotionNotify
165 event to ask for another such event. However, this made mouse tracking
166 slow, and there was a bug that made it eventually stop.
168 Simply asking for MotionNotify all the time seems to work better.
170 In order to avoid asking for motion events and then throwing most
171 of them away or busy-polling the server for mouse positions, we ask
172 the server for pointer motion hints. This means that we get only
173 one event per group of mouse movements. "Groups" are delimited by
174 other kinds of events (focus changes and button clicks, for
175 example), or by XQueryPointer calls; when one of these happens, we
176 get another MotionNotify event the next time the mouse moves. This
177 is at least as efficient as getting motion events when mouse
178 tracking is on, and I suspect only negligibly worse when tracking
179 is off. */
181 /* Where the mouse was last time we reported a mouse event. */
183 static Rect last_mouse_glyph;
184 static Lisp_Object last_mouse_press_frame;
186 /* The scroll bar in which the last X motion event occurred.
188 If the last X motion event occurred in a scroll bar, we set this so
189 XTmouse_position can know whether to report a scroll bar motion or
190 an ordinary motion.
192 If the last X motion event didn't occur in a scroll bar, we set
193 this to Qnil, to tell XTmouse_position to return an ordinary motion
194 event. */
196 static Lisp_Object last_mouse_scroll_bar;
198 /* This is a hack. We would really prefer that XTmouse_position would
199 return the time associated with the position it returns, but there
200 doesn't seem to be any way to wrest the time-stamp from the server
201 along with the position query. So, we just keep track of the time
202 of the last movement we received, and return that in hopes that
203 it's somewhat accurate. */
205 static Time last_mouse_movement_time;
207 struct scroll_bar *tracked_scroll_bar = NULL;
209 /* Incremented by XTread_socket whenever it really tries to read
210 events. */
212 #ifdef __STDC__
213 static int volatile input_signal_count;
214 #else
215 static int input_signal_count;
216 #endif
218 /* Used locally within XTread_socket. */
220 static int x_noop_count;
222 /* Initial values of argv and argc. */
224 extern char **initial_argv;
225 extern int initial_argc;
227 extern Lisp_Object Vcommand_line_args, Vsystem_name;
229 /* Tells if a window manager is present or not. */
231 extern Lisp_Object Vx_no_window_manager;
233 extern int errno;
235 /* A mask of extra modifier bits to put into every keyboard char. */
237 extern int extra_keyboard_modifiers;
239 /* The keysyms to use for the various modifiers. */
241 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
243 static Lisp_Object Qvendor_specific_keysyms;
245 #if 0
246 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
247 #endif
249 extern int inhibit_window_system;
251 #if __MRC__ && !TARGET_API_MAC_CARBON
252 QDGlobals qd; /* QuickDraw global information structure. */
253 #endif
256 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
257 struct mac_display_info *mac_display_info_for_display (Display *);
258 static void x_update_window_end P_ ((struct window *, int, int));
259 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
260 static int x_io_error_quitter P_ ((Display *));
261 int x_catch_errors P_ ((Display *));
262 void x_uncatch_errors P_ ((Display *, int));
263 void x_lower_frame P_ ((struct frame *));
264 void x_scroll_bar_clear P_ ((struct frame *));
265 int x_had_errors_p P_ ((Display *));
266 void x_wm_set_size_hint P_ ((struct frame *, long, int));
267 void x_raise_frame P_ ((struct frame *));
268 void x_set_window_size P_ ((struct frame *, int, int, int));
269 void x_wm_set_window_state P_ ((struct frame *, int));
270 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
271 void mac_initialize P_ ((void));
272 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
273 static int x_compute_min_glyph_bounds P_ ((struct frame *));
274 static void x_update_end P_ ((struct frame *));
275 static void XTframe_up_to_date P_ ((struct frame *));
276 static void XTreassert_line_highlight P_ ((int, int));
277 static void x_change_line_highlight P_ ((int, int, int, int));
278 static void XTset_terminal_modes P_ ((void));
279 static void XTreset_terminal_modes P_ ((void));
280 static void x_clear_frame P_ ((void));
281 static void frame_highlight P_ ((struct frame *));
282 static void frame_unhighlight P_ ((struct frame *));
283 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
284 static void XTframe_rehighlight P_ ((struct frame *));
285 static void x_frame_rehighlight P_ ((struct x_display_info *));
286 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
287 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
288 enum text_cursor_kinds));
290 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
291 static void x_flush P_ ((struct frame *f));
292 static void x_update_begin P_ ((struct frame *));
293 static void x_update_window_begin P_ ((struct window *));
294 static void x_after_update_window_line P_ ((struct glyph_row *));
296 static int is_emacs_window (WindowPtr);
298 int x_bitmap_icon (struct frame *, Lisp_Object);
299 void x_make_frame_visible (struct frame *);
301 extern void window_scroll (Lisp_Object, int, int, int);
303 /* Defined in macmenu.h. */
304 extern void menubar_selection_callback (FRAME_PTR, int);
305 extern void set_frame_menubar (FRAME_PTR, int, int);
307 /* X display function emulation */
309 void
310 XFreePixmap (display, pixmap)
311 Display *display; /* not used */
312 Pixmap pixmap;
314 DisposeGWorld (pixmap);
318 /* Set foreground color for subsequent QuickDraw commands. Assume
319 graphic port has already been set. */
321 static void
322 mac_set_forecolor (unsigned long color)
324 RGBColor fg_color;
326 fg_color.red = RED16_FROM_ULONG (color);
327 fg_color.green = GREEN16_FROM_ULONG (color);
328 fg_color.blue = BLUE16_FROM_ULONG (color);
330 RGBForeColor (&fg_color);
334 /* Set background color for subsequent QuickDraw commands. Assume
335 graphic port has already been set. */
337 static void
338 mac_set_backcolor (unsigned long color)
340 RGBColor bg_color;
342 bg_color.red = RED16_FROM_ULONG (color);
343 bg_color.green = GREEN16_FROM_ULONG (color);
344 bg_color.blue = BLUE16_FROM_ULONG (color);
346 RGBBackColor (&bg_color);
349 /* Set foreground and background color for subsequent QuickDraw
350 commands. Assume that the graphic port has already been set. */
352 static void
353 mac_set_colors (gc, bg_save)
354 GC gc;
355 RGBColor *bg_save;
357 if (bg_save)
358 GetBackColor (bg_save);
359 mac_set_forecolor (gc->foreground);
360 mac_set_backcolor (gc->background);
363 /* Mac version of XDrawLine. */
365 static void
366 XDrawLine (display, w, gc, x1, y1, x2, y2)
367 Display *display;
368 WindowPtr w;
369 GC gc;
370 int x1, y1, x2, y2;
372 RGBColor old_bg;
374 SetPortWindowPort (w);
376 mac_set_colors (gc, &old_bg);
378 MoveTo (x1, y1);
379 LineTo (x2, y2);
381 RGBBackColor (&old_bg);
384 void
385 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
386 Display *display;
387 Pixmap p;
388 GC gc;
389 int x1, y1, x2, y2;
391 CGrafPtr old_port;
392 GDHandle old_gdh;
394 GetGWorld (&old_port, &old_gdh);
395 SetGWorld (p, NULL);
397 mac_set_colors (gc, NULL);
399 LockPixels (GetGWorldPixMap (p));
400 MoveTo (x1, y1);
401 LineTo (x2, y2);
402 UnlockPixels (GetGWorldPixMap (p));
404 SetGWorld (old_port, old_gdh);
407 /* Mac version of XClearArea. */
409 void
410 XClearArea (display, w, x, y, width, height, exposures)
411 Display *display;
412 WindowPtr w;
413 int x, y;
414 unsigned int width, height;
415 int exposures;
417 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
418 Rect r;
419 XGCValues xgc;
420 RGBColor old_bg;
422 xgc.foreground = mwp->x_compatible.foreground_pixel;
423 xgc.background = mwp->x_compatible.background_pixel;
425 SetPortWindowPort (w);
427 mac_set_colors (&xgc, &old_bg);
428 SetRect (&r, x, y, x + width, y + height);
430 EraseRect (&r);
432 RGBBackColor (&old_bg);
435 /* Mac version of XClearWindow. */
437 static void
438 XClearWindow (display, w)
439 Display *display;
440 WindowPtr w;
442 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
443 XGCValues xgc;
445 xgc.foreground = mwp->x_compatible.foreground_pixel;
446 xgc.background = mwp->x_compatible.background_pixel;
448 SetPortWindowPort (w);
450 mac_set_colors (&xgc, NULL);
452 #if TARGET_API_MAC_CARBON
454 Rect r;
456 GetWindowPortBounds (w, &r);
457 EraseRect (&r);
459 #else /* not TARGET_API_MAC_CARBON */
460 EraseRect (&(w->portRect));
461 #endif /* not TARGET_API_MAC_CARBON */
465 /* Mac replacement for XCopyArea. */
467 static void
468 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
469 Display *display;
470 WindowPtr w;
471 GC gc;
472 int x, y, width, height;
473 unsigned short *bits;
474 int overlay_p;
476 BitMap bitmap;
477 Rect r;
478 RGBColor old_bg;
480 bitmap.rowBytes = sizeof(unsigned short);
481 bitmap.baseAddr = (char *)bits;
482 SetRect (&(bitmap.bounds), 0, 0, width, height);
484 SetPortWindowPort (w);
486 mac_set_colors (gc, &old_bg);
487 SetRect (&r, x, y, x + width, y + height);
489 #if TARGET_API_MAC_CARBON
490 LockPortBits (GetWindowPort (w));
491 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
492 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
493 UnlockPortBits (GetWindowPort (w));
494 #else /* not TARGET_API_MAC_CARBON */
495 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
496 overlay_p ? srcOr : srcCopy, 0);
497 #endif /* not TARGET_API_MAC_CARBON */
499 RGBBackColor (&old_bg);
503 /* Mac replacement for XSetClipRectangles. */
505 static void
506 mac_set_clip_rectangle (display, w, r)
507 Display *display;
508 WindowPtr w;
509 Rect *r;
511 SetPortWindowPort (w);
513 ClipRect (r);
517 /* Mac replacement for XSetClipMask. */
519 static void
520 mac_reset_clipping (display, w)
521 Display *display;
522 WindowPtr w;
524 Rect r;
526 SetPortWindowPort (w);
528 SetRect (&r, -32767, -32767, 32767, 32767);
529 ClipRect (&r);
533 /* Mac replacement for XCreateBitmapFromBitmapData. */
535 static void
536 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
537 BitMap *bitmap;
538 char *bits;
539 int w, h;
541 static unsigned char swap_nibble[16]
542 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
543 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
544 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
545 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
546 int i, j, w1;
547 char *p;
549 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
550 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
551 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
552 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
553 for (i = 0; i < h; i++)
555 p = bitmap->baseAddr + i * bitmap->rowBytes;
556 for (j = 0; j < w1; j++)
558 /* Bitswap XBM bytes to match how Mac does things. */
559 unsigned char c = *bits++;
560 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
561 | (swap_nibble[(c>>4) & 0xf]));;
565 SetRect (&(bitmap->bounds), 0, 0, w, h);
569 static void
570 mac_free_bitmap (bitmap)
571 BitMap *bitmap;
573 xfree (bitmap->baseAddr);
577 Pixmap
578 XCreatePixmap (display, w, width, height, depth)
579 Display *display; /* not used */
580 WindowPtr w;
581 unsigned int width, height;
582 unsigned int depth;
584 Pixmap pixmap;
585 Rect r;
586 QDErr err;
588 SetPortWindowPort (w);
590 SetRect (&r, 0, 0, width, height);
591 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
592 if (err != noErr)
593 return NULL;
594 return pixmap;
598 Pixmap
599 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
600 Display *display; /* not used */
601 WindowPtr w;
602 char *data;
603 unsigned int width, height;
604 unsigned long fg, bg;
605 unsigned int depth; /* not used */
607 Pixmap pixmap;
608 BitMap bitmap;
609 CGrafPtr old_port;
610 GDHandle old_gdh;
612 pixmap = XCreatePixmap (display, w, width, height, depth);
613 if (pixmap == NULL)
614 return NULL;
616 GetGWorld (&old_port, &old_gdh);
617 SetGWorld (pixmap, NULL);
618 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
619 mac_set_forecolor (fg);
620 mac_set_backcolor (bg);
621 LockPixels (GetGWorldPixMap (pixmap));
622 #if TARGET_API_MAC_CARBON
623 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
624 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
625 #else /* not TARGET_API_MAC_CARBON */
626 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
627 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
628 #endif /* not TARGET_API_MAC_CARBON */
629 UnlockPixels (GetGWorldPixMap (pixmap));
630 SetGWorld (old_port, old_gdh);
631 mac_free_bitmap (&bitmap);
633 return pixmap;
637 /* Mac replacement for XFillRectangle. */
639 static void
640 XFillRectangle (display, w, gc, x, y, width, height)
641 Display *display;
642 WindowPtr w;
643 GC gc;
644 int x, y;
645 unsigned int width, height;
647 Rect r;
648 RGBColor old_bg;
650 SetPortWindowPort (w);
652 mac_set_colors (gc, &old_bg);
653 SetRect (&r, x, y, x + width, y + height);
655 PaintRect (&r); /* using foreground color of gc */
657 RGBBackColor (&old_bg);
661 #if 0 /* TODO: figure out if we need to do this on Mac. */
662 static void
663 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
664 Display *display;
665 Pixmap p;
666 GC gc;
667 int x, y;
668 unsigned int width, height;
670 CGrafPtr old_port;
671 GDHandle old_gdh;
672 Rect r;
674 GetGWorld (&old_port, &old_gdh);
675 SetGWorld (p, NULL);
676 mac_set_colors (gc, NULL);
677 SetRect (&r, x, y, x + width, y + height);
679 LockPixels (GetGWorldPixMap (p));
680 PaintRect (&r); /* using foreground color of gc */
681 UnlockPixels (GetGWorldPixMap (p));
683 SetGWorld (old_port, old_gdh);
685 #endif
688 /* Mac replacement for XDrawRectangle: dest is a window. */
690 static void
691 mac_draw_rectangle (display, w, gc, x, y, width, height)
692 Display *display;
693 WindowPtr w;
694 GC gc;
695 int x, y;
696 unsigned int width, height;
698 Rect r;
699 RGBColor old_bg;
701 SetPortWindowPort (w);
703 mac_set_colors (gc, &old_bg);
704 SetRect (&r, x, y, x + width + 1, y + height + 1);
706 FrameRect (&r); /* using foreground color of gc */
708 RGBBackColor (&old_bg);
712 #if 0 /* TODO: figure out if we need to do this on Mac. */
713 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
715 static void
716 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
717 Display *display;
718 Pixmap p;
719 GC gc;
720 int x, y;
721 unsigned int width, height;
723 CGrafPtr old_port;
724 GDHandle old_gdh;
725 Rect r;
727 GetGWorld (&old_port, &old_gdh);
728 SetGWorld (p, NULL);
729 mac_set_colors (gc, NULL);
730 SetRect (&r, x, y, x + width + 1, y + height + 1);
732 LockPixels (GetGWorldPixMap (p));
733 FrameRect (&r); /* using foreground color of gc */
734 UnlockPixels (GetGWorldPixMap (p));
736 SetGWorld (old_port, old_gdh);
738 #endif
741 static void
742 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
743 bytes_per_char)
744 Display *display;
745 WindowPtr w;
746 GC gc;
747 int x, y;
748 char *buf;
749 int nchars, mode, bytes_per_char;
751 RGBColor old_bg;
753 SetPortWindowPort (w);
754 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
755 UInt32 textFlags, savedFlags;
756 if (!NILP(Vmac_use_core_graphics)) {
757 textFlags = kQDUseCGTextRendering;
758 savedFlags = SwapQDTextFlags(textFlags);
760 #endif
762 mac_set_colors (gc, &old_bg);
764 TextFont (gc->font->mac_fontnum);
765 TextSize (gc->font->mac_fontsize);
766 TextFace (gc->font->mac_fontface);
767 TextMode (mode);
769 MoveTo (x, y);
770 DrawText (buf, 0, nchars * bytes_per_char);
772 RGBBackColor (&old_bg);
773 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
774 if (!NILP(Vmac_use_core_graphics))
775 SwapQDTextFlags(savedFlags);
776 #endif
780 /* Mac replacement for XDrawString. */
782 static void
783 XDrawString (display, w, gc, x, y, buf, nchars)
784 Display *display;
785 WindowPtr w;
786 GC gc;
787 int x, y;
788 char *buf;
789 int nchars;
791 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
795 /* Mac replacement for XDrawString16. */
797 static void
798 XDrawString16 (display, w, gc, x, y, buf, nchars)
799 Display *display;
800 WindowPtr w;
801 GC gc;
802 int x, y;
803 XChar2b *buf;
804 int nchars;
806 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
811 /* Mac replacement for XDrawImageString. */
813 static void
814 XDrawImageString (display, w, gc, x, y, buf, nchars)
815 Display *display;
816 WindowPtr w;
817 GC gc;
818 int x, y;
819 char *buf;
820 int nchars;
822 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
826 /* Mac replacement for XDrawString16. */
828 static void
829 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
830 Display *display;
831 WindowPtr w;
832 GC gc;
833 int x, y;
834 XChar2b *buf;
835 int nchars;
837 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
842 /* Mac replacement for XCopyArea: dest must be window. */
844 static void
845 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
846 dest_y)
847 Display *display;
848 Pixmap src;
849 WindowPtr dest;
850 GC gc;
851 int src_x, src_y;
852 unsigned int width, height;
853 int dest_x, dest_y;
855 Rect src_r, dest_r;
857 SetPortWindowPort (dest);
859 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
860 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
862 ForeColor (blackColor);
863 BackColor (whiteColor);
865 LockPixels (GetGWorldPixMap (src));
866 #if TARGET_API_MAC_CARBON
867 LockPortBits (GetWindowPort (dest));
868 CopyBits (GetPortBitMapForCopyBits (src),
869 GetPortBitMapForCopyBits (GetWindowPort (dest)),
870 &src_r, &dest_r, srcCopy, 0);
871 UnlockPortBits (GetWindowPort (dest));
872 #else /* not TARGET_API_MAC_CARBON */
873 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
874 &src_r, &dest_r, srcCopy, 0);
875 #endif /* not TARGET_API_MAC_CARBON */
876 UnlockPixels (GetGWorldPixMap (src));
880 static void
881 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
882 width, height, dest_x, dest_y)
883 Display *display;
884 Pixmap src, mask;
885 WindowPtr dest;
886 GC gc;
887 int src_x, src_y;
888 unsigned int width, height;
889 int dest_x, dest_y;
891 Rect src_r, dest_r;
893 SetPortWindowPort (dest);
895 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
896 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
898 ForeColor (blackColor);
899 BackColor (whiteColor);
901 LockPixels (GetGWorldPixMap (src));
902 LockPixels (GetGWorldPixMap (mask));
903 #if TARGET_API_MAC_CARBON
904 LockPortBits (GetWindowPort (dest));
905 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
906 GetPortBitMapForCopyBits (GetWindowPort (dest)),
907 &src_r, &src_r, &dest_r);
908 UnlockPortBits (GetWindowPort (dest));
909 #else /* not TARGET_API_MAC_CARBON */
910 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
911 &(dest->portBits), &src_r, &src_r, &dest_r);
912 #endif /* not TARGET_API_MAC_CARBON */
913 UnlockPixels (GetGWorldPixMap (mask));
914 UnlockPixels (GetGWorldPixMap (src));
918 #if 0
919 /* Convert a pair of local coordinates to global (screen) coordinates.
920 Assume graphic port has been properly set. */
921 static void
922 local_to_global_coord (short *h, short *v)
924 Point p;
926 p.h = *h;
927 p.v = *v;
929 LocalToGlobal (&p);
931 *h = p.h;
932 *v = p.v;
934 #endif
936 /* Mac replacement for XCopyArea: used only for scrolling. */
938 static void
939 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
940 Display *display;
941 WindowPtr w;
942 GC gc;
943 int src_x, src_y;
944 unsigned int width, height;
945 int dest_x, dest_y;
947 #if TARGET_API_MAC_CARBON
948 Rect src_r;
949 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
951 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
952 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
953 kScrollWindowNoOptions, dummy);
954 DisposeRgn (dummy);
955 #else /* not TARGET_API_MAC_CARBON */
956 Rect src_r, dest_r;
958 SetPort (w);
959 #if 0
960 mac_set_colors (gc, NULL);
961 #endif
963 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
964 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
966 #if 0
967 /* Need to use global coordinates and screenBits since src and dest
968 areas overlap in general. */
969 local_to_global_coord (&src_r.left, &src_r.top);
970 local_to_global_coord (&src_r.right, &src_r.bottom);
971 local_to_global_coord (&dest_r.left, &dest_r.top);
972 local_to_global_coord (&dest_r.right, &dest_r.bottom);
974 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
975 #else
976 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
977 color mapping in CopyBits. Otherwise, it will be slow. */
978 ForeColor (blackColor);
979 BackColor (whiteColor);
980 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
982 mac_set_colors (gc, NULL);
983 #endif
984 #endif /* not TARGET_API_MAC_CARBON */
988 #if 0 /* TODO: figure out if we need to do this on Mac. */
989 /* Mac replacement for XCopyArea: dest must be Pixmap. */
991 static void
992 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
993 dest_x, dest_y)
994 Display *display;
995 Pixmap src, dest;
996 GC gc;
997 int src_x, src_y;
998 unsigned int width, height;
999 int dest_x, dest_y;
1001 CGrafPtr old_port;
1002 GDHandle old_gdh;
1003 Rect src_r, dest_r;
1005 GetGWorld (&old_port, &old_gdh);
1006 SetGWorld (dest, NULL);
1007 ForeColor (blackColor);
1008 BackColor (whiteColor);
1010 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1011 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1013 LockPixels (GetGWorldPixMap (src));
1014 LockPixels (GetGWorldPixMap (dest));
1015 #if TARGET_API_MAC_CARBON
1016 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
1017 &src_r, &dest_r, srcCopy, 0);
1018 #else /* not TARGET_API_MAC_CARBON */
1019 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
1020 &src_r, &dest_r, srcCopy, 0);
1021 #endif /* not TARGET_API_MAC_CARBON */
1022 UnlockPixels (GetGWorldPixMap (dest));
1023 UnlockPixels (GetGWorldPixMap (src));
1025 SetGWorld (old_port, old_gdh);
1029 static void
1030 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
1031 width, height, dest_x, dest_y)
1032 Display *display;
1033 Pixmap src, mask, dest;
1034 GC gc;
1035 int src_x, src_y;
1036 unsigned int width, height;
1037 int dest_x, dest_y;
1039 CGrafPtr old_port;
1040 GDHandle old_gdh;
1041 Rect src_r, dest_r;
1043 GetGWorld (&old_port, &old_gdh);
1044 SetGWorld (dest, NULL);
1045 ForeColor (blackColor);
1046 BackColor (whiteColor);
1048 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1049 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1051 LockPixels (GetGWorldPixMap (src));
1052 LockPixels (GetGWorldPixMap (mask));
1053 LockPixels (GetGWorldPixMap (dest));
1054 #if TARGET_API_MAC_CARBON
1055 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1056 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1057 #else /* not TARGET_API_MAC_CARBON */
1058 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1059 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1060 #endif /* not TARGET_API_MAC_CARBON */
1061 UnlockPixels (GetGWorldPixMap (dest));
1062 UnlockPixels (GetGWorldPixMap (mask));
1063 UnlockPixels (GetGWorldPixMap (src));
1065 SetGWorld (old_port, old_gdh);
1067 #endif
1070 /* Mac replacement for XChangeGC. */
1072 static void
1073 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1074 XGCValues *xgcv)
1076 if (mask & GCForeground)
1077 gc->foreground = xgcv->foreground;
1078 if (mask & GCBackground)
1079 gc->background = xgcv->background;
1080 if (mask & GCFont)
1081 gc->font = xgcv->font;
1085 /* Mac replacement for XCreateGC. */
1087 XGCValues *
1088 XCreateGC (void * ignore, Window window, unsigned long mask,
1089 XGCValues *xgcv)
1091 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1092 bzero (gc, sizeof (XGCValues));
1094 XChangeGC (ignore, gc, mask, xgcv);
1096 return gc;
1100 /* Used in xfaces.c. */
1102 void
1103 XFreeGC (display, gc)
1104 Display *display;
1105 GC gc;
1107 xfree (gc);
1111 /* Mac replacement for XGetGCValues. */
1113 static void
1114 XGetGCValues (void* ignore, XGCValues *gc,
1115 unsigned long mask, XGCValues *xgcv)
1117 XChangeGC (ignore, xgcv, mask, gc);
1121 /* Mac replacement for XSetForeground. */
1123 void
1124 XSetForeground (display, gc, color)
1125 Display *display;
1126 GC gc;
1127 unsigned long color;
1129 gc->foreground = color;
1133 /* Mac replacement for XSetBackground. */
1135 void
1136 XSetBackground (display, gc, color)
1137 Display *display;
1138 GC gc;
1139 unsigned long color;
1141 gc->background = color;
1145 /* Mac replacement for XSetWindowBackground. */
1147 void
1148 XSetWindowBackground (display, w, color)
1149 Display *display;
1150 WindowPtr w;
1151 unsigned long color;
1153 #if !TARGET_API_MAC_CARBON
1154 AuxWinHandle aw_handle;
1155 CTabHandle ctab_handle;
1156 ColorSpecPtr ct_table;
1157 short ct_size;
1158 #endif
1159 RGBColor bg_color;
1161 bg_color.red = RED16_FROM_ULONG (color);
1162 bg_color.green = GREEN16_FROM_ULONG (color);
1163 bg_color.blue = BLUE16_FROM_ULONG (color);
1165 #if TARGET_API_MAC_CARBON
1166 SetWindowContentColor (w, &bg_color);
1167 #else
1168 if (GetAuxWin (w, &aw_handle))
1170 ctab_handle = (*aw_handle)->awCTable;
1171 HandToHand ((Handle *) &ctab_handle);
1172 ct_table = (*ctab_handle)->ctTable;
1173 ct_size = (*ctab_handle)->ctSize;
1174 while (ct_size > -1)
1176 if (ct_table->value == 0)
1178 ct_table->rgb = bg_color;
1179 CTabChanged (ctab_handle);
1180 SetWinColor (w, (WCTabHandle) ctab_handle);
1182 ct_size--;
1185 #endif
1189 /* Mac replacement for XSetFont. */
1191 static void
1192 XSetFont (display, gc, font)
1193 Display *display;
1194 GC gc;
1195 XFontStruct *font;
1197 gc->font = font;
1201 static void
1202 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1203 int *direction,int *font_ascent,
1204 int *font_descent, XCharStruct *cs)
1206 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1210 /* x_sync is a no-op on Mac. */
1211 void
1212 x_sync (f)
1213 void *f;
1218 /* Flush display of frame F, or of all frames if F is null. */
1220 static void
1221 x_flush (f)
1222 struct frame *f;
1224 #if TARGET_API_MAC_CARBON
1225 BLOCK_INPUT;
1226 if (f)
1227 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1228 else
1229 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1230 UNBLOCK_INPUT;
1231 #endif
1235 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1236 Calls to XFlush should be unnecessary because the X output buffer
1237 is flushed automatically as needed by calls to XPending,
1238 XNextEvent, or XWindowEvent according to the XFlush man page.
1239 XTread_socket calls XPending. Removing XFlush improves
1240 performance. */
1242 #define XFlush(DISPLAY) (void) 0
1245 /* Return the struct mac_display_info corresponding to DPY. There's
1246 only one. */
1248 struct mac_display_info *
1249 mac_display_info_for_display (dpy)
1250 Display *dpy;
1252 return &one_mac_display_info;
1257 /***********************************************************************
1258 Starting and ending an update
1259 ***********************************************************************/
1261 /* Start an update of frame F. This function is installed as a hook
1262 for update_begin, i.e. it is called when update_begin is called.
1263 This function is called prior to calls to x_update_window_begin for
1264 each window being updated. */
1266 static void
1267 x_update_begin (f)
1268 struct frame *f;
1270 #if TARGET_API_MAC_CARBON
1271 /* During update of a frame, availability of input events is
1272 periodically checked with ReceiveNextEvent if
1273 redisplay-dont-pause is nil. That normally flushes window buffer
1274 changes for every check, and thus screen update looks waving even
1275 if no input is available. So we disable screen updates during
1276 update of a frame. */
1277 BLOCK_INPUT;
1278 DisableScreenUpdates ();
1279 UNBLOCK_INPUT;
1280 #endif
1284 /* Start update of window W. Set the global variable updated_window
1285 to the window being updated and set output_cursor to the cursor
1286 position of W. */
1288 static void
1289 x_update_window_begin (w)
1290 struct window *w;
1292 struct frame *f = XFRAME (WINDOW_FRAME (w));
1293 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1295 updated_window = w;
1296 set_output_cursor (&w->cursor);
1298 BLOCK_INPUT;
1300 if (f == display_info->mouse_face_mouse_frame)
1302 /* Don't do highlighting for mouse motion during the update. */
1303 display_info->mouse_face_defer = 1;
1305 /* If F needs to be redrawn, simply forget about any prior mouse
1306 highlighting. */
1307 if (FRAME_GARBAGED_P (f))
1308 display_info->mouse_face_window = Qnil;
1310 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1311 their mouse_face_p flag set, which means that they are always
1312 unequal to rows in a desired matrix which never have that
1313 flag set. So, rows containing mouse-face glyphs are never
1314 scrolled, and we don't have to switch the mouse highlight off
1315 here to prevent it from being scrolled. */
1317 /* Can we tell that this update does not affect the window
1318 where the mouse highlight is? If so, no need to turn off.
1319 Likewise, don't do anything if the frame is garbaged;
1320 in that case, the frame's current matrix that we would use
1321 is all wrong, and we will redisplay that line anyway. */
1322 if (!NILP (display_info->mouse_face_window)
1323 && w == XWINDOW (display_info->mouse_face_window))
1325 int i;
1327 for (i = 0; i < w->desired_matrix->nrows; ++i)
1328 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1329 break;
1331 if (i < w->desired_matrix->nrows)
1332 clear_mouse_face (display_info);
1334 #endif /* 0 */
1337 UNBLOCK_INPUT;
1341 /* Draw a vertical window border from (x,y0) to (x,y1) */
1343 static void
1344 mac_draw_vertical_window_border (w, x, y0, y1)
1345 struct window *w;
1346 int x, y0, y1;
1348 struct frame *f = XFRAME (WINDOW_FRAME (w));
1350 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1351 f->output_data.mac->normal_gc, x, y0, x, y1);
1355 /* End update of window W (which is equal to updated_window).
1357 Draw vertical borders between horizontally adjacent windows, and
1358 display W's cursor if CURSOR_ON_P is non-zero.
1360 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1361 glyphs in mouse-face were overwritten. In that case we have to
1362 make sure that the mouse-highlight is properly redrawn.
1364 W may be a menu bar pseudo-window in case we don't have X toolkit
1365 support. Such windows don't have a cursor, so don't display it
1366 here. */
1368 static void
1369 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1370 struct window *w;
1371 int cursor_on_p, mouse_face_overwritten_p;
1373 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1375 if (!w->pseudo_window_p)
1377 BLOCK_INPUT;
1379 if (cursor_on_p)
1380 display_and_set_cursor (w, 1, output_cursor.hpos,
1381 output_cursor.vpos,
1382 output_cursor.x, output_cursor.y);
1384 if (draw_window_fringes (w, 1))
1385 x_draw_vertical_border (w);
1387 UNBLOCK_INPUT;
1390 /* If a row with mouse-face was overwritten, arrange for
1391 XTframe_up_to_date to redisplay the mouse highlight. */
1392 if (mouse_face_overwritten_p)
1394 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1395 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1396 dpyinfo->mouse_face_window = Qnil;
1399 #if 0
1400 /* Unhide the caret. This won't actually show the cursor, unless it
1401 was visible before the corresponding call to HideCaret in
1402 x_update_window_begin. */
1403 if (w32_use_visible_system_caret)
1404 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1405 #endif
1407 updated_window = NULL;
1411 /* End update of frame F. This function is installed as a hook in
1412 update_end. */
1414 static void
1415 x_update_end (f)
1416 struct frame *f;
1418 /* Mouse highlight may be displayed again. */
1419 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1421 BLOCK_INPUT;
1422 #if TARGET_API_MAC_CARBON
1423 EnableScreenUpdates ();
1424 #endif
1425 XFlush (FRAME_MAC_DISPLAY (f));
1426 UNBLOCK_INPUT;
1430 /* This function is called from various places in xdisp.c whenever a
1431 complete update has been performed. The global variable
1432 updated_window is not available here. */
1434 static void
1435 XTframe_up_to_date (f)
1436 struct frame *f;
1438 if (FRAME_MAC_P (f))
1440 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1442 if (dpyinfo->mouse_face_deferred_gc
1443 || f == dpyinfo->mouse_face_mouse_frame)
1445 BLOCK_INPUT;
1446 if (dpyinfo->mouse_face_mouse_frame)
1447 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1448 dpyinfo->mouse_face_mouse_x,
1449 dpyinfo->mouse_face_mouse_y);
1450 dpyinfo->mouse_face_deferred_gc = 0;
1451 UNBLOCK_INPUT;
1457 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1458 arrow bitmaps, or clear the fringes if no bitmaps are required
1459 before DESIRED_ROW is made current. The window being updated is
1460 found in updated_window. This function is called from
1461 update_window_line only if it is known that there are differences
1462 between bitmaps to be drawn between current row and DESIRED_ROW. */
1464 static void
1465 x_after_update_window_line (desired_row)
1466 struct glyph_row *desired_row;
1468 struct window *w = updated_window;
1469 struct frame *f;
1470 int width, height;
1472 xassert (w);
1474 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1475 desired_row->redraw_fringe_bitmaps_p = 1;
1477 /* When a window has disappeared, make sure that no rest of
1478 full-width rows stays visible in the internal border. Could
1479 check here if updated_window is the leftmost/rightmost window,
1480 but I guess it's not worth doing since vertically split windows
1481 are almost never used, internal border is rarely set, and the
1482 overhead is very small. */
1483 if (windows_or_buffers_changed
1484 && desired_row->full_width_p
1485 && (f = XFRAME (w->frame),
1486 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1487 width != 0)
1488 && (height = desired_row->visible_height,
1489 height > 0))
1491 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1492 /* Internal border is drawn below the tool bar. */
1493 if (WINDOWP (f->tool_bar_window)
1494 && w == XWINDOW (f->tool_bar_window))
1495 y -= width;
1497 BLOCK_INPUT;
1499 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1500 0, y, width, height, 0);
1501 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1502 FRAME_PIXEL_WIDTH (f) - width, y,
1503 width, height, 0);
1505 UNBLOCK_INPUT;
1510 /* Draw the bitmap WHICH in one of the left or right fringes of
1511 window W. ROW is the glyph row for which to display the bitmap; it
1512 determines the vertical position at which the bitmap has to be
1513 drawn. */
1515 static void
1516 x_draw_fringe_bitmap (w, row, p)
1517 struct window *w;
1518 struct glyph_row *row;
1519 struct draw_fringe_bitmap_params *p;
1521 struct frame *f = XFRAME (WINDOW_FRAME (w));
1522 Display *display = FRAME_MAC_DISPLAY (f);
1523 WindowPtr window = FRAME_MAC_WINDOW (f);
1524 XGCValues gcv;
1525 GC gc = f->output_data.mac->normal_gc;
1526 struct face *face = p->face;
1527 int rowY;
1529 /* Must clip because of partially visible lines. */
1530 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1531 if (p->y < rowY)
1533 /* Adjust position of "bottom aligned" bitmap on partially
1534 visible last row. */
1535 int oldY = row->y;
1536 int oldVH = row->visible_height;
1537 row->visible_height = p->h;
1538 row->y -= rowY - p->y;
1539 x_clip_to_row (w, row, -1, gc);
1540 row->y = oldY;
1541 row->visible_height = oldVH;
1543 else
1544 x_clip_to_row (w, row, -1, gc);
1546 if (p->bx >= 0 && !p->overlay_p)
1548 XGCValues gcv;
1549 gcv.foreground = face->background;
1551 #if 0 /* MAC_TODO: stipple */
1552 /* In case the same realized face is used for fringes and
1553 for something displayed in the text (e.g. face `region' on
1554 mono-displays, the fill style may have been changed to
1555 FillSolid in x_draw_glyph_string_background. */
1556 if (face->stipple)
1557 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1558 else
1559 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1560 #endif
1562 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1563 &gcv,
1564 p->bx, p->by, p->nx, p->ny);
1566 #if 0 /* MAC_TODO: stipple */
1567 if (!face->stipple)
1568 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1569 #endif
1572 if (p->which)
1574 unsigned short *bits = p->bits + p->dh;
1576 gcv.foreground = (p->cursor_p
1577 ? (p->overlay_p ? face->background
1578 : f->output_data.mac->cursor_pixel)
1579 : face->foreground);
1580 gcv.background = face->background;
1582 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1583 p->wd, p->h, bits, p->overlay_p);
1586 mac_reset_clipping (display, window);
1590 /* This is called when starting Emacs and when restarting after
1591 suspend. When starting Emacs, no window is mapped. And nothing
1592 must be done to Emacs's own window if it is suspended (though that
1593 rarely happens). */
1595 static void
1596 XTset_terminal_modes ()
1600 /* This is called when exiting or suspending Emacs. Exiting will make
1601 the windows go away, and suspending requires no action. */
1603 static void
1604 XTreset_terminal_modes ()
1609 /***********************************************************************
1610 Display Iterator
1611 ***********************************************************************/
1613 /* Function prototypes of this page. */
1615 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1616 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1619 /* Return a pointer to per-char metric information in FONT of a
1620 character pointed by B which is a pointer to an XChar2b. */
1622 #define PER_CHAR_METRIC(font, b) \
1623 ((font)->per_char \
1624 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1625 + (((font)->min_byte1 || (font)->max_byte1) \
1626 ? (((b)->byte1 - (font)->min_byte1) \
1627 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1628 : 0)) \
1629 : &((font)->max_bounds))
1632 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1633 is not contained in the font. */
1635 static INLINE XCharStruct *
1636 x_per_char_metric (font, char2b)
1637 XFontStruct *font;
1638 XChar2b *char2b;
1640 /* The result metric information. */
1641 XCharStruct *pcm = NULL;
1643 xassert (font && char2b);
1645 if (font->per_char != NULL)
1647 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1649 /* min_char_or_byte2 specifies the linear character index
1650 corresponding to the first element of the per_char array,
1651 max_char_or_byte2 is the index of the last character. A
1652 character with non-zero CHAR2B->byte1 is not in the font.
1653 A character with byte2 less than min_char_or_byte2 or
1654 greater max_char_or_byte2 is not in the font. */
1655 if (char2b->byte1 == 0
1656 && char2b->byte2 >= font->min_char_or_byte2
1657 && char2b->byte2 <= font->max_char_or_byte2)
1658 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1660 else
1662 /* If either min_byte1 or max_byte1 are nonzero, both
1663 min_char_or_byte2 and max_char_or_byte2 are less than
1664 256, and the 2-byte character index values corresponding
1665 to the per_char array element N (counting from 0) are:
1667 byte1 = N/D + min_byte1
1668 byte2 = N\D + min_char_or_byte2
1670 where:
1672 D = max_char_or_byte2 - min_char_or_byte2 + 1
1673 / = integer division
1674 \ = integer modulus */
1675 if (char2b->byte1 >= font->min_byte1
1676 && char2b->byte1 <= font->max_byte1
1677 && char2b->byte2 >= font->min_char_or_byte2
1678 && char2b->byte2 <= font->max_char_or_byte2)
1680 pcm = (font->per_char
1681 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1682 * (char2b->byte1 - font->min_byte1))
1683 + (char2b->byte2 - font->min_char_or_byte2));
1687 else
1689 /* If the per_char pointer is null, all glyphs between the first
1690 and last character indexes inclusive have the same
1691 information, as given by both min_bounds and max_bounds. */
1692 if (char2b->byte2 >= font->min_char_or_byte2
1693 && char2b->byte2 <= font->max_char_or_byte2)
1694 pcm = &font->max_bounds;
1697 return ((pcm == NULL
1698 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1699 ? NULL : pcm);
1702 /* RIF:
1705 static XCharStruct *
1706 mac_per_char_metric (font, char2b, font_type)
1707 XFontStruct *font;
1708 XChar2b *char2b;
1709 int font_type;
1711 return x_per_char_metric (font, char2b);
1714 /* RIF:
1715 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1716 the two-byte form of C. Encoding is returned in *CHAR2B. */
1718 static int
1719 mac_encode_char (c, char2b, font_info, two_byte_p)
1720 int c;
1721 XChar2b *char2b;
1722 struct font_info *font_info;
1723 int *two_byte_p;
1725 int charset = CHAR_CHARSET (c);
1726 XFontStruct *font = font_info->font;
1728 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1729 This may be either a program in a special encoder language or a
1730 fixed encoding. */
1731 if (font_info->font_encoder)
1733 /* It's a program. */
1734 struct ccl_program *ccl = font_info->font_encoder;
1736 if (CHARSET_DIMENSION (charset) == 1)
1738 ccl->reg[0] = charset;
1739 ccl->reg[1] = char2b->byte2;
1741 else
1743 ccl->reg[0] = charset;
1744 ccl->reg[1] = char2b->byte1;
1745 ccl->reg[2] = char2b->byte2;
1748 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1750 /* We assume that MSBs are appropriately set/reset by CCL
1751 program. */
1752 if (font->max_byte1 == 0) /* 1-byte font */
1753 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1754 else
1755 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1757 else if (font_info->encoding[charset])
1759 /* Fixed encoding scheme. See fontset.h for the meaning of the
1760 encoding numbers. */
1761 int enc = font_info->encoding[charset];
1763 if ((enc == 1 || enc == 2)
1764 && CHARSET_DIMENSION (charset) == 2)
1765 char2b->byte1 |= 0x80;
1767 if (enc == 1 || enc == 3)
1768 char2b->byte2 |= 0x80;
1770 if (enc == 4)
1772 int sjis1, sjis2;
1774 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1775 char2b->byte1 = sjis1;
1776 char2b->byte2 = sjis2;
1780 if (two_byte_p)
1781 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1783 return FONT_TYPE_UNKNOWN;
1788 /***********************************************************************
1789 Glyph display
1790 ***********************************************************************/
1793 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1794 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1795 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1796 int));
1797 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1798 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1799 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1800 static void x_draw_glyph_string P_ ((struct glyph_string *));
1801 static void x_set_cursor_gc P_ ((struct glyph_string *));
1802 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1803 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1804 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1805 unsigned long *, double, int));*/
1806 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1807 double, int, unsigned long));
1808 static void x_setup_relief_colors P_ ((struct glyph_string *));
1809 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1810 static void x_draw_image_relief P_ ((struct glyph_string *));
1811 static void x_draw_image_foreground P_ ((struct glyph_string *));
1812 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1813 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1814 int, int, int));
1815 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1816 int, int, int, int, int, int,
1817 Rect *));
1818 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1819 int, int, int, Rect *));
1821 #if GLYPH_DEBUG
1822 static void x_check_font P_ ((struct frame *, XFontStruct *));
1823 #endif
1826 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1827 face. */
1829 static void
1830 x_set_cursor_gc (s)
1831 struct glyph_string *s;
1833 if (s->font == FRAME_FONT (s->f)
1834 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1835 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1836 && !s->cmp)
1837 s->gc = s->f->output_data.mac->cursor_gc;
1838 else
1840 /* Cursor on non-default face: must merge. */
1841 XGCValues xgcv;
1842 unsigned long mask;
1844 xgcv.background = s->f->output_data.mac->cursor_pixel;
1845 xgcv.foreground = s->face->background;
1847 /* If the glyph would be invisible, try a different foreground. */
1848 if (xgcv.foreground == xgcv.background)
1849 xgcv.foreground = s->face->foreground;
1850 if (xgcv.foreground == xgcv.background)
1851 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1852 if (xgcv.foreground == xgcv.background)
1853 xgcv.foreground = s->face->foreground;
1855 /* Make sure the cursor is distinct from text in this face. */
1856 if (xgcv.background == s->face->background
1857 && xgcv.foreground == s->face->foreground)
1859 xgcv.background = s->face->foreground;
1860 xgcv.foreground = s->face->background;
1863 IF_DEBUG (x_check_font (s->f, s->font));
1864 xgcv.font = s->font;
1865 mask = GCForeground | GCBackground | GCFont;
1867 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1868 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1869 mask, &xgcv);
1870 else
1871 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1872 = XCreateGC (s->display, s->window, mask, &xgcv);
1874 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1879 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1881 static void
1882 x_set_mouse_face_gc (s)
1883 struct glyph_string *s;
1885 int face_id;
1886 struct face *face;
1888 /* What face has to be used last for the mouse face? */
1889 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1890 face = FACE_FROM_ID (s->f, face_id);
1891 if (face == NULL)
1892 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1894 if (s->first_glyph->type == CHAR_GLYPH)
1895 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1896 else
1897 face_id = FACE_FOR_CHAR (s->f, face, 0);
1898 s->face = FACE_FROM_ID (s->f, face_id);
1899 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1901 /* If font in this face is same as S->font, use it. */
1902 if (s->font == s->face->font)
1903 s->gc = s->face->gc;
1904 else
1906 /* Otherwise construct scratch_cursor_gc with values from FACE
1907 but font FONT. */
1908 XGCValues xgcv;
1909 unsigned long mask;
1911 xgcv.background = s->face->background;
1912 xgcv.foreground = s->face->foreground;
1913 IF_DEBUG (x_check_font (s->f, s->font));
1914 xgcv.font = s->font;
1915 mask = GCForeground | GCBackground | GCFont;
1917 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1918 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1919 mask, &xgcv);
1920 else
1921 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1922 = XCreateGC (s->display, s->window, mask, &xgcv);
1924 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1927 xassert (s->gc != 0);
1931 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1932 Faces to use in the mode line have already been computed when the
1933 matrix was built, so there isn't much to do, here. */
1935 static INLINE void
1936 x_set_mode_line_face_gc (s)
1937 struct glyph_string *s;
1939 s->gc = s->face->gc;
1943 /* Set S->gc of glyph string S for drawing that glyph string. Set
1944 S->stippled_p to a non-zero value if the face of S has a stipple
1945 pattern. */
1947 static INLINE void
1948 x_set_glyph_string_gc (s)
1949 struct glyph_string *s;
1951 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1953 if (s->hl == DRAW_NORMAL_TEXT)
1955 s->gc = s->face->gc;
1956 s->stippled_p = s->face->stipple != 0;
1958 else if (s->hl == DRAW_INVERSE_VIDEO)
1960 x_set_mode_line_face_gc (s);
1961 s->stippled_p = s->face->stipple != 0;
1963 else if (s->hl == DRAW_CURSOR)
1965 x_set_cursor_gc (s);
1966 s->stippled_p = 0;
1968 else if (s->hl == DRAW_MOUSE_FACE)
1970 x_set_mouse_face_gc (s);
1971 s->stippled_p = s->face->stipple != 0;
1973 else if (s->hl == DRAW_IMAGE_RAISED
1974 || s->hl == DRAW_IMAGE_SUNKEN)
1976 s->gc = s->face->gc;
1977 s->stippled_p = s->face->stipple != 0;
1979 else
1981 s->gc = s->face->gc;
1982 s->stippled_p = s->face->stipple != 0;
1985 /* GC must have been set. */
1986 xassert (s->gc != 0);
1990 /* Set clipping for output of glyph string S. S may be part of a mode
1991 line or menu if we don't have X toolkit support. */
1993 static INLINE void
1994 x_set_glyph_string_clipping (s)
1995 struct glyph_string *s;
1997 Rect r;
1998 get_glyph_string_clip_rect (s, &r);
1999 mac_set_clip_rectangle (s->display, s->window, &r);
2003 /* RIF:
2004 Compute left and right overhang of glyph string S. If S is a glyph
2005 string for a composition, assume overhangs don't exist. */
2007 static void
2008 mac_compute_glyph_string_overhangs (s)
2009 struct glyph_string *s;
2011 Rect r;
2012 MacFontStruct *font = s->font;
2014 TextFont (font->mac_fontnum);
2015 TextSize (font->mac_fontsize);
2016 TextFace (font->mac_fontface);
2018 if (s->two_byte_p)
2019 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r);
2020 else
2022 int i;
2023 char *buf = xmalloc (s->nchars);
2025 if (buf == NULL)
2026 SetRect (&r, 0, 0, 0, 0);
2027 else
2029 for (i = 0; i < s->nchars; ++i)
2030 buf[i] = s->char2b[i].byte2;
2031 QDTextBounds (s->nchars, buf, &r);
2032 xfree (buf);
2036 s->right_overhang = r.right > s->width ? r.right - s->width : 0;
2037 s->left_overhang = r.left < 0 ? -r.left : 0;
2041 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2043 static INLINE void
2044 x_clear_glyph_string_rect (s, x, y, w, h)
2045 struct glyph_string *s;
2046 int x, y, w, h;
2048 XGCValues xgcv;
2050 xgcv.foreground = s->gc->background;
2051 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
2055 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2056 on Mac OS X because:
2057 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2058 into an offscreen graphics world first. So performance gain
2059 cannot be expected.)
2060 - It lowers rendering quality.
2061 - Some fonts leave garbage on cursor movement. */
2063 /* Draw the background of glyph_string S. If S->background_filled_p
2064 is non-zero don't draw it. FORCE_P non-zero means draw the
2065 background even if it wouldn't be drawn normally. This is used
2066 when a string preceding S draws into the background of S, or S
2067 contains the first component of a composition. */
2069 static void
2070 x_draw_glyph_string_background (s, force_p)
2071 struct glyph_string *s;
2072 int force_p;
2074 /* Nothing to do if background has already been drawn or if it
2075 shouldn't be drawn in the first place. */
2076 if (!s->background_filled_p)
2078 int box_line_width = max (s->face->box_line_width, 0);
2080 #if 0 /* MAC_TODO: stipple */
2081 if (s->stippled_p)
2083 /* Fill background with a stipple pattern. */
2084 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2085 XFillRectangle (s->display, s->window, s->gc, s->x,
2086 s->y + box_line_width,
2087 s->background_width,
2088 s->height - 2 * box_line_width);
2089 XSetFillStyle (s->display, s->gc, FillSolid);
2090 s->background_filled_p = 1;
2092 else
2093 #endif
2094 #ifdef MAC_OS8
2095 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2096 || s->font_not_found_p
2097 || s->extends_to_end_of_line_p
2098 || force_p)
2099 #endif
2101 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2102 s->background_width,
2103 s->height - 2 * box_line_width);
2104 s->background_filled_p = 1;
2110 /* Draw the foreground of glyph string S. */
2112 static void
2113 x_draw_glyph_string_foreground (s)
2114 struct glyph_string *s;
2116 int i, x;
2118 /* If first glyph of S has a left box line, start drawing the text
2119 of S to the right of that box line. */
2120 if (s->face->box != FACE_NO_BOX
2121 && s->first_glyph->left_box_line_p)
2122 x = s->x + abs (s->face->box_line_width);
2123 else
2124 x = s->x;
2126 /* Draw characters of S as rectangles if S's font could not be
2127 loaded. */
2128 if (s->font_not_found_p)
2130 for (i = 0; i < s->nchars; ++i)
2132 struct glyph *g = s->first_glyph + i;
2133 mac_draw_rectangle (s->display, s->window,
2134 s->gc, x, s->y, g->pixel_width - 1,
2135 s->height - 1);
2136 x += g->pixel_width;
2139 else
2141 char *char1b = (char *) s->char2b;
2142 int boff = s->font_info->baseline_offset;
2144 if (s->font_info->vertical_centering)
2145 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2147 /* If we can use 8-bit functions, condense S->char2b. */
2148 if (!s->two_byte_p)
2149 for (i = 0; i < s->nchars; ++i)
2150 char1b[i] = s->char2b[i].byte2;
2152 #ifdef MAC_OS8
2153 /* Draw text with XDrawString if background has already been
2154 filled. Otherwise, use XDrawImageString. (Note that
2155 XDrawImageString is usually faster than XDrawString.) Always
2156 use XDrawImageString when drawing the cursor so that there is
2157 no chance that characters under a box cursor are invisible. */
2158 if (s->for_overlaps_p
2159 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2160 #endif
2162 /* Draw characters with 16-bit or 8-bit functions. */
2163 if (s->two_byte_p)
2164 XDrawString16 (s->display, s->window, s->gc, x,
2165 s->ybase - boff, s->char2b, s->nchars);
2166 else
2167 XDrawString (s->display, s->window, s->gc, x,
2168 s->ybase - boff, char1b, s->nchars);
2170 #ifdef MAC_OS8
2171 else
2173 if (s->two_byte_p)
2174 XDrawImageString16 (s->display, s->window, s->gc, x,
2175 s->ybase - boff, s->char2b, s->nchars);
2176 else
2177 XDrawImageString (s->display, s->window, s->gc, x,
2178 s->ybase - boff, char1b, s->nchars);
2180 #endif
2184 /* Draw the foreground of composite glyph string S. */
2186 static void
2187 x_draw_composite_glyph_string_foreground (s)
2188 struct glyph_string *s;
2190 int i, x;
2192 /* If first glyph of S has a left box line, start drawing the text
2193 of S to the right of that box line. */
2194 if (s->face->box != FACE_NO_BOX
2195 && s->first_glyph->left_box_line_p)
2196 x = s->x + abs (s->face->box_line_width);
2197 else
2198 x = s->x;
2200 /* S is a glyph string for a composition. S->gidx is the index of
2201 the first character drawn for glyphs of this composition.
2202 S->gidx == 0 means we are drawing the very first character of
2203 this composition. */
2205 /* Draw a rectangle for the composition if the font for the very
2206 first character of the composition could not be loaded. */
2207 if (s->font_not_found_p)
2209 if (s->gidx == 0)
2210 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2211 s->width - 1, s->height - 1);
2213 else
2215 for (i = 0; i < s->nchars; i++, ++s->gidx)
2216 XDrawString16 (s->display, s->window, s->gc,
2217 x + s->cmp->offsets[s->gidx * 2],
2218 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2219 s->char2b + i, 1);
2224 #ifdef USE_X_TOOLKIT
2226 static struct frame *x_frame_of_widget P_ ((Widget));
2229 /* Return the frame on which widget WIDGET is used.. Abort if frame
2230 cannot be determined. */
2232 static struct frame *
2233 x_frame_of_widget (widget)
2234 Widget widget;
2236 struct x_display_info *dpyinfo;
2237 Lisp_Object tail;
2238 struct frame *f;
2240 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2242 /* Find the top-level shell of the widget. Note that this function
2243 can be called when the widget is not yet realized, so XtWindow
2244 (widget) == 0. That's the reason we can't simply use
2245 x_any_window_to_frame. */
2246 while (!XtIsTopLevelShell (widget))
2247 widget = XtParent (widget);
2249 /* Look for a frame with that top-level widget. Allocate the color
2250 on that frame to get the right gamma correction value. */
2251 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2252 if (GC_FRAMEP (XCAR (tail))
2253 && (f = XFRAME (XCAR (tail)),
2254 (f->output_data.nothing != 1
2255 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2256 && f->output_data.x->widget == widget)
2257 return f;
2259 abort ();
2263 /* Allocate the color COLOR->pixel on the screen and display of
2264 widget WIDGET in colormap CMAP. If an exact match cannot be
2265 allocated, try the nearest color available. Value is non-zero
2266 if successful. This is called from lwlib. */
2269 x_alloc_nearest_color_for_widget (widget, cmap, color)
2270 Widget widget;
2271 Colormap cmap;
2272 XColor *color;
2274 struct frame *f = x_frame_of_widget (widget);
2275 return x_alloc_nearest_color (f, cmap, color);
2279 #endif /* USE_X_TOOLKIT */
2281 #if 0 /* MAC_TODO */
2283 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2284 CMAP. If an exact match can't be allocated, try the nearest color
2285 available. Value is non-zero if successful. Set *COLOR to the
2286 color allocated. */
2289 x_alloc_nearest_color (f, cmap, color)
2290 struct frame *f;
2291 Colormap cmap;
2292 XColor *color;
2294 Display *display = FRAME_X_DISPLAY (f);
2295 Screen *screen = FRAME_X_SCREEN (f);
2296 int rc;
2298 gamma_correct (f, color);
2299 rc = XAllocColor (display, cmap, color);
2300 if (rc == 0)
2302 /* If we got to this point, the colormap is full, so we're going
2303 to try to get the next closest color. The algorithm used is
2304 a least-squares matching, which is what X uses for closest
2305 color matching with StaticColor visuals. */
2306 int nearest, i;
2307 unsigned long nearest_delta = ~0;
2308 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2309 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2311 for (i = 0; i < ncells; ++i)
2312 cells[i].pixel = i;
2313 XQueryColors (display, cmap, cells, ncells);
2315 for (nearest = i = 0; i < ncells; ++i)
2317 long dred = (color->red >> 8) - (cells[i].red >> 8);
2318 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2319 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2320 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2322 if (delta < nearest_delta)
2324 nearest = i;
2325 nearest_delta = delta;
2329 color->red = cells[nearest].red;
2330 color->green = cells[nearest].green;
2331 color->blue = cells[nearest].blue;
2332 rc = XAllocColor (display, cmap, color);
2335 #ifdef DEBUG_X_COLORS
2336 if (rc)
2337 register_color (color->pixel);
2338 #endif /* DEBUG_X_COLORS */
2340 return rc;
2344 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2345 It's necessary to do this instead of just using PIXEL directly to
2346 get color reference counts right. */
2348 unsigned long
2349 x_copy_color (f, pixel)
2350 struct frame *f;
2351 unsigned long pixel;
2353 XColor color;
2355 color.pixel = pixel;
2356 BLOCK_INPUT;
2357 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2358 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2359 UNBLOCK_INPUT;
2360 #ifdef DEBUG_X_COLORS
2361 register_color (pixel);
2362 #endif
2363 return color.pixel;
2367 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2368 It's necessary to do this instead of just using PIXEL directly to
2369 get color reference counts right. */
2371 unsigned long
2372 x_copy_dpy_color (dpy, cmap, pixel)
2373 Display *dpy;
2374 Colormap cmap;
2375 unsigned long pixel;
2377 XColor color;
2379 color.pixel = pixel;
2380 BLOCK_INPUT;
2381 XQueryColor (dpy, cmap, &color);
2382 XAllocColor (dpy, cmap, &color);
2383 UNBLOCK_INPUT;
2384 #ifdef DEBUG_X_COLORS
2385 register_color (pixel);
2386 #endif
2387 return color.pixel;
2390 #endif /* MAC_TODO */
2393 /* Brightness beyond which a color won't have its highlight brightness
2394 boosted.
2396 Nominally, highlight colors for `3d' faces are calculated by
2397 brightening an object's color by a constant scale factor, but this
2398 doesn't yield good results for dark colors, so for colors who's
2399 brightness is less than this value (on a scale of 0-255) have to
2400 use an additional additive factor.
2402 The value here is set so that the default menu-bar/mode-line color
2403 (grey75) will not have its highlights changed at all. */
2404 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2407 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2408 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2409 If this produces the same color as COLOR, try a color where all RGB
2410 values have DELTA added. Return the allocated color in *COLOR.
2411 DISPLAY is the X display, CMAP is the colormap to operate on.
2412 Value is non-zero if successful. */
2414 static int
2415 mac_alloc_lighter_color (f, color, factor, delta)
2416 struct frame *f;
2417 unsigned long *color;
2418 double factor;
2419 int delta;
2421 unsigned long new;
2422 long bright;
2424 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2425 delta /= 256;
2427 /* Change RGB values by specified FACTOR. Avoid overflow! */
2428 xassert (factor >= 0);
2429 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2430 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2431 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2433 /* Calculate brightness of COLOR. */
2434 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2435 + BLUE_FROM_ULONG (*color)) / 6;
2437 /* We only boost colors that are darker than
2438 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2439 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2440 /* Make an additive adjustment to NEW, because it's dark enough so
2441 that scaling by FACTOR alone isn't enough. */
2443 /* How far below the limit this color is (0 - 1, 1 being darker). */
2444 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2445 /* The additive adjustment. */
2446 int min_delta = delta * dimness * factor / 2;
2448 if (factor < 1)
2449 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2450 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2451 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2452 else
2453 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2454 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2455 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2458 if (new == *color)
2459 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2460 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2461 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2463 /* MAC_TODO: Map to palette and retry with delta if same? */
2464 /* MAC_TODO: Free colors (if using palette)? */
2466 if (new == *color)
2467 return 0;
2469 *color = new;
2471 return 1;
2475 /* Set up the foreground color for drawing relief lines of glyph
2476 string S. RELIEF is a pointer to a struct relief containing the GC
2477 with which lines will be drawn. Use a color that is FACTOR or
2478 DELTA lighter or darker than the relief's background which is found
2479 in S->f->output_data.x->relief_background. If such a color cannot
2480 be allocated, use DEFAULT_PIXEL, instead. */
2482 static void
2483 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2484 struct frame *f;
2485 struct relief *relief;
2486 double factor;
2487 int delta;
2488 unsigned long default_pixel;
2490 XGCValues xgcv;
2491 struct mac_output *di = f->output_data.mac;
2492 unsigned long mask = GCForeground;
2493 unsigned long pixel;
2494 unsigned long background = di->relief_background;
2495 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2497 /* MAC_TODO: Free colors (if using palette)? */
2499 /* Allocate new color. */
2500 xgcv.foreground = default_pixel;
2501 pixel = background;
2502 if (dpyinfo->n_planes != 1
2503 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2505 relief->allocated_p = 1;
2506 xgcv.foreground = relief->pixel = pixel;
2509 if (relief->gc == 0)
2511 #if 0 /* MAC_TODO: stipple */
2512 xgcv.stipple = dpyinfo->gray;
2513 mask |= GCStipple;
2514 #endif
2515 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2517 else
2518 XChangeGC (NULL, relief->gc, mask, &xgcv);
2522 /* Set up colors for the relief lines around glyph string S. */
2524 static void
2525 x_setup_relief_colors (s)
2526 struct glyph_string *s;
2528 struct mac_output *di = s->f->output_data.mac;
2529 unsigned long color;
2531 if (s->face->use_box_color_for_shadows_p)
2532 color = s->face->box_color;
2533 else if (s->first_glyph->type == IMAGE_GLYPH
2534 && s->img->pixmap
2535 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2536 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2537 else
2539 XGCValues xgcv;
2541 /* Get the background color of the face. */
2542 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2543 color = xgcv.background;
2546 if (di->white_relief.gc == 0
2547 || color != di->relief_background)
2549 di->relief_background = color;
2550 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2551 WHITE_PIX_DEFAULT (s->f));
2552 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2553 BLACK_PIX_DEFAULT (s->f));
2558 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2559 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2560 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2561 relief. LEFT_P non-zero means draw a relief on the left side of
2562 the rectangle. RIGHT_P non-zero means draw a relief on the right
2563 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2564 when drawing. */
2566 static void
2567 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2568 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2569 struct frame *f;
2570 int left_x, top_y, right_x, bottom_y, width;
2571 int top_p, bot_p, left_p, right_p, raised_p;
2572 Rect *clip_rect;
2574 Display *dpy = FRAME_MAC_DISPLAY (f);
2575 Window window = FRAME_MAC_WINDOW (f);
2576 int i;
2577 GC gc;
2579 if (raised_p)
2580 gc = f->output_data.mac->white_relief.gc;
2581 else
2582 gc = f->output_data.mac->black_relief.gc;
2583 mac_set_clip_rectangle (dpy, window, clip_rect);
2585 /* Top. */
2586 if (top_p)
2587 for (i = 0; i < width; ++i)
2588 XDrawLine (dpy, window, gc,
2589 left_x + i * left_p, top_y + i,
2590 right_x - i * right_p, top_y + i);
2592 /* Left. */
2593 if (left_p)
2594 for (i = 0; i < width; ++i)
2595 XDrawLine (dpy, window, gc,
2596 left_x + i, top_y + i, left_x + i, bottom_y - i);
2598 mac_reset_clipping (dpy, window);
2599 if (raised_p)
2600 gc = f->output_data.mac->black_relief.gc;
2601 else
2602 gc = f->output_data.mac->white_relief.gc;
2603 mac_set_clip_rectangle (dpy, window,
2604 clip_rect);
2606 /* Bottom. */
2607 if (bot_p)
2608 for (i = 0; i < width; ++i)
2609 XDrawLine (dpy, window, gc,
2610 left_x + i * left_p, bottom_y - i,
2611 right_x - i * right_p, bottom_y - i);
2613 /* Right. */
2614 if (right_p)
2615 for (i = 0; i < width; ++i)
2616 XDrawLine (dpy, window, gc,
2617 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2619 mac_reset_clipping (dpy, window);
2623 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2624 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2625 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2626 left side of the rectangle. RIGHT_P non-zero means draw a line
2627 on the right side of the rectangle. CLIP_RECT is the clipping
2628 rectangle to use when drawing. */
2630 static void
2631 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2632 left_p, right_p, clip_rect)
2633 struct glyph_string *s;
2634 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2635 Rect *clip_rect;
2637 XGCValues xgcv;
2639 xgcv.foreground = s->face->box_color;
2640 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2642 /* Top. */
2643 XFillRectangle (s->display, s->window, &xgcv,
2644 left_x, top_y, right_x - left_x + 1, width);
2646 /* Left. */
2647 if (left_p)
2648 XFillRectangle (s->display, s->window, &xgcv,
2649 left_x, top_y, width, bottom_y - top_y + 1);
2651 /* Bottom. */
2652 XFillRectangle (s->display, s->window, &xgcv,
2653 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2655 /* Right. */
2656 if (right_p)
2657 XFillRectangle (s->display, s->window, &xgcv,
2658 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2660 mac_reset_clipping (s->display, s->window);
2664 /* Draw a box around glyph string S. */
2666 static void
2667 x_draw_glyph_string_box (s)
2668 struct glyph_string *s;
2670 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2671 int left_p, right_p;
2672 struct glyph *last_glyph;
2673 Rect clip_rect;
2675 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2676 ? WINDOW_RIGHT_EDGE_X (s->w)
2677 : window_box_right (s->w, s->area));
2679 /* The glyph that may have a right box line. */
2680 last_glyph = (s->cmp || s->img
2681 ? s->first_glyph
2682 : s->first_glyph + s->nchars - 1);
2684 width = abs (s->face->box_line_width);
2685 raised_p = s->face->box == FACE_RAISED_BOX;
2686 left_x = s->x;
2687 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2688 ? last_x - 1
2689 : min (last_x, s->x + s->background_width) - 1);
2690 top_y = s->y;
2691 bottom_y = top_y + s->height - 1;
2693 left_p = (s->first_glyph->left_box_line_p
2694 || (s->hl == DRAW_MOUSE_FACE
2695 && (s->prev == NULL
2696 || s->prev->hl != s->hl)));
2697 right_p = (last_glyph->right_box_line_p
2698 || (s->hl == DRAW_MOUSE_FACE
2699 && (s->next == NULL
2700 || s->next->hl != s->hl)));
2702 get_glyph_string_clip_rect (s, &clip_rect);
2704 if (s->face->box == FACE_SIMPLE_BOX)
2705 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2706 left_p, right_p, &clip_rect);
2707 else
2709 x_setup_relief_colors (s);
2710 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2711 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2716 /* Draw foreground of image glyph string S. */
2718 static void
2719 x_draw_image_foreground (s)
2720 struct glyph_string *s;
2722 int x = s->x;
2723 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2725 /* If first glyph of S has a left box line, start drawing it to the
2726 right of that line. */
2727 if (s->face->box != FACE_NO_BOX
2728 && s->first_glyph->left_box_line_p
2729 && s->slice.x == 0)
2730 x += abs (s->face->box_line_width);
2732 /* If there is a margin around the image, adjust x- and y-position
2733 by that margin. */
2734 if (s->slice.x == 0)
2735 x += s->img->hmargin;
2736 if (s->slice.y == 0)
2737 y += s->img->vmargin;
2739 if (s->img->pixmap)
2741 x_set_glyph_string_clipping (s);
2743 if (s->img->mask)
2744 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2745 s->window, s->gc, s->slice.x, s->slice.y,
2746 s->slice.width, s->slice.height, x, y);
2747 else
2749 mac_copy_area (s->display, s->img->pixmap,
2750 s->window, s->gc, s->slice.x, s->slice.y,
2751 s->slice.width, s->slice.height, x, y);
2753 /* When the image has a mask, we can expect that at
2754 least part of a mouse highlight or a block cursor will
2755 be visible. If the image doesn't have a mask, make
2756 a block cursor visible by drawing a rectangle around
2757 the image. I believe it's looking better if we do
2758 nothing here for mouse-face. */
2759 if (s->hl == DRAW_CURSOR)
2761 int r = s->img->relief;
2762 if (r < 0) r = -r;
2763 mac_draw_rectangle (s->display, s->window, s->gc,
2764 x - r, y - r,
2765 s->slice.width + r*2 - 1,
2766 s->slice.height + r*2 - 1);
2770 else
2771 /* Draw a rectangle if image could not be loaded. */
2772 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2773 s->slice.width - 1, s->slice.height - 1);
2777 /* Draw a relief around the image glyph string S. */
2779 static void
2780 x_draw_image_relief (s)
2781 struct glyph_string *s;
2783 int x0, y0, x1, y1, thick, raised_p;
2784 Rect r;
2785 int x = s->x;
2786 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2788 /* If first glyph of S has a left box line, start drawing it to the
2789 right of that line. */
2790 if (s->face->box != FACE_NO_BOX
2791 && s->first_glyph->left_box_line_p
2792 && s->slice.x == 0)
2793 x += abs (s->face->box_line_width);
2795 /* If there is a margin around the image, adjust x- and y-position
2796 by that margin. */
2797 if (s->slice.x == 0)
2798 x += s->img->hmargin;
2799 if (s->slice.y == 0)
2800 y += s->img->vmargin;
2802 if (s->hl == DRAW_IMAGE_SUNKEN
2803 || s->hl == DRAW_IMAGE_RAISED)
2805 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2806 raised_p = s->hl == DRAW_IMAGE_RAISED;
2808 else
2810 thick = abs (s->img->relief);
2811 raised_p = s->img->relief > 0;
2814 x0 = x - thick;
2815 y0 = y - thick;
2816 x1 = x + s->slice.width + thick - 1;
2817 y1 = y + s->slice.height + thick - 1;
2819 x_setup_relief_colors (s);
2820 get_glyph_string_clip_rect (s, &r);
2821 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2822 s->slice.y == 0,
2823 s->slice.y + s->slice.height == s->img->height,
2824 s->slice.x == 0,
2825 s->slice.x + s->slice.width == s->img->width,
2826 &r);
2830 #if 0 /* TODO: figure out if we need to do this on Mac. */
2831 /* Draw the foreground of image glyph string S to PIXMAP. */
2833 static void
2834 x_draw_image_foreground_1 (s, pixmap)
2835 struct glyph_string *s;
2836 Pixmap pixmap;
2838 int x = 0;
2839 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2841 /* If first glyph of S has a left box line, start drawing it to the
2842 right of that line. */
2843 if (s->face->box != FACE_NO_BOX
2844 && s->first_glyph->left_box_line_p
2845 && s->slice.x == 0)
2846 x += abs (s->face->box_line_width);
2848 /* If there is a margin around the image, adjust x- and y-position
2849 by that margin. */
2850 if (s->slice.x == 0)
2851 x += s->img->hmargin;
2852 if (s->slice.y == 0)
2853 y += s->img->vmargin;
2855 if (s->img->pixmap)
2857 if (s->img->mask)
2858 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2859 s->img->mask, pixmap, s->gc,
2860 s->slice.x, s->slice.y,
2861 s->slice.width, s->slice.height,
2862 x, y);
2863 else
2865 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2866 s->slice.x, s->slice.y,
2867 s->slice.width, s->slice.height,
2868 x, y);
2870 /* When the image has a mask, we can expect that at
2871 least part of a mouse highlight or a block cursor will
2872 be visible. If the image doesn't have a mask, make
2873 a block cursor visible by drawing a rectangle around
2874 the image. I believe it's looking better if we do
2875 nothing here for mouse-face. */
2876 if (s->hl == DRAW_CURSOR)
2878 int r = s->img->relief;
2879 if (r < 0) r = -r;
2880 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2881 s->slice.width + r*2 - 1,
2882 s->slice.height + r*2 - 1);
2886 else
2887 /* Draw a rectangle if image could not be loaded. */
2888 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2889 s->slice.width - 1, s->slice.height - 1);
2891 #endif
2894 /* Draw part of the background of glyph string S. X, Y, W, and H
2895 give the rectangle to draw. */
2897 static void
2898 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2899 struct glyph_string *s;
2900 int x, y, w, h;
2902 #if 0 /* MAC_TODO: stipple */
2903 if (s->stippled_p)
2905 /* Fill background with a stipple pattern. */
2906 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2907 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2908 XSetFillStyle (s->display, s->gc, FillSolid);
2910 else
2911 #endif /* MAC_TODO */
2912 x_clear_glyph_string_rect (s, x, y, w, h);
2916 /* Draw image glyph string S.
2918 s->y
2919 s->x +-------------------------
2920 | s->face->box
2922 | +-------------------------
2923 | | s->img->margin
2925 | | +-------------------
2926 | | | the image
2930 static void
2931 x_draw_image_glyph_string (s)
2932 struct glyph_string *s;
2934 int x, y;
2935 int box_line_hwidth = abs (s->face->box_line_width);
2936 int box_line_vwidth = max (s->face->box_line_width, 0);
2937 int height;
2938 Pixmap pixmap = 0;
2940 height = s->height - 2 * box_line_vwidth;
2943 /* Fill background with face under the image. Do it only if row is
2944 taller than image or if image has a clip mask to reduce
2945 flickering. */
2946 s->stippled_p = s->face->stipple != 0;
2947 if (height > s->slice.height
2948 || s->img->hmargin
2949 || s->img->vmargin
2950 || s->img->mask
2951 || s->img->pixmap == 0
2952 || s->width != s->background_width)
2954 x = s->x;
2955 if (s->first_glyph->left_box_line_p
2956 && s->slice.x == 0)
2957 x += box_line_hwidth;
2959 y = s->y;
2960 if (s->slice.y == 0)
2961 y += box_line_vwidth;
2963 #if 0 /* TODO: figure out if we need to do this on Mac. */
2964 if (s->img->mask)
2966 /* Create a pixmap as large as the glyph string. Fill it
2967 with the background color. Copy the image to it, using
2968 its mask. Copy the temporary pixmap to the display. */
2969 int depth = one_mac_display_info.n_planes;
2971 /* Create a pixmap as large as the glyph string. */
2972 pixmap = XCreatePixmap (s->display, s->window,
2973 s->background_width,
2974 s->height, depth);
2976 /* Fill the pixmap with the background color/stipple. */
2977 #if 0 /* TODO: stipple */
2978 if (s->stippled_p)
2980 /* Fill background with a stipple pattern. */
2981 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2982 XFillRectangle (s->display, pixmap, s->gc,
2983 0, 0, s->background_width, s->height);
2984 XSetFillStyle (s->display, s->gc, FillSolid);
2986 else
2987 #endif
2989 XGCValues xgcv;
2990 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2991 &xgcv);
2992 XSetForeground (s->display, s->gc, xgcv.background);
2993 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2994 0, 0, s->background_width,
2995 s->height);
2996 XSetForeground (s->display, s->gc, xgcv.foreground);
2999 else
3000 #endif
3001 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3003 s->background_filled_p = 1;
3006 /* Draw the foreground. */
3007 #if 0 /* TODO: figure out if we need to do this on Mac. */
3008 if (pixmap != 0)
3010 x_draw_image_foreground_1 (s, pixmap);
3011 x_set_glyph_string_clipping (s);
3012 mac_copy_area (s->display, pixmap, s->window, s->gc,
3013 0, 0, s->background_width, s->height, s->x, s->y);
3014 mac_reset_clipping (s->display, s->window);
3015 XFreePixmap (s->display, pixmap);
3017 else
3018 #endif
3019 x_draw_image_foreground (s);
3021 /* If we must draw a relief around the image, do it. */
3022 if (s->img->relief
3023 || s->hl == DRAW_IMAGE_RAISED
3024 || s->hl == DRAW_IMAGE_SUNKEN)
3025 x_draw_image_relief (s);
3029 /* Draw stretch glyph string S. */
3031 static void
3032 x_draw_stretch_glyph_string (s)
3033 struct glyph_string *s;
3035 xassert (s->first_glyph->type == STRETCH_GLYPH);
3036 s->stippled_p = s->face->stipple != 0;
3038 if (s->hl == DRAW_CURSOR
3039 && !x_stretch_cursor_p)
3041 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3042 as wide as the stretch glyph. */
3043 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
3045 /* Draw cursor. */
3046 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3048 /* Clear rest using the GC of the original non-cursor face. */
3049 if (width < s->background_width)
3051 int x = s->x + width, y = s->y;
3052 int w = s->background_width - width, h = s->height;
3053 Rect r;
3054 GC gc;
3056 if (s->row->mouse_face_p
3057 && cursor_in_mouse_face_p (s->w))
3059 x_set_mouse_face_gc (s);
3060 gc = s->gc;
3062 else
3063 gc = s->face->gc;
3065 get_glyph_string_clip_rect (s, &r);
3066 mac_set_clip_rectangle (s->display, s->window, &r);
3068 #if 0 /* MAC_TODO: stipple */
3069 if (s->face->stipple)
3071 /* Fill background with a stipple pattern. */
3072 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3073 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3074 XSetFillStyle (s->display, gc, FillSolid);
3076 else
3077 #endif /* MAC_TODO */
3079 XGCValues xgcv;
3080 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3081 XSetForeground (s->display, gc, xgcv.background);
3082 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3083 XSetForeground (s->display, gc, xgcv.foreground);
3086 mac_reset_clipping (s->display, s->window);
3089 else if (!s->background_filled_p)
3090 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3091 s->height);
3093 s->background_filled_p = 1;
3097 /* Draw glyph string S. */
3099 static void
3100 x_draw_glyph_string (s)
3101 struct glyph_string *s;
3103 int relief_drawn_p = 0;
3105 /* If S draws into the background of its successor that does not
3106 draw a cursor, draw the background of the successor first so that
3107 S can draw into it. This makes S->next use XDrawString instead
3108 of XDrawImageString. */
3109 if (s->next && s->right_overhang && !s->for_overlaps_p
3110 && s->next->hl != DRAW_CURSOR)
3112 xassert (s->next->img == NULL);
3113 x_set_glyph_string_gc (s->next);
3114 x_set_glyph_string_clipping (s->next);
3115 x_draw_glyph_string_background (s->next, 1);
3118 /* Set up S->gc, set clipping and draw S. */
3119 x_set_glyph_string_gc (s);
3121 /* Draw relief (if any) in advance for char/composition so that the
3122 glyph string can be drawn over it. */
3123 if (!s->for_overlaps_p
3124 && s->face->box != FACE_NO_BOX
3125 && (s->first_glyph->type == CHAR_GLYPH
3126 || s->first_glyph->type == COMPOSITE_GLYPH))
3129 x_set_glyph_string_clipping (s);
3130 x_draw_glyph_string_background (s, 1);
3131 x_draw_glyph_string_box (s);
3132 x_set_glyph_string_clipping (s);
3133 relief_drawn_p = 1;
3135 else
3136 x_set_glyph_string_clipping (s);
3138 switch (s->first_glyph->type)
3140 case IMAGE_GLYPH:
3141 x_draw_image_glyph_string (s);
3142 break;
3144 case STRETCH_GLYPH:
3145 x_draw_stretch_glyph_string (s);
3146 break;
3148 case CHAR_GLYPH:
3149 if (s->for_overlaps_p)
3150 s->background_filled_p = 1;
3151 else
3152 x_draw_glyph_string_background (s, 0);
3153 x_draw_glyph_string_foreground (s);
3154 break;
3156 case COMPOSITE_GLYPH:
3157 if (s->for_overlaps_p || s->gidx > 0)
3158 s->background_filled_p = 1;
3159 else
3160 x_draw_glyph_string_background (s, 1);
3161 x_draw_composite_glyph_string_foreground (s);
3162 break;
3164 default:
3165 abort ();
3168 if (!s->for_overlaps_p)
3170 /* Draw underline. */
3171 if (s->face->underline_p)
3173 unsigned long h = 1;
3174 unsigned long dy = s->height - h;
3176 if (s->face->underline_defaulted_p)
3177 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3178 s->width, h);
3179 else
3181 XGCValues xgcv;
3182 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3183 XSetForeground (s->display, s->gc, s->face->underline_color);
3184 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3185 s->width, h);
3186 XSetForeground (s->display, s->gc, xgcv.foreground);
3190 /* Draw overline. */
3191 if (s->face->overline_p)
3193 unsigned long dy = 0, h = 1;
3195 if (s->face->overline_color_defaulted_p)
3196 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3197 s->width, h);
3198 else
3200 XGCValues xgcv;
3201 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3202 XSetForeground (s->display, s->gc, s->face->overline_color);
3203 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3204 s->width, h);
3205 XSetForeground (s->display, s->gc, xgcv.foreground);
3209 /* Draw strike-through. */
3210 if (s->face->strike_through_p)
3212 unsigned long h = 1;
3213 unsigned long dy = (s->height - h) / 2;
3215 if (s->face->strike_through_color_defaulted_p)
3216 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3217 s->width, h);
3218 else
3220 XGCValues xgcv;
3221 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3222 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3223 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3224 s->width, h);
3225 XSetForeground (s->display, s->gc, xgcv.foreground);
3229 /* Draw relief if not yet drawn. */
3230 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3231 x_draw_glyph_string_box (s);
3234 /* Reset clipping. */
3235 mac_reset_clipping (s->display, s->window);
3238 /* Shift display to make room for inserted glyphs. */
3240 void
3241 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3242 struct frame *f;
3243 int x, y, width, height, shift_by;
3245 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3246 f->output_data.mac->normal_gc,
3247 x, y, width, height,
3248 x + shift_by, y);
3251 /* Delete N glyphs at the nominal cursor position. Not implemented
3252 for X frames. */
3254 static void
3255 x_delete_glyphs (n)
3256 register int n;
3258 abort ();
3262 /* Clear entire frame. If updating_frame is non-null, clear that
3263 frame. Otherwise clear the selected frame. */
3265 static void
3266 x_clear_frame ()
3268 struct frame *f;
3270 if (updating_frame)
3271 f = updating_frame;
3272 else
3273 f = SELECTED_FRAME ();
3275 /* Clearing the frame will erase any cursor, so mark them all as no
3276 longer visible. */
3277 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3278 output_cursor.hpos = output_cursor.vpos = 0;
3279 output_cursor.x = -1;
3281 /* We don't set the output cursor here because there will always
3282 follow an explicit cursor_to. */
3283 BLOCK_INPUT;
3284 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3286 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3287 /* We have to clear the scroll bars, too. If we have changed
3288 colors or something like that, then they should be notified. */
3289 x_scroll_bar_clear (f);
3290 #endif
3292 XFlush (FRAME_MAC_DISPLAY (f));
3293 UNBLOCK_INPUT;
3298 /* Invert the middle quarter of the frame for .15 sec. */
3300 /* We use the select system call to do the waiting, so we have to make
3301 sure it's available. If it isn't, we just won't do visual bells. */
3303 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3306 /* Subtract the `struct timeval' values X and Y, storing the result in
3307 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3309 static int
3310 timeval_subtract (result, x, y)
3311 struct timeval *result, x, y;
3313 /* Perform the carry for the later subtraction by updating y. This
3314 is safer because on some systems the tv_sec member is unsigned. */
3315 if (x.tv_usec < y.tv_usec)
3317 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3318 y.tv_usec -= 1000000 * nsec;
3319 y.tv_sec += nsec;
3322 if (x.tv_usec - y.tv_usec > 1000000)
3324 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3325 y.tv_usec += 1000000 * nsec;
3326 y.tv_sec -= nsec;
3329 /* Compute the time remaining to wait. tv_usec is certainly
3330 positive. */
3331 result->tv_sec = x.tv_sec - y.tv_sec;
3332 result->tv_usec = x.tv_usec - y.tv_usec;
3334 /* Return indication of whether the result should be considered
3335 negative. */
3336 return x.tv_sec < y.tv_sec;
3339 void
3340 XTflash (f)
3341 struct frame *f;
3343 BLOCK_INPUT;
3345 FlashMenuBar (0);
3348 struct timeval wakeup;
3350 EMACS_GET_TIME (wakeup);
3352 /* Compute time to wait until, propagating carry from usecs. */
3353 wakeup.tv_usec += 150000;
3354 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3355 wakeup.tv_usec %= 1000000;
3357 /* Keep waiting until past the time wakeup. */
3358 while (1)
3360 struct timeval timeout;
3362 EMACS_GET_TIME (timeout);
3364 /* In effect, timeout = wakeup - timeout.
3365 Break if result would be negative. */
3366 if (timeval_subtract (&timeout, wakeup, timeout))
3367 break;
3369 /* Try to wait that long--but we might wake up sooner. */
3370 select (0, NULL, NULL, NULL, &timeout);
3374 FlashMenuBar (0);
3376 UNBLOCK_INPUT;
3379 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3382 /* Make audible bell. */
3384 void
3385 XTring_bell ()
3387 struct frame *f = SELECTED_FRAME ();
3389 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3390 if (visible_bell)
3391 XTflash (f);
3392 else
3393 #endif
3395 BLOCK_INPUT;
3396 SysBeep (1);
3397 XFlush (FRAME_MAC_DISPLAY (f));
3398 UNBLOCK_INPUT;
3404 /* Specify how many text lines, from the top of the window,
3405 should be affected by insert-lines and delete-lines operations.
3406 This, and those operations, are used only within an update
3407 that is bounded by calls to x_update_begin and x_update_end. */
3409 static void
3410 XTset_terminal_window (n)
3411 register int n;
3413 /* This function intentionally left blank. */
3418 /***********************************************************************
3419 Line Dance
3420 ***********************************************************************/
3422 /* Perform an insert-lines or delete-lines operation, inserting N
3423 lines or deleting -N lines at vertical position VPOS. */
3425 static void
3426 x_ins_del_lines (vpos, n)
3427 int vpos, n;
3429 abort ();
3433 /* Scroll part of the display as described by RUN. */
3435 static void
3436 x_scroll_run (w, run)
3437 struct window *w;
3438 struct run *run;
3440 struct frame *f = XFRAME (w->frame);
3441 int x, y, width, height, from_y, to_y, bottom_y;
3443 /* Get frame-relative bounding box of the text display area of W,
3444 without mode lines. Include in this box the left and right
3445 fringe of W. */
3446 window_box (w, -1, &x, &y, &width, &height);
3448 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3449 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3450 bottom_y = y + height;
3452 if (to_y < from_y)
3454 /* Scrolling up. Make sure we don't copy part of the mode
3455 line at the bottom. */
3456 if (from_y + run->height > bottom_y)
3457 height = bottom_y - from_y;
3458 else
3459 height = run->height;
3461 else
3463 /* Scolling down. Make sure we don't copy over the mode line.
3464 at the bottom. */
3465 if (to_y + run->height > bottom_y)
3466 height = bottom_y - to_y;
3467 else
3468 height = run->height;
3471 BLOCK_INPUT;
3473 /* Cursor off. Will be switched on again in x_update_window_end. */
3474 updated_window = w;
3475 x_clear_cursor (w);
3477 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3478 f->output_data.mac->normal_gc,
3479 x, from_y,
3480 width, height,
3481 x, to_y);
3483 UNBLOCK_INPUT;
3488 /***********************************************************************
3489 Exposure Events
3490 ***********************************************************************/
3493 static void
3494 frame_highlight (f)
3495 struct frame *f;
3497 x_update_cursor (f, 1);
3500 static void
3501 frame_unhighlight (f)
3502 struct frame *f;
3504 x_update_cursor (f, 1);
3507 /* The focus has changed. Update the frames as necessary to reflect
3508 the new situation. Note that we can't change the selected frame
3509 here, because the Lisp code we are interrupting might become confused.
3510 Each event gets marked with the frame in which it occurred, so the
3511 Lisp code can tell when the switch took place by examining the events. */
3513 static void
3514 x_new_focus_frame (dpyinfo, frame)
3515 struct x_display_info *dpyinfo;
3516 struct frame *frame;
3518 struct frame *old_focus = dpyinfo->x_focus_frame;
3520 if (frame != dpyinfo->x_focus_frame)
3522 /* Set this before calling other routines, so that they see
3523 the correct value of x_focus_frame. */
3524 dpyinfo->x_focus_frame = frame;
3526 if (old_focus && old_focus->auto_lower)
3527 x_lower_frame (old_focus);
3529 #if 0
3530 selected_frame = frame;
3531 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3532 selected_frame);
3533 Fselect_window (selected_frame->selected_window, Qnil);
3534 choose_minibuf_frame ();
3535 #endif /* ! 0 */
3537 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3538 pending_autoraise_frame = dpyinfo->x_focus_frame;
3539 else
3540 pending_autoraise_frame = 0;
3543 x_frame_rehighlight (dpyinfo);
3546 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3548 void
3549 x_mouse_leave (dpyinfo)
3550 struct x_display_info *dpyinfo;
3552 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3555 /* The focus has changed, or we have redirected a frame's focus to
3556 another frame (this happens when a frame uses a surrogate
3557 mini-buffer frame). Shift the highlight as appropriate.
3559 The FRAME argument doesn't necessarily have anything to do with which
3560 frame is being highlighted or un-highlighted; we only use it to find
3561 the appropriate X display info. */
3563 static void
3564 XTframe_rehighlight (frame)
3565 struct frame *frame;
3567 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3570 static void
3571 x_frame_rehighlight (dpyinfo)
3572 struct x_display_info *dpyinfo;
3574 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3576 if (dpyinfo->x_focus_frame)
3578 dpyinfo->x_highlight_frame
3579 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3580 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3581 : dpyinfo->x_focus_frame);
3582 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3584 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3585 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3588 else
3589 dpyinfo->x_highlight_frame = 0;
3591 if (dpyinfo->x_highlight_frame != old_highlight)
3593 if (old_highlight)
3594 frame_unhighlight (old_highlight);
3595 if (dpyinfo->x_highlight_frame)
3596 frame_highlight (dpyinfo->x_highlight_frame);
3602 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3604 #if 0 /* MAC_TODO */
3605 /* Initialize mode_switch_bit and modifier_meaning. */
3606 static void
3607 x_find_modifier_meanings (dpyinfo)
3608 struct x_display_info *dpyinfo;
3610 int min_code, max_code;
3611 KeySym *syms;
3612 int syms_per_code;
3613 XModifierKeymap *mods;
3615 dpyinfo->meta_mod_mask = 0;
3616 dpyinfo->shift_lock_mask = 0;
3617 dpyinfo->alt_mod_mask = 0;
3618 dpyinfo->super_mod_mask = 0;
3619 dpyinfo->hyper_mod_mask = 0;
3621 #ifdef HAVE_X11R4
3622 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3623 #else
3624 min_code = dpyinfo->display->min_keycode;
3625 max_code = dpyinfo->display->max_keycode;
3626 #endif
3628 syms = XGetKeyboardMapping (dpyinfo->display,
3629 min_code, max_code - min_code + 1,
3630 &syms_per_code);
3631 mods = XGetModifierMapping (dpyinfo->display);
3633 /* Scan the modifier table to see which modifier bits the Meta and
3634 Alt keysyms are on. */
3636 int row, col; /* The row and column in the modifier table. */
3638 for (row = 3; row < 8; row++)
3639 for (col = 0; col < mods->max_keypermod; col++)
3641 KeyCode code
3642 = mods->modifiermap[(row * mods->max_keypermod) + col];
3644 /* Zeroes are used for filler. Skip them. */
3645 if (code == 0)
3646 continue;
3648 /* Are any of this keycode's keysyms a meta key? */
3650 int code_col;
3652 for (code_col = 0; code_col < syms_per_code; code_col++)
3654 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3656 switch (sym)
3658 case XK_Meta_L:
3659 case XK_Meta_R:
3660 dpyinfo->meta_mod_mask |= (1 << row);
3661 break;
3663 case XK_Alt_L:
3664 case XK_Alt_R:
3665 dpyinfo->alt_mod_mask |= (1 << row);
3666 break;
3668 case XK_Hyper_L:
3669 case XK_Hyper_R:
3670 dpyinfo->hyper_mod_mask |= (1 << row);
3671 break;
3673 case XK_Super_L:
3674 case XK_Super_R:
3675 dpyinfo->super_mod_mask |= (1 << row);
3676 break;
3678 case XK_Shift_Lock:
3679 /* Ignore this if it's not on the lock modifier. */
3680 if ((1 << row) == LockMask)
3681 dpyinfo->shift_lock_mask = LockMask;
3682 break;
3689 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3690 if (! dpyinfo->meta_mod_mask)
3692 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3693 dpyinfo->alt_mod_mask = 0;
3696 /* If some keys are both alt and meta,
3697 make them just meta, not alt. */
3698 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3700 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3703 XFree ((char *) syms);
3704 XFreeModifiermap (mods);
3707 #endif /* MAC_TODO */
3709 /* Convert between the modifier bits X uses and the modifier bits
3710 Emacs uses. */
3712 static unsigned int
3713 x_mac_to_emacs_modifiers (dpyinfo, state)
3714 struct x_display_info *dpyinfo;
3715 unsigned short state;
3717 return (((state & shiftKey) ? shift_modifier : 0)
3718 | ((state & controlKey) ? ctrl_modifier : 0)
3719 | ((state & cmdKey) ? meta_modifier : 0)
3720 | ((state & optionKey) ? alt_modifier : 0));
3723 #if 0 /* MAC_TODO */
3724 static unsigned short
3725 x_emacs_to_x_modifiers (dpyinfo, state)
3726 struct x_display_info *dpyinfo;
3727 unsigned int state;
3729 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3730 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3731 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3732 | ((state & shift_modifier) ? ShiftMask : 0)
3733 | ((state & ctrl_modifier) ? ControlMask : 0)
3734 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3736 #endif /* MAC_TODO */
3738 /* Convert a keysym to its name. */
3740 char *
3741 x_get_keysym_name (keysym)
3742 int keysym;
3744 char *value;
3746 BLOCK_INPUT;
3747 #if 0
3748 value = XKeysymToString (keysym);
3749 #else
3750 value = 0;
3751 #endif
3752 UNBLOCK_INPUT;
3754 return value;
3759 #if 0
3760 /* Mouse clicks and mouse movement. Rah. */
3762 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3764 If the event is a button press, then note that we have grabbed
3765 the mouse. */
3767 static Lisp_Object
3768 construct_mouse_click (result, event, f)
3769 struct input_event *result;
3770 EventRecord *event;
3771 struct frame *f;
3773 Point mouseLoc;
3775 result->kind = MOUSE_CLICK_EVENT;
3776 result->code = 0; /* only one mouse button */
3777 result->timestamp = event->when;
3778 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3780 mouseLoc = event->where;
3782 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3784 GlobalToLocal (&mouseLoc);
3785 XSETINT (result->x, mouseLoc.h);
3786 XSETINT (result->y, mouseLoc.v);
3788 XSETFRAME (result->frame_or_window, f);
3790 result->arg = Qnil;
3791 return Qnil;
3793 #endif
3796 /* Function to report a mouse movement to the mainstream Emacs code.
3797 The input handler calls this.
3799 We have received a mouse movement event, which is given in *event.
3800 If the mouse is over a different glyph than it was last time, tell
3801 the mainstream emacs code by setting mouse_moved. If not, ask for
3802 another motion event, so we can check again the next time it moves. */
3804 static Point last_mouse_motion_position;
3805 static Lisp_Object last_mouse_motion_frame;
3807 static void
3808 note_mouse_movement (frame, pos)
3809 FRAME_PTR frame;
3810 Point *pos;
3812 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3813 #if TARGET_API_MAC_CARBON
3814 Rect r;
3815 #endif
3817 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3818 last_mouse_motion_position = *pos;
3819 XSETFRAME (last_mouse_motion_frame, frame);
3821 #if TARGET_API_MAC_CARBON
3822 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3823 #else
3824 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3825 #endif
3827 if (frame == dpyinfo->mouse_face_mouse_frame)
3828 /* This case corresponds to LeaveNotify in X11. */
3830 /* If we move outside the frame, then we're certainly no
3831 longer on any text in the frame. */
3832 clear_mouse_face (dpyinfo);
3833 dpyinfo->mouse_face_mouse_frame = 0;
3834 if (!dpyinfo->grabbed)
3835 rif->define_frame_cursor (frame,
3836 frame->output_data.mac->nontext_cursor);
3839 /* Has the mouse moved off the glyph it was on at the last sighting? */
3840 else if (pos->h < last_mouse_glyph.left
3841 || pos->h >= last_mouse_glyph.right
3842 || pos->v < last_mouse_glyph.top
3843 || pos->v >= last_mouse_glyph.bottom)
3845 frame->mouse_moved = 1;
3846 last_mouse_scroll_bar = Qnil;
3847 note_mouse_highlight (frame, pos->h, pos->v);
3851 /* This is used for debugging, to turn off note_mouse_highlight. */
3853 int disable_mouse_highlight;
3857 /************************************************************************
3858 Mouse Face
3859 ************************************************************************/
3861 static struct scroll_bar *x_window_to_scroll_bar ();
3862 static void x_scroll_bar_report_motion ();
3863 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3866 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3868 static void
3869 redo_mouse_highlight ()
3871 if (!NILP (last_mouse_motion_frame)
3872 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3873 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3874 last_mouse_motion_position.h,
3875 last_mouse_motion_position.v);
3879 /* Try to determine frame pixel position and size of the glyph under
3880 frame pixel coordinates X/Y on frame F . Return the position and
3881 size in *RECT. Value is non-zero if we could compute these
3882 values. */
3884 static int
3885 glyph_rect (f, x, y, rect)
3886 struct frame *f;
3887 int x, y;
3888 Rect *rect;
3890 Lisp_Object window;
3892 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3894 if (!NILP (window))
3896 struct window *w = XWINDOW (window);
3897 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3898 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3900 for (; r < end && r->enabled_p; ++r)
3901 if (r->y <= y && r->y + r->height > y)
3903 /* Found the row at y. */
3904 struct glyph *g = r->glyphs[TEXT_AREA];
3905 struct glyph *end = g + r->used[TEXT_AREA];
3906 int gx;
3908 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3909 rect->bottom = rect->top + r->height;
3911 if (x < r->x)
3913 /* x is to the left of the first glyph in the row. */
3914 /* Shouldn't this be a pixel value?
3915 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3916 ++KFS */
3917 rect->left = WINDOW_LEFT_EDGE_COL (w);
3918 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3919 return 1;
3922 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3923 if (gx <= x && gx + g->pixel_width > x)
3925 /* x is on a glyph. */
3926 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3927 rect->right = rect->left + g->pixel_width;
3928 return 1;
3931 /* x is to the right of the last glyph in the row. */
3932 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3933 /* Shouldn't this be a pixel value?
3934 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3935 ++KFS */
3936 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3937 return 1;
3941 /* The y is not on any row. */
3942 return 0;
3945 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3947 /* Record the position of the mouse in last_mouse_glyph. */
3948 static void
3949 remember_mouse_glyph (f1, gx, gy)
3950 struct frame * f1;
3951 int gx, gy;
3953 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3955 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3956 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3958 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3959 round down even for negative values. */
3960 if (gx < 0)
3961 gx -= width - 1;
3962 if (gy < 0)
3963 gy -= height - 1;
3964 #if 0
3965 /* This was the original code from XTmouse_position, but it seems
3966 to give the position of the glyph diagonally next to the one
3967 the mouse is over. */
3968 gx = (gx + width - 1) / width * width;
3969 gy = (gy + height - 1) / height * height;
3970 #else
3971 gx = gx / width * width;
3972 gy = gy / height * height;
3973 #endif
3975 last_mouse_glyph.left = gx;
3976 last_mouse_glyph.top = gy;
3977 last_mouse_glyph.right = gx + width;
3978 last_mouse_glyph.bottom = gy + height;
3983 static WindowPtr
3984 front_emacs_window ()
3986 #if TARGET_API_MAC_CARBON
3987 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3989 while (wp && !is_emacs_window (wp))
3990 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3991 #else
3992 WindowPtr wp = FrontWindow ();
3994 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3995 wp = GetNextWindow (wp);
3996 #endif
3998 return wp;
4001 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
4003 /* Return the current position of the mouse.
4004 *fp should be a frame which indicates which display to ask about.
4006 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4007 and *part to the frame, window, and scroll bar part that the mouse
4008 is over. Set *x and *y to the portion and whole of the mouse's
4009 position on the scroll bar.
4011 If the mouse movement started elsewhere, set *fp to the frame the
4012 mouse is on, *bar_window to nil, and *x and *y to the character cell
4013 the mouse is over.
4015 Set *time to the server time-stamp for the time at which the mouse
4016 was at this position.
4018 Don't store anything if we don't have a valid set of values to report.
4020 This clears the mouse_moved flag, so we can wait for the next mouse
4021 movement. */
4023 static void
4024 XTmouse_position (fp, insist, bar_window, part, x, y, time)
4025 FRAME_PTR *fp;
4026 int insist;
4027 Lisp_Object *bar_window;
4028 enum scroll_bar_part *part;
4029 Lisp_Object *x, *y;
4030 unsigned long *time;
4032 Point mouse_pos;
4033 int ignore1, ignore2;
4034 WindowPtr wp = front_emacs_window ();
4035 struct frame *f;
4036 Lisp_Object frame, tail;
4038 if (is_emacs_window(wp))
4039 f = mac_window_to_frame (wp);
4041 BLOCK_INPUT;
4043 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4044 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4045 else
4047 /* Clear the mouse-moved flag for every frame on this display. */
4048 FOR_EACH_FRAME (tail, frame)
4049 XFRAME (frame)->mouse_moved = 0;
4051 last_mouse_scroll_bar = Qnil;
4053 SetPortWindowPort (wp);
4055 GetMouse (&mouse_pos);
4057 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
4058 &last_mouse_glyph, insist);
4060 *bar_window = Qnil;
4061 *part = scroll_bar_handle;
4062 *fp = f;
4063 XSETINT (*x, mouse_pos.h);
4064 XSETINT (*y, mouse_pos.v);
4065 *time = last_mouse_movement_time;
4068 UNBLOCK_INPUT;
4072 /***********************************************************************
4073 Tool-bars
4074 ***********************************************************************/
4076 /* Handle mouse button event on the tool-bar of frame F, at
4077 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4078 or ButtonRelase. */
4080 static void
4081 mac_handle_tool_bar_click (f, button_event)
4082 struct frame *f;
4083 EventRecord *button_event;
4085 int x = button_event->where.h;
4086 int y = button_event->where.v;
4088 if (button_event->what == mouseDown)
4089 handle_tool_bar_click (f, x, y, 1, 0);
4090 else
4091 handle_tool_bar_click (f, x, y, 0,
4092 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
4093 button_event->modifiers));
4097 /************************************************************************
4098 Scroll bars, general
4099 ************************************************************************/
4101 /* Create a scroll bar and return the scroll bar vector for it. W is
4102 the Emacs window on which to create the scroll bar. TOP, LEFT,
4103 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4104 scroll bar. */
4106 static struct scroll_bar *
4107 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4108 struct window *w;
4109 int top, left, width, height, disp_top, disp_height;
4111 struct frame *f = XFRAME (w->frame);
4112 struct scroll_bar *bar
4113 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4114 Rect r;
4115 ControlHandle ch;
4117 BLOCK_INPUT;
4119 r.left = left;
4120 r.top = disp_top;
4121 r.right = left + width;
4122 r.bottom = disp_top + disp_height;
4124 #if TARGET_API_MAC_CARBON
4125 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4126 kControlScrollBarProc, 0L);
4127 #else
4128 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4129 0L);
4130 #endif
4131 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4132 SetControlReference (ch, (long) bar);
4134 XSETWINDOW (bar->window, w);
4135 XSETINT (bar->top, top);
4136 XSETINT (bar->left, left);
4137 XSETINT (bar->width, width);
4138 XSETINT (bar->height, height);
4139 XSETINT (bar->start, 0);
4140 XSETINT (bar->end, 0);
4141 bar->dragging = Qnil;
4143 /* Add bar to its frame's list of scroll bars. */
4144 bar->next = FRAME_SCROLL_BARS (f);
4145 bar->prev = Qnil;
4146 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4147 if (!NILP (bar->next))
4148 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4150 UNBLOCK_INPUT;
4151 return bar;
4155 /* Draw BAR's handle in the proper position.
4157 If the handle is already drawn from START to END, don't bother
4158 redrawing it, unless REBUILD is non-zero; in that case, always
4159 redraw it. (REBUILD is handy for drawing the handle after expose
4160 events.)
4162 Normally, we want to constrain the start and end of the handle to
4163 fit inside its rectangle, but if the user is dragging the scroll
4164 bar handle, we want to let them drag it down all the way, so that
4165 the bar's top is as far down as it goes; otherwise, there's no way
4166 to move to the very end of the buffer. */
4168 static void
4169 x_scroll_bar_set_handle (bar, start, end, rebuild)
4170 struct scroll_bar *bar;
4171 int start, end;
4172 int rebuild;
4174 int dragging = ! NILP (bar->dragging);
4175 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4176 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4177 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4178 int length = end - start;
4180 /* If the display is already accurate, do nothing. */
4181 if (! rebuild
4182 && start == XINT (bar->start)
4183 && end == XINT (bar->end))
4184 return;
4186 BLOCK_INPUT;
4188 /* Make sure the values are reasonable, and try to preserve the
4189 distance between start and end. */
4190 if (start < 0)
4191 start = 0;
4192 else if (start > top_range)
4193 start = top_range;
4194 end = start + length;
4196 if (end < start)
4197 end = start;
4198 else if (end > top_range && ! dragging)
4199 end = top_range;
4201 /* Store the adjusted setting in the scroll bar. */
4202 XSETINT (bar->start, start);
4203 XSETINT (bar->end, end);
4205 /* Clip the end position, just for display. */
4206 if (end > top_range)
4207 end = top_range;
4209 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4210 top positions, to make sure the handle is always at least that
4211 many pixels tall. */
4212 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4214 SetControlMinimum (ch, 0);
4215 /* Don't inadvertently activate deactivated scroll bars */
4216 if (GetControlMaximum (ch) != -1)
4217 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4218 - (end - start));
4219 SetControlValue (ch, start);
4220 #if TARGET_API_MAC_CARBON
4221 SetControlViewSize (ch, end - start);
4222 #endif
4224 UNBLOCK_INPUT;
4228 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4229 nil. */
4231 static void
4232 x_scroll_bar_remove (bar)
4233 struct scroll_bar *bar;
4235 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4237 BLOCK_INPUT;
4239 /* Destroy the Mac scroll bar control */
4240 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4242 /* Disassociate this scroll bar from its window. */
4243 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4245 UNBLOCK_INPUT;
4248 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4249 that we are displaying PORTION characters out of a total of WHOLE
4250 characters, starting at POSITION. If WINDOW has no scroll bar,
4251 create one. */
4252 static void
4253 XTset_vertical_scroll_bar (w, portion, whole, position)
4254 struct window *w;
4255 int portion, whole, position;
4257 struct frame *f = XFRAME (w->frame);
4258 struct scroll_bar *bar;
4259 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4260 int window_y, window_height;
4262 /* Get window dimensions. */
4263 window_box (w, -1, 0, &window_y, 0, &window_height);
4264 top = window_y;
4265 #ifdef MAC_OSX
4266 width = 16;
4267 #else
4268 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4269 #endif
4270 height = window_height;
4272 /* Compute the left edge of the scroll bar area. */
4273 left = WINDOW_SCROLL_BAR_AREA_X (w);
4275 /* Compute the width of the scroll bar which might be less than
4276 the width of the area reserved for the scroll bar. */
4277 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4278 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4279 else
4280 sb_width = width;
4282 /* Compute the left edge of the scroll bar. */
4283 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4284 sb_left = left + width - sb_width - (width - sb_width) / 2;
4285 else
4286 sb_left = left + (width - sb_width) / 2;
4288 /* Adjustments according to Inside Macintosh to make it look nice */
4289 disp_top = top;
4290 disp_height = height;
4291 if (disp_top == 0)
4293 disp_top = -1;
4294 disp_height++;
4296 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4298 disp_top++;
4299 disp_height--;
4302 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4303 sb_left++;
4305 /* Does the scroll bar exist yet? */
4306 if (NILP (w->vertical_scroll_bar))
4308 BLOCK_INPUT;
4309 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4310 left, top, width, height, 0);
4311 UNBLOCK_INPUT;
4312 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4313 disp_height);
4314 XSETVECTOR (w->vertical_scroll_bar, bar);
4316 else
4318 /* It may just need to be moved and resized. */
4319 ControlHandle ch;
4321 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4322 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4324 BLOCK_INPUT;
4326 /* If already correctly positioned, do nothing. */
4327 if (XINT (bar->left) == sb_left
4328 && XINT (bar->top) == top
4329 && XINT (bar->width) == sb_width
4330 && XINT (bar->height) == height)
4331 Draw1Control (ch);
4332 else
4334 /* Clear areas not covered by the scroll bar because it's not as
4335 wide as the area reserved for it . This makes sure a
4336 previous mode line display is cleared after C-x 2 C-x 1, for
4337 example. */
4338 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4339 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4340 left, top, area_width, height, 0);
4342 #if 0
4343 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4344 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4345 sb_left - 1, top, 1, height, 0);
4346 #endif
4348 HideControl (ch);
4349 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4350 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4351 disp_height);
4352 ShowControl (ch);
4354 /* Remember new settings. */
4355 XSETINT (bar->left, sb_left);
4356 XSETINT (bar->top, top);
4357 XSETINT (bar->width, sb_width);
4358 XSETINT (bar->height, height);
4361 UNBLOCK_INPUT;
4364 /* Set the scroll bar's current state, unless we're currently being
4365 dragged. */
4366 if (NILP (bar->dragging))
4368 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4370 if (whole == 0)
4371 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4372 else
4374 int start = ((double) position * top_range) / whole;
4375 int end = ((double) (position + portion) * top_range) / whole;
4376 x_scroll_bar_set_handle (bar, start, end, 0);
4382 /* The following three hooks are used when we're doing a thorough
4383 redisplay of the frame. We don't explicitly know which scroll bars
4384 are going to be deleted, because keeping track of when windows go
4385 away is a real pain - "Can you say set-window-configuration, boys
4386 and girls?" Instead, we just assert at the beginning of redisplay
4387 that *all* scroll bars are to be removed, and then save a scroll bar
4388 from the fiery pit when we actually redisplay its window. */
4390 /* Arrange for all scroll bars on FRAME to be removed at the next call
4391 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4392 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4394 static void
4395 XTcondemn_scroll_bars (frame)
4396 FRAME_PTR frame;
4398 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4399 while (! NILP (FRAME_SCROLL_BARS (frame)))
4401 Lisp_Object bar;
4402 bar = FRAME_SCROLL_BARS (frame);
4403 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4404 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4405 XSCROLL_BAR (bar)->prev = Qnil;
4406 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4407 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4408 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4413 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4414 Note that WINDOW isn't necessarily condemned at all. */
4416 static void
4417 XTredeem_scroll_bar (window)
4418 struct window *window;
4420 struct scroll_bar *bar;
4422 /* We can't redeem this window's scroll bar if it doesn't have one. */
4423 if (NILP (window->vertical_scroll_bar))
4424 abort ();
4426 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4428 /* Unlink it from the condemned list. */
4430 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4432 if (NILP (bar->prev))
4434 /* If the prev pointer is nil, it must be the first in one of
4435 the lists. */
4436 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4437 /* It's not condemned. Everything's fine. */
4438 return;
4439 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4440 window->vertical_scroll_bar))
4441 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4442 else
4443 /* If its prev pointer is nil, it must be at the front of
4444 one or the other! */
4445 abort ();
4447 else
4448 XSCROLL_BAR (bar->prev)->next = bar->next;
4450 if (! NILP (bar->next))
4451 XSCROLL_BAR (bar->next)->prev = bar->prev;
4453 bar->next = FRAME_SCROLL_BARS (f);
4454 bar->prev = Qnil;
4455 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4456 if (! NILP (bar->next))
4457 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4461 /* Remove all scroll bars on FRAME that haven't been saved since the
4462 last call to `*condemn_scroll_bars_hook'. */
4464 static void
4465 XTjudge_scroll_bars (f)
4466 FRAME_PTR f;
4468 Lisp_Object bar, next;
4470 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4472 /* Clear out the condemned list now so we won't try to process any
4473 more events on the hapless scroll bars. */
4474 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4476 for (; ! NILP (bar); bar = next)
4478 struct scroll_bar *b = XSCROLL_BAR (bar);
4480 x_scroll_bar_remove (b);
4482 next = b->next;
4483 b->next = b->prev = Qnil;
4486 /* Now there should be no references to the condemned scroll bars,
4487 and they should get garbage-collected. */
4491 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4492 is set to something other than NO_EVENT, it is enqueued.
4494 This may be called from a signal handler, so we have to ignore GC
4495 mark bits. */
4497 static void
4498 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4499 struct scroll_bar *bar;
4500 int part_code;
4501 EventRecord *er;
4502 struct input_event *bufp;
4504 int win_y, top_range;
4506 if (! GC_WINDOWP (bar->window))
4507 abort ();
4509 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4510 bufp->frame_or_window = bar->window;
4511 bufp->arg = Qnil;
4513 bar->dragging = Qnil;
4515 switch (part_code)
4517 case kControlUpButtonPart:
4518 bufp->part = scroll_bar_up_arrow;
4519 break;
4520 case kControlDownButtonPart:
4521 bufp->part = scroll_bar_down_arrow;
4522 break;
4523 case kControlPageUpPart:
4524 bufp->part = scroll_bar_above_handle;
4525 break;
4526 case kControlPageDownPart:
4527 bufp->part = scroll_bar_below_handle;
4528 break;
4529 #if TARGET_API_MAC_CARBON
4530 default:
4531 #else
4532 case kControlIndicatorPart:
4533 #endif
4534 if (er->what == mouseDown)
4535 bar->dragging = make_number (0);
4536 XSETVECTOR (last_mouse_scroll_bar, bar);
4537 bufp->part = scroll_bar_handle;
4538 break;
4541 win_y = XINT (bufp->y) - XINT (bar->top);
4542 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4544 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4546 win_y -= 24;
4548 if (! NILP (bar->dragging))
4549 win_y -= XINT (bar->dragging);
4551 if (win_y < 0)
4552 win_y = 0;
4553 if (win_y > top_range)
4554 win_y = top_range;
4556 XSETINT (bufp->x, win_y);
4557 XSETINT (bufp->y, top_range);
4561 /* Handle some mouse motion while someone is dragging the scroll bar.
4563 This may be called from a signal handler, so we have to ignore GC
4564 mark bits. */
4566 static void
4567 x_scroll_bar_note_movement (bar, y_pos, t)
4568 struct scroll_bar *bar;
4569 int y_pos;
4570 Time t;
4572 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4574 last_mouse_movement_time = t;
4576 f->mouse_moved = 1;
4577 XSETVECTOR (last_mouse_scroll_bar, bar);
4579 /* If we're dragging the bar, display it. */
4580 if (! GC_NILP (bar->dragging))
4582 /* Where should the handle be now? */
4583 int new_start = y_pos - 24;
4585 if (new_start != XINT (bar->start))
4587 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4589 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4595 /* Return information to the user about the current position of the
4596 mouse on the scroll bar. */
4598 static void
4599 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4600 FRAME_PTR *fp;
4601 Lisp_Object *bar_window;
4602 enum scroll_bar_part *part;
4603 Lisp_Object *x, *y;
4604 unsigned long *time;
4606 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4607 WindowPtr wp = front_emacs_window ();
4608 Point mouse_pos;
4609 struct frame *f = mac_window_to_frame (wp);
4610 int win_y, top_range;
4612 SetPortWindowPort (wp);
4614 GetMouse (&mouse_pos);
4616 win_y = mouse_pos.v - XINT (bar->top);
4617 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4619 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4621 win_y -= 24;
4623 if (! NILP (bar->dragging))
4624 win_y -= XINT (bar->dragging);
4626 if (win_y < 0)
4627 win_y = 0;
4628 if (win_y > top_range)
4629 win_y = top_range;
4631 *fp = f;
4632 *bar_window = bar->window;
4634 if (! NILP (bar->dragging))
4635 *part = scroll_bar_handle;
4636 else if (win_y < XINT (bar->start))
4637 *part = scroll_bar_above_handle;
4638 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4639 *part = scroll_bar_handle;
4640 else
4641 *part = scroll_bar_below_handle;
4643 XSETINT (*x, win_y);
4644 XSETINT (*y, top_range);
4646 f->mouse_moved = 0;
4647 last_mouse_scroll_bar = Qnil;
4649 *time = last_mouse_movement_time;
4652 /***********************************************************************
4653 Text Cursor
4654 ***********************************************************************/
4656 /* Set clipping for output in glyph row ROW. W is the window in which
4657 we operate. GC is the graphics context to set clipping in.
4659 ROW may be a text row or, e.g., a mode line. Text rows must be
4660 clipped to the interior of the window dedicated to text display,
4661 mode lines must be clipped to the whole window. */
4663 static void
4664 x_clip_to_row (w, row, area, gc)
4665 struct window *w;
4666 struct glyph_row *row;
4667 int area;
4668 GC gc;
4670 struct frame *f = XFRAME (WINDOW_FRAME (w));
4671 Rect clip_rect;
4672 int window_x, window_y, window_width;
4674 window_box (w, area, &window_x, &window_y, &window_width, 0);
4676 clip_rect.left = window_x;
4677 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4678 clip_rect.top = max (clip_rect.top, window_y);
4679 clip_rect.right = clip_rect.left + window_width;
4680 clip_rect.bottom = clip_rect.top + row->visible_height;
4682 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4686 /* Draw a hollow box cursor on window W in glyph row ROW. */
4688 static void
4689 x_draw_hollow_cursor (w, row)
4690 struct window *w;
4691 struct glyph_row *row;
4693 struct frame *f = XFRAME (WINDOW_FRAME (w));
4694 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4695 Display *dpy = FRAME_MAC_DISPLAY (f);
4696 int x, y, wd, h;
4697 XGCValues xgcv;
4698 struct glyph *cursor_glyph;
4699 GC gc;
4701 /* Get the glyph the cursor is on. If we can't tell because
4702 the current matrix is invalid or such, give up. */
4703 cursor_glyph = get_phys_cursor_glyph (w);
4704 if (cursor_glyph == NULL)
4705 return;
4707 /* Compute frame-relative coordinates for phys cursor. */
4708 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4709 y = get_phys_cursor_geometry (w, row, cursor_glyph, &h);
4710 wd = w->phys_cursor_width;
4712 /* The foreground of cursor_gc is typically the same as the normal
4713 background color, which can cause the cursor box to be invisible. */
4714 xgcv.foreground = f->output_data.mac->cursor_pixel;
4715 if (dpyinfo->scratch_cursor_gc)
4716 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4717 else
4718 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4719 GCForeground, &xgcv);
4720 gc = dpyinfo->scratch_cursor_gc;
4722 /* Set clipping, draw the rectangle, and reset clipping again. */
4723 x_clip_to_row (w, row, TEXT_AREA, gc);
4724 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4725 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4729 /* Draw a bar cursor on window W in glyph row ROW.
4731 Implementation note: One would like to draw a bar cursor with an
4732 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4733 Unfortunately, I didn't find a font yet that has this property set.
4734 --gerd. */
4736 static void
4737 x_draw_bar_cursor (w, row, width, kind)
4738 struct window *w;
4739 struct glyph_row *row;
4740 int width;
4741 enum text_cursor_kinds kind;
4743 struct frame *f = XFRAME (w->frame);
4744 struct glyph *cursor_glyph;
4746 /* If cursor is out of bounds, don't draw garbage. This can happen
4747 in mini-buffer windows when switching between echo area glyphs
4748 and mini-buffer. */
4749 cursor_glyph = get_phys_cursor_glyph (w);
4750 if (cursor_glyph == NULL)
4751 return;
4753 /* If on an image, draw like a normal cursor. That's usually better
4754 visible than drawing a bar, esp. if the image is large so that
4755 the bar might not be in the window. */
4756 if (cursor_glyph->type == IMAGE_GLYPH)
4758 struct glyph_row *row;
4759 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4760 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4762 else
4764 Display *dpy = FRAME_MAC_DISPLAY (f);
4765 Window window = FRAME_MAC_WINDOW (f);
4766 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4767 unsigned long mask = GCForeground | GCBackground;
4768 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4769 XGCValues xgcv;
4771 /* If the glyph's background equals the color we normally draw
4772 the bar cursor in, the bar cursor in its normal color is
4773 invisible. Use the glyph's foreground color instead in this
4774 case, on the assumption that the glyph's colors are chosen so
4775 that the glyph is legible. */
4776 if (face->background == f->output_data.mac->cursor_pixel)
4777 xgcv.background = xgcv.foreground = face->foreground;
4778 else
4779 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4781 if (gc)
4782 XChangeGC (dpy, gc, mask, &xgcv);
4783 else
4785 gc = XCreateGC (dpy, window, mask, &xgcv);
4786 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4789 if (width < 0)
4790 width = FRAME_CURSOR_WIDTH (f);
4791 width = min (cursor_glyph->pixel_width, width);
4793 w->phys_cursor_width = width;
4794 x_clip_to_row (w, row, TEXT_AREA, gc);
4796 if (kind == BAR_CURSOR)
4797 XFillRectangle (dpy, window, gc,
4798 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4799 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4800 width, row->height);
4801 else
4802 XFillRectangle (dpy, window, gc,
4803 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4804 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4805 row->height - width),
4806 cursor_glyph->pixel_width,
4807 width);
4809 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4814 /* RIF: Define cursor CURSOR on frame F. */
4816 static void
4817 mac_define_frame_cursor (f, cursor)
4818 struct frame *f;
4819 Cursor cursor;
4821 SetThemeCursor (cursor);
4825 /* RIF: Clear area on frame F. */
4827 static void
4828 mac_clear_frame_area (f, x, y, width, height)
4829 struct frame *f;
4830 int x, y, width, height;
4832 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4833 x, y, width, height, 0);
4837 /* RIF: Draw cursor on window W. */
4839 static void
4840 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4841 struct window *w;
4842 struct glyph_row *glyph_row;
4843 int x, y;
4844 int cursor_type, cursor_width;
4845 int on_p, active_p;
4847 if (on_p)
4849 w->phys_cursor_type = cursor_type;
4850 w->phys_cursor_on_p = 1;
4852 if (glyph_row->exact_window_width_line_p
4853 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4855 glyph_row->cursor_in_fringe_p = 1;
4856 draw_fringe_bitmap (w, glyph_row, 0);
4858 else
4859 switch (cursor_type)
4861 case HOLLOW_BOX_CURSOR:
4862 x_draw_hollow_cursor (w, glyph_row);
4863 break;
4865 case FILLED_BOX_CURSOR:
4866 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4867 break;
4869 case BAR_CURSOR:
4870 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4871 break;
4873 case HBAR_CURSOR:
4874 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4875 break;
4877 case NO_CURSOR:
4878 w->phys_cursor_width = 0;
4879 break;
4881 default:
4882 abort ();
4888 /* Icons. */
4890 #if 0 /* MAC_TODO: no icon support yet. */
4892 x_bitmap_icon (f, icon)
4893 struct frame *f;
4894 Lisp_Object icon;
4896 HANDLE hicon;
4898 if (FRAME_W32_WINDOW (f) == 0)
4899 return 1;
4901 if (NILP (icon))
4902 hicon = LoadIcon (hinst, EMACS_CLASS);
4903 else if (STRINGP (icon))
4904 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4905 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4906 else if (SYMBOLP (icon))
4908 LPCTSTR name;
4910 if (EQ (icon, intern ("application")))
4911 name = (LPCTSTR) IDI_APPLICATION;
4912 else if (EQ (icon, intern ("hand")))
4913 name = (LPCTSTR) IDI_HAND;
4914 else if (EQ (icon, intern ("question")))
4915 name = (LPCTSTR) IDI_QUESTION;
4916 else if (EQ (icon, intern ("exclamation")))
4917 name = (LPCTSTR) IDI_EXCLAMATION;
4918 else if (EQ (icon, intern ("asterisk")))
4919 name = (LPCTSTR) IDI_ASTERISK;
4920 else if (EQ (icon, intern ("winlogo")))
4921 name = (LPCTSTR) IDI_WINLOGO;
4922 else
4923 return 1;
4925 hicon = LoadIcon (NULL, name);
4927 else
4928 return 1;
4930 if (hicon == NULL)
4931 return 1;
4933 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4934 (LPARAM) hicon);
4936 return 0;
4938 #endif /* MAC_TODO */
4940 /************************************************************************
4941 Handling X errors
4942 ************************************************************************/
4944 /* Display Error Handling functions not used on W32. Listing them here
4945 helps diff stay in step when comparing w32term.c with xterm.c.
4947 x_error_catcher (display, error)
4948 x_catch_errors (dpy)
4949 x_catch_errors_unwind (old_val)
4950 x_check_errors (dpy, format)
4951 x_had_errors_p (dpy)
4952 x_clear_errors (dpy)
4953 x_uncatch_errors (dpy, count)
4954 x_trace_wire ()
4955 x_connection_signal (signalnum)
4956 x_connection_closed (dpy, error_message)
4957 x_error_quitter (display, error)
4958 x_error_handler (display, error)
4959 x_io_error_quitter (display)
4964 /* Changing the font of the frame. */
4966 /* Give frame F the font named FONTNAME as its default font, and
4967 return the full name of that font. FONTNAME may be a wildcard
4968 pattern; in that case, we choose some font that fits the pattern.
4969 The return value shows which font we chose. */
4971 Lisp_Object
4972 x_new_font (f, fontname)
4973 struct frame *f;
4974 register char *fontname;
4976 struct font_info *fontp
4977 = FS_LOAD_FONT (f, 0, fontname, -1);
4979 if (!fontp)
4980 return Qnil;
4982 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4983 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4984 FRAME_FONTSET (f) = -1;
4986 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
4987 FRAME_SPACE_WIDTH (f) = fontp->space_width;
4988 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4990 compute_fringe_widths (f, 1);
4992 /* Compute the scroll bar width in character columns. */
4993 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4995 int wid = FRAME_COLUMN_WIDTH (f);
4996 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4997 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4999 else
5001 int wid = FRAME_COLUMN_WIDTH (f);
5002 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5005 /* Now make the frame display the given font. */
5006 if (FRAME_MAC_WINDOW (f) != 0)
5008 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5009 FRAME_FONT (f));
5010 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5011 FRAME_FONT (f));
5012 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5013 FRAME_FONT (f));
5015 /* Don't change the size of a tip frame; there's no point in
5016 doing it because it's done in Fx_show_tip, and it leads to
5017 problems because the tip frame has no widget. */
5018 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5019 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5022 return build_string (fontp->full_name);
5025 /* Give frame F the fontset named FONTSETNAME as its default font, and
5026 return the full name of that fontset. FONTSETNAME may be a wildcard
5027 pattern; in that case, we choose some fontset that fits the pattern.
5028 The return value shows which fontset we chose. */
5030 Lisp_Object
5031 x_new_fontset (f, fontsetname)
5032 struct frame *f;
5033 char *fontsetname;
5035 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5036 Lisp_Object result;
5038 if (fontset < 0)
5039 return Qnil;
5041 if (FRAME_FONTSET (f) == fontset)
5042 /* This fontset is already set in frame F. There's nothing more
5043 to do. */
5044 return fontset_name (fontset);
5046 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5048 if (!STRINGP (result))
5049 /* Can't load ASCII font. */
5050 return Qnil;
5052 /* Since x_new_font doesn't update any fontset information, do it now. */
5053 FRAME_FONTSET(f) = fontset;
5055 return build_string (fontsetname);
5059 /***********************************************************************
5060 TODO: W32 Input Methods
5061 ***********************************************************************/
5062 /* Listing missing functions from xterm.c helps diff stay in step.
5064 xim_destroy_callback (xim, client_data, call_data)
5065 xim_open_dpy (dpyinfo, resource_name)
5066 struct xim_inst_t
5067 xim_instantiate_callback (display, client_data, call_data)
5068 xim_initialize (dpyinfo, resource_name)
5069 xim_close_dpy (dpyinfo)
5074 void
5075 mac_get_window_bounds (f, inner, outer)
5076 struct frame *f;
5077 Rect *inner, *outer;
5079 #if TARGET_API_MAC_CARBON
5080 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5081 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5082 #else /* not TARGET_API_MAC_CARBON */
5083 RgnHandle region = NewRgn ();
5085 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5086 *inner = (*region)->rgnBBox;
5087 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5088 *outer = (*region)->rgnBBox;
5089 DisposeRgn (region);
5090 #endif /* not TARGET_API_MAC_CARBON */
5094 /* Calculate the absolute position in frame F
5095 from its current recorded position values and gravity. */
5097 void
5098 x_calc_absolute_position (f)
5099 struct frame *f;
5101 int width_diff = 0, height_diff = 0;
5102 int flags = f->size_hint_flags;
5103 Rect inner, outer;
5105 /* We have nothing to do if the current position
5106 is already for the top-left corner. */
5107 if (! ((flags & XNegative) || (flags & YNegative)))
5108 return;
5110 /* Find the offsets of the outside upper-left corner of
5111 the inner window, with respect to the outer window. */
5112 mac_get_window_bounds (f, &inner, &outer);
5114 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5115 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5117 /* Treat negative positions as relative to the leftmost bottommost
5118 position that fits on the screen. */
5119 if (flags & XNegative)
5120 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5121 - width_diff
5122 - FRAME_PIXEL_WIDTH (f)
5123 + f->left_pos);
5125 if (flags & YNegative)
5126 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5127 - height_diff
5128 - FRAME_PIXEL_HEIGHT (f)
5129 + f->top_pos);
5131 /* The left_pos and top_pos
5132 are now relative to the top and left screen edges,
5133 so the flags should correspond. */
5134 f->size_hint_flags &= ~ (XNegative | YNegative);
5137 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5138 to really change the position, and 0 when calling from
5139 x_make_frame_visible (in that case, XOFF and YOFF are the current
5140 position values). It is -1 when calling from x_set_frame_parameters,
5141 which means, do adjust for borders but don't change the gravity. */
5143 void
5144 x_set_offset (f, xoff, yoff, change_gravity)
5145 struct frame *f;
5146 register int xoff, yoff;
5147 int change_gravity;
5149 if (change_gravity > 0)
5151 f->top_pos = yoff;
5152 f->left_pos = xoff;
5153 f->size_hint_flags &= ~ (XNegative | YNegative);
5154 if (xoff < 0)
5155 f->size_hint_flags |= XNegative;
5156 if (yoff < 0)
5157 f->size_hint_flags |= YNegative;
5158 f->win_gravity = NorthWestGravity;
5160 x_calc_absolute_position (f);
5162 BLOCK_INPUT;
5163 x_wm_set_size_hint (f, (long) 0, 0);
5165 #if TARGET_API_MAC_CARBON
5166 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5167 /* If the title bar is completely outside the screen, adjust the
5168 position. */
5169 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5170 kWindowConstrainMoveRegardlessOfFit
5171 | kWindowConstrainAllowPartial, NULL, NULL);
5172 x_real_positions (f, &f->left_pos, &f->top_pos);
5173 #else
5175 Rect inner, outer, screen_rect, dummy;
5176 RgnHandle region = NewRgn ();
5178 mac_get_window_bounds (f, &inner, &outer);
5179 f->x_pixels_diff = inner.left - outer.left;
5180 f->y_pixels_diff = inner.top - outer.top;
5181 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5182 f->top_pos + f->y_pixels_diff, false);
5184 /* If the title bar is completely outside the screen, adjust the
5185 position. The variable `outer' holds the title bar rectangle.
5186 The variable `inner' holds slightly smaller one than `outer',
5187 so that the calculation of overlapping may not become too
5188 strict. */
5189 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5190 outer = (*region)->rgnBBox;
5191 DisposeRgn (region);
5192 inner = outer;
5193 InsetRect (&inner, 8, 8);
5194 screen_rect = qd.screenBits.bounds;
5195 screen_rect.top += GetMBarHeight ();
5197 if (!SectRect (&inner, &screen_rect, &dummy))
5199 if (inner.right <= screen_rect.left)
5200 f->left_pos = screen_rect.left;
5201 else if (inner.left >= screen_rect.right)
5202 f->left_pos = screen_rect.right - (outer.right - outer.left);
5204 if (inner.bottom <= screen_rect.top)
5205 f->top_pos = screen_rect.top;
5206 else if (inner.top >= screen_rect.bottom)
5207 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5209 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5210 f->top_pos + f->y_pixels_diff, false);
5213 #endif
5215 UNBLOCK_INPUT;
5218 /* Call this to change the size of frame F's x-window.
5219 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5220 for this size change and subsequent size changes.
5221 Otherwise we leave the window gravity unchanged. */
5223 void
5224 x_set_window_size (f, change_gravity, cols, rows)
5225 struct frame *f;
5226 int change_gravity;
5227 int cols, rows;
5229 int pixelwidth, pixelheight;
5231 BLOCK_INPUT;
5233 check_frame_size (f, &rows, &cols);
5234 f->scroll_bar_actual_width
5235 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5237 compute_fringe_widths (f, 0);
5239 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5240 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5242 f->win_gravity = NorthWestGravity;
5243 x_wm_set_size_hint (f, (long) 0, 0);
5245 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5246 #if TARGET_API_MAC_CARBON
5247 if (f->output_data.mac->hourglass_control)
5248 MoveControl (f->output_data.mac->hourglass_control,
5249 pixelwidth - HOURGLASS_WIDTH, 0);
5250 #endif
5252 /* Now, strictly speaking, we can't be sure that this is accurate,
5253 but the window manager will get around to dealing with the size
5254 change request eventually, and we'll hear how it went when the
5255 ConfigureNotify event gets here.
5257 We could just not bother storing any of this information here,
5258 and let the ConfigureNotify event set everything up, but that
5259 might be kind of confusing to the Lisp code, since size changes
5260 wouldn't be reported in the frame parameters until some random
5261 point in the future when the ConfigureNotify event arrives.
5263 We pass 1 for DELAY since we can't run Lisp code inside of
5264 a BLOCK_INPUT. */
5265 change_frame_size (f, rows, cols, 0, 1, 0);
5266 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5267 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5269 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5270 receive in the ConfigureNotify event; if we get what we asked
5271 for, then the event won't cause the screen to become garbaged, so
5272 we have to make sure to do it here. */
5273 SET_FRAME_GARBAGED (f);
5275 XFlush (FRAME_X_DISPLAY (f));
5277 /* If cursor was outside the new size, mark it as off. */
5278 mark_window_cursors_off (XWINDOW (f->root_window));
5280 /* Clear out any recollection of where the mouse highlighting was,
5281 since it might be in a place that's outside the new frame size.
5282 Actually checking whether it is outside is a pain in the neck,
5283 so don't try--just let the highlighting be done afresh with new size. */
5284 cancel_mouse_face (f);
5286 UNBLOCK_INPUT;
5289 /* Mouse warping. */
5291 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5293 void
5294 x_set_mouse_position (f, x, y)
5295 struct frame *f;
5296 int x, y;
5298 int pix_x, pix_y;
5300 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5301 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5303 if (pix_x < 0) pix_x = 0;
5304 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5306 if (pix_y < 0) pix_y = 0;
5307 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5309 x_set_mouse_pixel_position (f, pix_x, pix_y);
5312 void
5313 x_set_mouse_pixel_position (f, pix_x, pix_y)
5314 struct frame *f;
5315 int pix_x, pix_y;
5317 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5318 BLOCK_INPUT;
5320 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5321 0, 0, 0, 0, pix_x, pix_y);
5322 UNBLOCK_INPUT;
5323 #endif
5327 /* focus shifting, raising and lowering. */
5329 void
5330 x_focus_on_frame (f)
5331 struct frame *f;
5333 #if 0 /* This proves to be unpleasant. */
5334 x_raise_frame (f);
5335 #endif
5336 #if 0
5337 /* I don't think that the ICCCM allows programs to do things like this
5338 without the interaction of the window manager. Whatever you end up
5339 doing with this code, do it to x_unfocus_frame too. */
5340 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5341 RevertToPointerRoot, CurrentTime);
5342 #endif /* ! 0 */
5345 void
5346 x_unfocus_frame (f)
5347 struct frame *f;
5351 /* Raise frame F. */
5352 void
5353 x_raise_frame (f)
5354 struct frame *f;
5356 if (f->async_visible)
5358 BLOCK_INPUT;
5359 SelectWindow (FRAME_MAC_WINDOW (f));
5360 UNBLOCK_INPUT;
5364 /* Lower frame F. */
5365 void
5366 x_lower_frame (f)
5367 struct frame *f;
5369 if (f->async_visible)
5371 BLOCK_INPUT;
5372 SendBehind (FRAME_MAC_WINDOW (f), nil);
5373 UNBLOCK_INPUT;
5377 static void
5378 XTframe_raise_lower (f, raise_flag)
5379 FRAME_PTR f;
5380 int raise_flag;
5382 if (raise_flag)
5383 x_raise_frame (f);
5384 else
5385 x_lower_frame (f);
5388 /* Change of visibility. */
5390 /* This tries to wait until the frame is really visible.
5391 However, if the window manager asks the user where to position
5392 the frame, this will return before the user finishes doing that.
5393 The frame will not actually be visible at that time,
5394 but it will become visible later when the window manager
5395 finishes with it. */
5397 void
5398 x_make_frame_visible (f)
5399 struct frame *f;
5401 Lisp_Object type;
5402 int original_top, original_left;
5404 BLOCK_INPUT;
5406 if (! FRAME_VISIBLE_P (f))
5408 /* We test FRAME_GARBAGED_P here to make sure we don't
5409 call x_set_offset a second time
5410 if we get to x_make_frame_visible a second time
5411 before the window gets really visible. */
5412 if (! FRAME_ICONIFIED_P (f)
5413 && ! f->output_data.mac->asked_for_visible)
5414 x_set_offset (f, f->left_pos, f->top_pos, 0);
5416 f->output_data.mac->asked_for_visible = 1;
5418 #if TARGET_API_MAC_CARBON
5419 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5421 struct frame *sf = SELECTED_FRAME ();
5422 if (!FRAME_MAC_P (sf))
5423 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5424 kWindowCenterOnMainScreen);
5425 else
5426 RepositionWindow (FRAME_MAC_WINDOW (f),
5427 FRAME_MAC_WINDOW (sf),
5428 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5429 kWindowCascadeStartAtParentWindowScreen
5430 #else
5431 kWindowCascadeOnParentWindowScreen
5432 #endif
5434 x_real_positions (f, &f->left_pos, &f->top_pos);
5436 #endif
5437 ShowWindow (FRAME_MAC_WINDOW (f));
5440 XFlush (FRAME_MAC_DISPLAY (f));
5442 /* Synchronize to ensure Emacs knows the frame is visible
5443 before we do anything else. We do this loop with input not blocked
5444 so that incoming events are handled. */
5446 Lisp_Object frame;
5447 int count;
5449 /* This must come after we set COUNT. */
5450 UNBLOCK_INPUT;
5452 XSETFRAME (frame, f);
5454 /* Wait until the frame is visible. Process X events until a
5455 MapNotify event has been seen, or until we think we won't get a
5456 MapNotify at all.. */
5457 for (count = input_signal_count + 10;
5458 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5460 /* Force processing of queued events. */
5461 x_sync (f);
5463 /* Machines that do polling rather than SIGIO have been
5464 observed to go into a busy-wait here. So we'll fake an
5465 alarm signal to let the handler know that there's something
5466 to be read. We used to raise a real alarm, but it seems
5467 that the handler isn't always enabled here. This is
5468 probably a bug. */
5469 if (input_polling_used ())
5471 /* It could be confusing if a real alarm arrives while
5472 processing the fake one. Turn it off and let the
5473 handler reset it. */
5474 extern void poll_for_input_1 P_ ((void));
5475 int old_poll_suppress_count = poll_suppress_count;
5476 poll_suppress_count = 1;
5477 poll_for_input_1 ();
5478 poll_suppress_count = old_poll_suppress_count;
5481 /* See if a MapNotify event has been processed. */
5482 FRAME_SAMPLE_VISIBILITY (f);
5487 /* Change from mapped state to withdrawn state. */
5489 /* Make the frame visible (mapped and not iconified). */
5491 void
5492 x_make_frame_invisible (f)
5493 struct frame *f;
5495 /* Don't keep the highlight on an invisible frame. */
5496 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5497 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5499 BLOCK_INPUT;
5501 HideWindow (FRAME_MAC_WINDOW (f));
5503 /* We can't distinguish this from iconification
5504 just by the event that we get from the server.
5505 So we can't win using the usual strategy of letting
5506 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5507 and synchronize with the server to make sure we agree. */
5508 f->visible = 0;
5509 FRAME_ICONIFIED_P (f) = 0;
5510 f->async_visible = 0;
5511 f->async_iconified = 0;
5513 UNBLOCK_INPUT;
5516 /* Change window state from mapped to iconified. */
5518 void
5519 x_iconify_frame (f)
5520 struct frame *f;
5522 /* Don't keep the highlight on an invisible frame. */
5523 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5524 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5526 #if 0
5527 /* Review: Since window is still visible in dock, still allow updates? */
5528 if (f->async_iconified)
5529 return;
5530 #endif
5532 BLOCK_INPUT;
5534 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5536 UNBLOCK_INPUT;
5540 /* Free X resources of frame F. */
5542 void
5543 x_free_frame_resources (f)
5544 struct frame *f;
5546 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5547 WindowPtr wp = FRAME_MAC_WINDOW (f);
5549 BLOCK_INPUT;
5551 if (wp != tip_window)
5552 remove_window_handler (wp);
5554 DisposeWindow (wp);
5555 if (wp == tip_window)
5556 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5557 closed' event. So we reset tip_window here. */
5558 tip_window = NULL;
5560 free_frame_menubar (f);
5562 if (FRAME_FACE_CACHE (f))
5563 free_frame_faces (f);
5565 x_free_gcs (f);
5567 if (FRAME_SIZE_HINTS (f))
5568 xfree (FRAME_SIZE_HINTS (f));
5570 xfree (f->output_data.mac);
5571 f->output_data.mac = NULL;
5573 if (f == dpyinfo->x_focus_frame)
5574 dpyinfo->x_focus_frame = 0;
5575 if (f == dpyinfo->x_focus_event_frame)
5576 dpyinfo->x_focus_event_frame = 0;
5577 if (f == dpyinfo->x_highlight_frame)
5578 dpyinfo->x_highlight_frame = 0;
5580 if (f == dpyinfo->mouse_face_mouse_frame)
5582 dpyinfo->mouse_face_beg_row
5583 = dpyinfo->mouse_face_beg_col = -1;
5584 dpyinfo->mouse_face_end_row
5585 = dpyinfo->mouse_face_end_col = -1;
5586 dpyinfo->mouse_face_window = Qnil;
5587 dpyinfo->mouse_face_deferred_gc = 0;
5588 dpyinfo->mouse_face_mouse_frame = 0;
5591 UNBLOCK_INPUT;
5595 /* Destroy the X window of frame F. */
5597 void
5598 x_destroy_window (f)
5599 struct frame *f;
5601 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5603 x_free_frame_resources (f);
5605 dpyinfo->reference_count--;
5609 /* Setting window manager hints. */
5611 /* Set the normal size hints for the window manager, for frame F.
5612 FLAGS is the flags word to use--or 0 meaning preserve the flags
5613 that the window now has.
5614 If USER_POSITION is nonzero, we set the USPosition
5615 flag (this is useful when FLAGS is 0). */
5616 void
5617 x_wm_set_size_hint (f, flags, user_position)
5618 struct frame *f;
5619 long flags;
5620 int user_position;
5622 int base_width, base_height, width_inc, height_inc;
5623 int min_rows = 0, min_cols = 0;
5624 XSizeHints *size_hints;
5626 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5627 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5628 width_inc = FRAME_COLUMN_WIDTH (f);
5629 height_inc = FRAME_LINE_HEIGHT (f);
5631 check_frame_size (f, &min_rows, &min_cols);
5633 size_hints = FRAME_SIZE_HINTS (f);
5634 if (size_hints == NULL)
5636 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
5637 bzero (size_hints, sizeof (XSizeHints));
5640 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
5641 size_hints->width_inc = width_inc;
5642 size_hints->height_inc = height_inc;
5643 size_hints->min_width = base_width + min_cols * width_inc;
5644 size_hints->min_height = base_height + min_rows * height_inc;
5645 size_hints->base_width = base_width;
5646 size_hints->base_height = base_height;
5648 if (flags)
5649 size_hints->flags = flags;
5650 else if (user_position)
5652 size_hints->flags &= ~ PPosition;
5653 size_hints->flags |= USPosition;
5657 #if 0 /* MAC_TODO: hide application instead of iconify? */
5658 /* Used for IconicState or NormalState */
5660 void
5661 x_wm_set_window_state (f, state)
5662 struct frame *f;
5663 int state;
5665 #ifdef USE_X_TOOLKIT
5666 Arg al[1];
5668 XtSetArg (al[0], XtNinitialState, state);
5669 XtSetValues (f->output_data.x->widget, al, 1);
5670 #else /* not USE_X_TOOLKIT */
5671 Window window = FRAME_X_WINDOW (f);
5673 f->output_data.x->wm_hints.flags |= StateHint;
5674 f->output_data.x->wm_hints.initial_state = state;
5676 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5677 #endif /* not USE_X_TOOLKIT */
5680 void
5681 x_wm_set_icon_pixmap (f, pixmap_id)
5682 struct frame *f;
5683 int pixmap_id;
5685 Pixmap icon_pixmap;
5687 #ifndef USE_X_TOOLKIT
5688 Window window = FRAME_X_WINDOW (f);
5689 #endif
5691 if (pixmap_id > 0)
5693 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5694 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5696 else
5698 /* It seems there is no way to turn off use of an icon pixmap.
5699 The following line does it, only if no icon has yet been created,
5700 for some window managers. But with mwm it crashes.
5701 Some people say it should clear the IconPixmapHint bit in this case,
5702 but that doesn't work, and the X consortium said it isn't the
5703 right thing at all. Since there is no way to win,
5704 best to explicitly give up. */
5705 #if 0
5706 f->output_data.x->wm_hints.icon_pixmap = None;
5707 #else
5708 return;
5709 #endif
5712 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5715 Arg al[1];
5716 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5717 XtSetValues (f->output_data.x->widget, al, 1);
5720 #else /* not USE_X_TOOLKIT */
5722 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5723 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5725 #endif /* not USE_X_TOOLKIT */
5728 #endif /* MAC_TODO */
5730 void
5731 x_wm_set_icon_position (f, icon_x, icon_y)
5732 struct frame *f;
5733 int icon_x, icon_y;
5735 #if 0 /* MAC_TODO: no icons on Mac */
5736 #ifdef USE_X_TOOLKIT
5737 Window window = XtWindow (f->output_data.x->widget);
5738 #else
5739 Window window = FRAME_X_WINDOW (f);
5740 #endif
5742 f->output_data.x->wm_hints.flags |= IconPositionHint;
5743 f->output_data.x->wm_hints.icon_x = icon_x;
5744 f->output_data.x->wm_hints.icon_y = icon_y;
5746 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5747 #endif /* MAC_TODO */
5751 /***********************************************************************
5752 Fonts
5753 ***********************************************************************/
5755 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5757 struct font_info *
5758 x_get_font_info (f, font_idx)
5759 FRAME_PTR f;
5760 int font_idx;
5762 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5765 /* the global font name table */
5766 char **font_name_table = NULL;
5767 int font_name_table_size = 0;
5768 int font_name_count = 0;
5770 #if 0
5771 /* compare two strings ignoring case */
5772 static int
5773 stricmp (const char *s, const char *t)
5775 for ( ; tolower (*s) == tolower (*t); s++, t++)
5776 if (*s == '\0')
5777 return 0;
5778 return tolower (*s) - tolower (*t);
5781 /* compare two strings ignoring case and handling wildcard */
5782 static int
5783 wildstrieq (char *s1, char *s2)
5785 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5786 return true;
5788 return stricmp (s1, s2) == 0;
5791 /* Assume parameter 1 is fully qualified, no wildcards. */
5792 static int
5793 mac_font_pattern_match (fontname, pattern)
5794 char * fontname;
5795 char * pattern;
5797 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5798 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5799 char *ptr;
5801 /* Copy fontname so we can modify it during comparison. */
5802 strcpy (font_name_copy, fontname);
5804 ptr = regex;
5805 *ptr++ = '^';
5807 /* Turn pattern into a regexp and do a regexp match. */
5808 for (; *pattern; pattern++)
5810 if (*pattern == '?')
5811 *ptr++ = '.';
5812 else if (*pattern == '*')
5814 *ptr++ = '.';
5815 *ptr++ = '*';
5817 else
5818 *ptr++ = *pattern;
5820 *ptr = '$';
5821 *(ptr + 1) = '\0';
5823 return (fast_c_string_match_ignore_case (build_string (regex),
5824 font_name_copy) >= 0);
5827 /* Two font specs are considered to match if their foundry, family,
5828 weight, slant, and charset match. */
5829 static int
5830 mac_font_match (char *mf, char *xf)
5832 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5833 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5835 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5836 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5837 return mac_font_pattern_match (mf, xf);
5839 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5840 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5841 return mac_font_pattern_match (mf, xf);
5843 return (wildstrieq (m_foundry, x_foundry)
5844 && wildstrieq (m_family, x_family)
5845 && wildstrieq (m_weight, x_weight)
5846 && wildstrieq (m_slant, x_slant)
5847 && wildstrieq (m_charset, x_charset))
5848 || mac_font_pattern_match (mf, xf);
5850 #endif
5852 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5854 static void
5855 decode_mac_font_name (name, size, scriptcode)
5856 char *name;
5857 int size;
5858 #if TARGET_API_MAC_CARBON
5859 int scriptcode;
5860 #else
5861 short scriptcode;
5862 #endif
5864 Lisp_Object coding_system;
5865 struct coding_system coding;
5866 char *buf;
5868 switch (scriptcode)
5870 case smTradChinese:
5871 coding_system = Qbig5;
5872 break;
5873 case smSimpChinese:
5874 coding_system = Qcn_gb;
5875 break;
5876 case smJapanese:
5877 coding_system = Qsjis;
5878 break;
5879 case smKorean:
5880 coding_system = Qeuc_kr;
5881 break;
5882 default:
5883 return;
5886 setup_coding_system (coding_system, &coding);
5887 coding.src_multibyte = 0;
5888 coding.dst_multibyte = 1;
5889 coding.mode |= CODING_MODE_LAST_BLOCK;
5890 coding.composing = COMPOSITION_DISABLED;
5891 buf = (char *) alloca (size);
5893 decode_coding (&coding, name, buf, strlen (name), size - 1);
5894 bcopy (buf, name, coding.produced);
5895 name[coding.produced] = '\0';
5899 static char *
5900 mac_to_x_fontname (name, size, style, scriptcode)
5901 char *name;
5902 int size;
5903 Style style;
5904 #if TARGET_API_MAC_CARBON
5905 int scriptcode;
5906 #else
5907 short scriptcode;
5908 #endif
5910 char foundry[32], family[32], cs[32];
5911 char xf[256], *result, *p;
5913 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5915 strcpy(foundry, "Apple");
5916 strcpy(family, name);
5918 switch (scriptcode)
5920 case smTradChinese: /* == kTextEncodingMacChineseTrad */
5921 strcpy(cs, "big5-0");
5922 break;
5923 case smSimpChinese: /* == kTextEncodingMacChineseSimp */
5924 strcpy(cs, "gb2312.1980-0");
5925 break;
5926 case smJapanese: /* == kTextEncodingMacJapanese */
5927 strcpy(cs, "jisx0208.1983-sjis");
5928 break;
5929 case -smJapanese:
5930 /* Each Apple Japanese font is entered into the font table
5931 twice: once as a jisx0208.1983-sjis font and once as a
5932 jisx0201.1976-0 font. The latter can be used to display
5933 the ascii charset and katakana-jisx0201 charset. A
5934 negative script code signals that the name of this latter
5935 font is being built. */
5936 strcpy(cs, "jisx0201.1976-0");
5937 break;
5938 case smKorean: /* == kTextEncodingMacKorean */
5939 strcpy(cs, "ksc5601.1989-0");
5940 break;
5941 #if TARGET_API_MAC_CARBON
5942 case kTextEncodingMacCyrillic:
5943 strcpy(cs, "mac-cyrillic");
5944 break;
5945 case kTextEncodingMacCentralEurRoman:
5946 strcpy(cs, "mac-centraleurroman");
5947 break;
5948 case kTextEncodingMacSymbol:
5949 case kTextEncodingMacDingbats:
5950 strcpy(cs, "adobe-fontspecific");
5951 break;
5952 #endif
5953 default:
5954 strcpy(cs, "mac-roman");
5955 break;
5959 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5960 foundry, family, style & bold ? "bold" : "medium",
5961 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5963 result = (char *) xmalloc (strlen (xf) + 1);
5964 strcpy (result, xf);
5965 for (p = result; *p; p++)
5966 *p = tolower(*p);
5967 return result;
5971 /* Convert an X font spec to the corresponding mac font name, which
5972 can then be passed to GetFNum after conversion to a Pascal string.
5973 For ordinary Mac fonts, this should just be their names, like
5974 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5975 collection contain their charset designation in their names, like
5976 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5977 names are handled accordingly. */
5978 static void
5979 x_font_name_to_mac_font_name (char *xf, char *mf)
5981 char foundry[32], family[32], weight[20], slant[2], cs[32];
5982 Lisp_Object coding_system = Qnil;
5983 struct coding_system coding;
5985 strcpy (mf, "");
5987 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5988 foundry, family, weight, slant, cs) != 5 &&
5989 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5990 foundry, family, weight, slant, cs) != 5)
5991 return;
5993 if (strcmp (cs, "big5-0") == 0)
5994 coding_system = Qbig5;
5995 else if (strcmp (cs, "gb2312.1980-0") == 0)
5996 coding_system = Qcn_gb;
5997 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
5998 || strcmp (cs, "jisx0201.1976-0") == 0)
5999 coding_system = Qsjis;
6000 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6001 coding_system = Qeuc_kr;
6002 else if (strcmp (cs, "mac-roman") == 0
6003 || strcmp (cs, "mac-cyrillic") == 0
6004 || strcmp (cs, "mac-centraleurroman") == 0
6005 || strcmp (cs, "adobe-fontspecific") == 0)
6006 strcpy (mf, family);
6007 else
6008 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6010 if (!NILP (coding_system))
6012 setup_coding_system (coding_system, &coding);
6013 coding.src_multibyte = 1;
6014 coding.dst_multibyte = 1;
6015 coding.mode |= CODING_MODE_LAST_BLOCK;
6016 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6017 mf[coding.produced] = '\0';
6022 static void
6023 add_font_name_table_entry (char *font_name)
6025 if (font_name_table_size == 0)
6027 font_name_table_size = 16;
6028 font_name_table = (char **)
6029 xmalloc (font_name_table_size * sizeof (char *));
6031 else if (font_name_count + 1 >= font_name_table_size)
6033 font_name_table_size += 16;
6034 font_name_table = (char **)
6035 xrealloc (font_name_table,
6036 font_name_table_size * sizeof (char *));
6039 font_name_table[font_name_count++] = font_name;
6042 /* Sets up the table font_name_table to contain the list of all fonts
6043 in the system the first time the table is used so that the Resource
6044 Manager need not be accessed every time this information is
6045 needed. */
6047 static void
6048 init_font_name_table ()
6050 #if TARGET_API_MAC_CARBON
6051 SInt32 sv;
6053 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6055 FMFontFamilyIterator ffi;
6056 FMFontFamilyInstanceIterator ffii;
6057 FMFontFamily ff;
6059 /* Create a dummy instance iterator here to avoid creating and
6060 destroying it in the loop. */
6061 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6062 return;
6063 /* Create an iterator to enumerate the font families. */
6064 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6065 != noErr)
6067 FMDisposeFontFamilyInstanceIterator (&ffii);
6068 return;
6071 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6073 Str255 name;
6074 FMFont font;
6075 FMFontStyle style;
6076 FMFontSize size;
6077 TextEncoding encoding;
6078 TextEncodingBase sc;
6080 if (FMGetFontFamilyName (ff, name) != noErr)
6081 break;
6082 p2cstr (name);
6083 if (*name == '.')
6084 continue;
6086 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6087 break;
6088 sc = GetTextEncodingBase (encoding);
6089 decode_mac_font_name (name, sizeof (name), sc);
6091 /* Point the instance iterator at the current font family. */
6092 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6093 break;
6095 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6096 == noErr)
6098 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6099 contained in Apple Japanese (SJIS) font. */
6100 again:
6101 if (size == 0)
6103 add_font_name_table_entry (mac_to_x_fontname (name, size,
6104 style, sc));
6105 add_font_name_table_entry (mac_to_x_fontname (name, size,
6106 italic, sc));
6107 add_font_name_table_entry (mac_to_x_fontname (name, size,
6108 bold, sc));
6109 add_font_name_table_entry (mac_to_x_fontname (name, size,
6110 italic | bold,
6111 sc));
6113 else
6114 add_font_name_table_entry (mac_to_x_fontname (name, size,
6115 style, sc));
6116 if (sc == smJapanese)
6118 sc = -smJapanese;
6119 goto again;
6121 else if (sc == -smJapanese)
6122 sc = smJapanese;
6126 /* Dispose of the iterators. */
6127 FMDisposeFontFamilyIterator (&ffi);
6128 FMDisposeFontFamilyInstanceIterator (&ffii);
6130 else
6132 #endif /* TARGET_API_MAC_CARBON */
6133 GrafPtr port;
6134 SInt16 fontnum, old_fontnum;
6135 int num_mac_fonts = CountResources('FOND');
6136 int i, j;
6137 Handle font_handle, font_handle_2;
6138 short id, scriptcode;
6139 ResType type;
6140 Str32 name;
6141 struct FontAssoc *fat;
6142 struct AsscEntry *assc_entry;
6144 GetPort (&port); /* save the current font number used */
6145 #if TARGET_API_MAC_CARBON
6146 old_fontnum = GetPortTextFont (port);
6147 #else
6148 old_fontnum = port->txFont;
6149 #endif
6151 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6153 font_handle = GetIndResource ('FOND', i);
6154 if (!font_handle)
6155 continue;
6157 GetResInfo (font_handle, &id, &type, name);
6158 GetFNum (name, &fontnum);
6159 p2cstr (name);
6160 if (fontnum == 0)
6161 continue;
6163 TextFont (fontnum);
6164 scriptcode = FontToScript (fontnum);
6165 decode_mac_font_name (name, sizeof (name), scriptcode);
6168 HLock (font_handle);
6170 if (GetResourceSizeOnDisk (font_handle)
6171 >= sizeof (struct FamRec))
6173 fat = (struct FontAssoc *) (*font_handle
6174 + sizeof (struct FamRec));
6175 assc_entry
6176 = (struct AsscEntry *) (*font_handle
6177 + sizeof (struct FamRec)
6178 + sizeof (struct FontAssoc));
6180 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6182 if (font_name_table_size == 0)
6184 font_name_table_size = 16;
6185 font_name_table = (char **)
6186 xmalloc (font_name_table_size * sizeof (char *));
6188 else if (font_name_count >= font_name_table_size)
6190 font_name_table_size += 16;
6191 font_name_table = (char **)
6192 xrealloc (font_name_table,
6193 font_name_table_size * sizeof (char *));
6195 font_name_table[font_name_count++]
6196 = mac_to_x_fontname (name,
6197 assc_entry->fontSize,
6198 assc_entry->fontStyle,
6199 scriptcode);
6200 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6201 parts are contained in Apple Japanese (SJIS)
6202 font. */
6203 if (smJapanese == scriptcode)
6205 font_name_table[font_name_count++]
6206 = mac_to_x_fontname (name,
6207 assc_entry->fontSize,
6208 assc_entry->fontStyle,
6209 -smJapanese);
6214 HUnlock (font_handle);
6215 font_handle_2 = GetNextFOND (font_handle);
6216 ReleaseResource (font_handle);
6217 font_handle = font_handle_2;
6219 while (ResError () == noErr && font_handle);
6222 TextFont (old_fontnum);
6223 #if TARGET_API_MAC_CARBON
6225 #endif /* TARGET_API_MAC_CARBON */
6229 void
6230 mac_clear_font_name_table ()
6232 int i;
6234 for (i = 0; i < font_name_count; i++)
6235 xfree (font_name_table[i]);
6236 xfree (font_name_table);
6237 font_name_table = NULL;
6238 font_name_table_size = font_name_count = 0;
6242 enum xlfd_scalable_field_index
6244 XLFD_SCL_PIXEL_SIZE,
6245 XLFD_SCL_POINT_SIZE,
6246 XLFD_SCL_AVGWIDTH,
6247 XLFD_SCL_LAST
6250 static int xlfd_scalable_fields[] =
6252 6, /* PIXEL_SIZE */
6253 7, /* POINT_SIZE */
6254 11, /* AVGWIDTH */
6258 static Lisp_Object
6259 mac_c_string_match (regexp, string, nonspecial, exact)
6260 Lisp_Object regexp;
6261 const char *string, *nonspecial;
6262 int exact;
6264 if (exact)
6266 if (strcmp (string, nonspecial) == 0)
6267 return build_string (string);
6269 else if (strstr (string, nonspecial))
6271 Lisp_Object str = build_string (string);
6273 if (fast_string_match (regexp, str) >= 0)
6274 return str;
6277 return Qnil;
6280 static Lisp_Object
6281 mac_do_list_fonts (pattern, maxnames)
6282 char *pattern;
6283 int maxnames;
6285 int i, n_fonts = 0;
6286 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6287 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6288 char scaled[256];
6289 char *ptr;
6290 int scl_val[XLFD_SCL_LAST], *field, *val;
6291 char *longest_start, *cur_start, *nonspecial;
6292 int longest_len, exact;
6294 if (font_name_table == NULL) /* Initialize when first used. */
6295 init_font_name_table ();
6297 for (i = 0; i < XLFD_SCL_LAST; i++)
6298 scl_val[i] = -1;
6300 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6301 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6302 fonts are scaled according to the specified size. */
6303 ptr = pattern;
6304 i = 0;
6305 field = xlfd_scalable_fields;
6306 val = scl_val;
6307 if (*ptr == '-')
6310 ptr++;
6311 if (i == *field)
6313 if ('1' <= *ptr && *ptr <= '9')
6315 *val = *ptr++ - '0';
6316 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6317 *val = *val * 10 + *ptr++ - '0';
6318 if (*ptr != '-')
6319 *val = -1;
6321 field++;
6322 val++;
6324 ptr = strchr (ptr, '-');
6325 i++;
6327 while (ptr && i < 14);
6329 if (i == 14 && ptr == NULL)
6331 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6333 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6334 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6336 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6338 scl_val[XLFD_SCL_POINT_SIZE] =
6339 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6341 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6343 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6344 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6347 else
6348 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6350 ptr = regex;
6351 *ptr++ = '^';
6353 longest_start = cur_start = ptr;
6354 longest_len = 0;
6355 exact = 1;
6357 /* Turn pattern into a regexp and do a regexp match. Also find the
6358 longest substring containing no special characters. */
6359 for (; *pattern; pattern++)
6361 if (*pattern == '?' || *pattern == '*')
6363 if (ptr - cur_start > longest_len)
6365 longest_start = cur_start;
6366 longest_len = ptr - cur_start;
6368 exact = 0;
6370 if (*pattern == '?')
6371 *ptr++ = '.';
6372 else /* if (*pattern == '*') */
6374 *ptr++ = '.';
6375 *ptr++ = '*';
6377 cur_start = ptr;
6379 else
6380 *ptr++ = tolower (*pattern);
6383 if (ptr - cur_start > longest_len)
6385 longest_start = cur_start;
6386 longest_len = ptr - cur_start;
6389 *ptr = '$';
6390 *(ptr + 1) = '\0';
6392 nonspecial = xmalloc (longest_len + 1);
6393 strncpy (nonspecial, longest_start, longest_len);
6394 nonspecial[longest_len] = '\0';
6396 pattern_regex = build_string (regex);
6398 for (i = 0; i < font_name_count; i++)
6400 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6401 nonspecial, exact);
6402 if (!NILP (fontname))
6404 font_list = Fcons (fontname, font_list);
6405 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6406 break;
6408 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6409 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6411 int former_len = ptr - font_name_table[i];
6413 memcpy (scaled, font_name_table[i], former_len);
6414 sprintf (scaled + former_len,
6415 "-%d-%d-75-75-m-%d-%s",
6416 scl_val[XLFD_SCL_PIXEL_SIZE],
6417 scl_val[XLFD_SCL_POINT_SIZE],
6418 scl_val[XLFD_SCL_AVGWIDTH],
6419 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6420 fontname = mac_c_string_match (pattern_regex, scaled,
6421 nonspecial, exact);
6422 if (!NILP (fontname))
6424 font_list = Fcons (fontname, font_list);
6425 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6426 break;
6431 xfree (nonspecial);
6433 return font_list;
6436 /* Return a list of at most MAXNAMES font specs matching the one in
6437 PATTERN. Cache matching fonts for patterns in
6438 dpyinfo->name_list_element to avoid looking them up again by
6439 calling mac_font_pattern_match (slow). Return as many matching
6440 fonts as possible if MAXNAMES = -1. */
6442 Lisp_Object
6443 x_list_fonts (struct frame *f,
6444 Lisp_Object pattern,
6445 int size,
6446 int maxnames)
6448 Lisp_Object newlist = Qnil, tem, key;
6449 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6451 if (dpyinfo)
6453 tem = XCAR (XCDR (dpyinfo->name_list_element));
6454 key = Fcons (pattern, make_number (maxnames));
6456 newlist = Fassoc (key, tem);
6457 if (!NILP (newlist))
6459 newlist = Fcdr_safe (newlist);
6460 goto label_cached;
6464 BLOCK_INPUT;
6465 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6466 UNBLOCK_INPUT;
6468 /* MAC_TODO: add code for matching outline fonts here */
6470 if (dpyinfo)
6472 XSETCAR (XCDR (dpyinfo->name_list_element),
6473 Fcons (Fcons (key, newlist),
6474 XCAR (XCDR (dpyinfo->name_list_element))));
6476 label_cached:
6478 return newlist;
6482 #if GLYPH_DEBUG
6484 /* Check that FONT is valid on frame F. It is if it can be found in F's
6485 font table. */
6487 static void
6488 x_check_font (f, font)
6489 struct frame *f;
6490 XFontStruct *font;
6492 int i;
6493 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6495 xassert (font != NULL);
6497 for (i = 0; i < dpyinfo->n_fonts; i++)
6498 if (dpyinfo->font_table[i].name
6499 && font == dpyinfo->font_table[i].font)
6500 break;
6502 xassert (i < dpyinfo->n_fonts);
6505 #endif /* GLYPH_DEBUG != 0 */
6507 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6508 Note: There are (broken) X fonts out there with invalid XFontStruct
6509 min_bounds contents. For example, handa@etl.go.jp reports that
6510 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6511 have font->min_bounds.width == 0. */
6513 static INLINE void
6514 x_font_min_bounds (font, w, h)
6515 MacFontStruct *font;
6516 int *w, *h;
6518 *h = FONT_HEIGHT (font);
6519 *w = font->min_bounds.width;
6523 /* Compute the smallest character width and smallest font height over
6524 all fonts available on frame F. Set the members smallest_char_width
6525 and smallest_font_height in F's x_display_info structure to
6526 the values computed. Value is non-zero if smallest_font_height or
6527 smallest_char_width become smaller than they were before. */
6530 x_compute_min_glyph_bounds (f)
6531 struct frame *f;
6533 int i;
6534 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6535 MacFontStruct *font;
6536 int old_width = dpyinfo->smallest_char_width;
6537 int old_height = dpyinfo->smallest_font_height;
6539 dpyinfo->smallest_font_height = 100000;
6540 dpyinfo->smallest_char_width = 100000;
6542 for (i = 0; i < dpyinfo->n_fonts; ++i)
6543 if (dpyinfo->font_table[i].name)
6545 struct font_info *fontp = dpyinfo->font_table + i;
6546 int w, h;
6548 font = (MacFontStruct *) fontp->font;
6549 xassert (font != (MacFontStruct *) ~0);
6550 x_font_min_bounds (font, &w, &h);
6552 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6553 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6556 xassert (dpyinfo->smallest_char_width > 0
6557 && dpyinfo->smallest_font_height > 0);
6559 return (dpyinfo->n_fonts == 1
6560 || dpyinfo->smallest_char_width < old_width
6561 || dpyinfo->smallest_font_height < old_height);
6565 /* Determine whether given string is a fully-specified XLFD: all 14
6566 fields are present, none is '*'. */
6568 static int
6569 is_fully_specified_xlfd (char *p)
6571 int i;
6572 char *q;
6574 if (*p != '-')
6575 return 0;
6577 for (i = 0; i < 13; i++)
6579 q = strchr (p + 1, '-');
6580 if (q == NULL)
6581 return 0;
6582 if (q - p == 2 && *(p + 1) == '*')
6583 return 0;
6584 p = q;
6587 if (strchr (p + 1, '-') != NULL)
6588 return 0;
6590 if (*(p + 1) == '*' && *(p + 2) == '\0')
6591 return 0;
6593 return 1;
6597 const int kDefaultFontSize = 9;
6600 /* XLoadQueryFont creates and returns an internal representation for a
6601 font in a MacFontStruct struct. There is really no concept
6602 corresponding to "loading" a font on the Mac. But we check its
6603 existence and find the font number and all other information for it
6604 and store them in the returned MacFontStruct. */
6606 static MacFontStruct *
6607 XLoadQueryFont (Display *dpy, char *fontname)
6609 int i, size, is_two_byte_font, char_width;
6610 char *name;
6611 GrafPtr port;
6612 SInt16 old_fontnum, old_fontsize;
6613 Style old_fontface;
6614 Str32 mfontname;
6615 SInt16 fontnum;
6616 Style fontface = normal;
6617 MacFontStruct *font;
6618 FontInfo the_fontinfo;
6619 char s_weight[7], c_slant;
6621 if (is_fully_specified_xlfd (fontname))
6622 name = fontname;
6623 else
6625 Lisp_Object matched_fonts;
6627 matched_fonts = mac_do_list_fonts (fontname, 1);
6628 if (NILP (matched_fonts))
6629 return NULL;
6630 name = SDATA (XCAR (matched_fonts));
6633 GetPort (&port); /* save the current font number used */
6634 #if TARGET_API_MAC_CARBON
6635 old_fontnum = GetPortTextFont (port);
6636 old_fontsize = GetPortTextSize (port);
6637 old_fontface = GetPortTextFace (port);
6638 #else
6639 old_fontnum = port->txFont;
6640 old_fontsize = port->txSize;
6641 old_fontface = port->txFace;
6642 #endif
6644 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6645 size = kDefaultFontSize;
6647 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6648 if (strcmp (s_weight, "bold") == 0)
6649 fontface |= bold;
6651 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6652 if (c_slant == 'i')
6653 fontface |= italic;
6655 x_font_name_to_mac_font_name (name, mfontname);
6656 c2pstr (mfontname);
6657 GetFNum (mfontname, &fontnum);
6658 if (fontnum == 0)
6659 return NULL;
6661 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6663 font->fontname = (char *) xmalloc (strlen (name) + 1);
6664 bcopy (name, font->fontname, strlen (name) + 1);
6666 font->mac_fontnum = fontnum;
6667 font->mac_fontsize = size;
6668 font->mac_fontface = fontface;
6669 font->mac_scriptcode = FontToScript (fontnum);
6671 /* Apple Japanese (SJIS) font is listed as both
6672 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6673 (Roman script) in init_font_name_table (). The latter should be
6674 treated as a one-byte font. */
6676 char cs[32];
6678 if (sscanf (name,
6679 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6680 cs) == 1
6681 && 0 == strcmp (cs, "jisx0201.1976-0"))
6682 font->mac_scriptcode = smRoman;
6685 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6686 font->mac_scriptcode == smTradChinese ||
6687 font->mac_scriptcode == smSimpChinese ||
6688 font->mac_scriptcode == smKorean;
6690 TextFont (fontnum);
6691 TextSize (size);
6692 TextFace (fontface);
6694 GetFontInfo (&the_fontinfo);
6696 font->ascent = the_fontinfo.ascent;
6697 font->descent = the_fontinfo.descent;
6699 font->min_byte1 = 0;
6700 if (is_two_byte_font)
6701 font->max_byte1 = 1;
6702 else
6703 font->max_byte1 = 0;
6704 font->min_char_or_byte2 = 0x20;
6705 font->max_char_or_byte2 = 0xff;
6707 if (is_two_byte_font)
6709 /* Use the width of an "ideographic space" of that font because
6710 the_fontinfo.widMax returns the wrong width for some fonts. */
6711 switch (font->mac_scriptcode)
6713 case smJapanese:
6714 char_width = StringWidth("\p\x81\x40");
6715 break;
6716 case smTradChinese:
6717 char_width = StringWidth("\p\xa1\x40");
6718 break;
6719 case smSimpChinese:
6720 char_width = StringWidth("\p\xa1\xa1");
6721 break;
6722 case smKorean:
6723 char_width = StringWidth("\p\xa1\xa1");
6724 break;
6727 else
6728 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6729 returns 15 for 12-point Monaco! */
6730 char_width = CharWidth ('m');
6732 if (is_two_byte_font)
6734 font->per_char = NULL;
6736 if (fontface & italic)
6737 font->max_bounds.rbearing = char_width + 1;
6738 else
6739 font->max_bounds.rbearing = char_width;
6740 font->max_bounds.lbearing = 0;
6741 font->max_bounds.width = char_width;
6742 font->max_bounds.ascent = the_fontinfo.ascent;
6743 font->max_bounds.descent = the_fontinfo.descent;
6745 font->min_bounds = font->max_bounds;
6747 else
6749 font->per_char = (XCharStruct *)
6750 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6752 int c, min_width, max_width;
6753 Rect char_bounds, min_bounds, max_bounds;
6754 char ch;
6756 min_width = max_width = char_width;
6757 SetRect (&min_bounds, -32767, -32767, 32767, 32767);
6758 SetRect (&max_bounds, 0, 0, 0, 0);
6759 for (c = 0x20; c <= 0xff; c++)
6761 ch = c;
6762 char_width = CharWidth (ch);
6763 QDTextBounds (1, &ch, &char_bounds);
6764 STORE_XCHARSTRUCT (font->per_char[c - 0x20],
6765 char_width, char_bounds);
6766 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6767 character width of 0x7f. */
6768 if (char_width > 0)
6770 min_width = min (min_width, char_width);
6771 max_width = max (max_width, char_width);
6773 if (!EmptyRect (&char_bounds))
6775 SetRect (&min_bounds,
6776 max (min_bounds.left, char_bounds.left),
6777 max (min_bounds.top, char_bounds.top),
6778 min (min_bounds.right, char_bounds.right),
6779 min (min_bounds.bottom, char_bounds.bottom));
6780 UnionRect (&max_bounds, &char_bounds, &max_bounds);
6783 STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds);
6784 STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds);
6785 if (min_width == max_width
6786 && max_bounds.left >= 0 && max_bounds.right <= max_width)
6788 /* Fixed width and no overhangs. */
6789 xfree (font->per_char);
6790 font->per_char = NULL;
6795 TextFont (old_fontnum); /* restore previous font number, size and face */
6796 TextSize (old_fontsize);
6797 TextFace (old_fontface);
6799 return font;
6803 void
6804 mac_unload_font (dpyinfo, font)
6805 struct mac_display_info *dpyinfo;
6806 XFontStruct *font;
6808 xfree (font->fontname);
6809 if (font->per_char)
6810 xfree (font->per_char);
6811 xfree (font);
6815 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6816 pointer to the structure font_info while allocating it dynamically.
6817 If SIZE is 0, load any size of font.
6818 If loading is failed, return NULL. */
6820 struct font_info *
6821 x_load_font (f, fontname, size)
6822 struct frame *f;
6823 register char *fontname;
6824 int size;
6826 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6827 Lisp_Object font_names;
6829 /* Get a list of all the fonts that match this name. Once we
6830 have a list of matching fonts, we compare them against the fonts
6831 we already have by comparing names. */
6832 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6834 if (!NILP (font_names))
6836 Lisp_Object tail;
6837 int i;
6839 for (i = 0; i < dpyinfo->n_fonts; i++)
6840 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6841 if (dpyinfo->font_table[i].name
6842 && (!strcmp (dpyinfo->font_table[i].name,
6843 SDATA (XCAR (tail)))
6844 || !strcmp (dpyinfo->font_table[i].full_name,
6845 SDATA (XCAR (tail)))))
6846 return (dpyinfo->font_table + i);
6849 /* Load the font and add it to the table. */
6851 char *full_name;
6852 struct MacFontStruct *font;
6853 struct font_info *fontp;
6854 unsigned long value;
6855 int i;
6857 /* If we have found fonts by x_list_font, load one of them. If
6858 not, we still try to load a font by the name given as FONTNAME
6859 because XListFonts (called in x_list_font) of some X server has
6860 a bug of not finding a font even if the font surely exists and
6861 is loadable by XLoadQueryFont. */
6862 if (size > 0 && !NILP (font_names))
6863 fontname = (char *) SDATA (XCAR (font_names));
6865 BLOCK_INPUT;
6866 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6867 UNBLOCK_INPUT;
6868 if (!font)
6869 return NULL;
6871 /* Find a free slot in the font table. */
6872 for (i = 0; i < dpyinfo->n_fonts; ++i)
6873 if (dpyinfo->font_table[i].name == NULL)
6874 break;
6876 /* If no free slot found, maybe enlarge the font table. */
6877 if (i == dpyinfo->n_fonts
6878 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6880 int sz;
6881 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6882 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6883 dpyinfo->font_table
6884 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6887 fontp = dpyinfo->font_table + i;
6888 if (i == dpyinfo->n_fonts)
6889 ++dpyinfo->n_fonts;
6891 /* Now fill in the slots of *FONTP. */
6892 BLOCK_INPUT;
6893 bzero (fontp, sizeof (*fontp));
6894 fontp->font = font;
6895 fontp->font_idx = i;
6896 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6897 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6899 if (font->min_bounds.width == font->max_bounds.width)
6901 /* Fixed width font. */
6902 fontp->average_width = fontp->space_width = font->min_bounds.width;
6904 else
6906 XChar2b char2b;
6907 XCharStruct *pcm;
6909 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
6910 pcm = mac_per_char_metric (font, &char2b, 0);
6911 if (pcm)
6912 fontp->space_width = pcm->width;
6913 else
6914 fontp->space_width = FONT_WIDTH (font);
6916 if (pcm)
6918 int width = pcm->width;
6919 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
6920 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
6921 width += pcm->width;
6922 fontp->average_width = width / 95;
6924 else
6925 fontp->average_width = FONT_WIDTH (font);
6928 fontp->full_name = fontp->name;
6930 fontp->size = font->max_bounds.width;
6931 fontp->height = FONT_HEIGHT (font);
6933 /* For some font, ascent and descent in max_bounds field is
6934 larger than the above value. */
6935 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6936 if (max_height > fontp->height)
6937 fontp->height = max_height;
6940 /* The slot `encoding' specifies how to map a character
6941 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6942 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6943 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6944 2:0xA020..0xFF7F). For the moment, we don't know which charset
6945 uses this font. So, we set information in fontp->encoding[1]
6946 which is never used by any charset. If mapping can't be
6947 decided, set FONT_ENCODING_NOT_DECIDED. */
6948 if (font->mac_scriptcode == smJapanese)
6949 fontp->encoding[1] = 4;
6950 else
6952 fontp->encoding[1]
6953 = (font->max_byte1 == 0
6954 /* 1-byte font */
6955 ? (font->min_char_or_byte2 < 0x80
6956 ? (font->max_char_or_byte2 < 0x80
6957 ? 0 /* 0x20..0x7F */
6958 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6959 : 1) /* 0xA0..0xFF */
6960 /* 2-byte font */
6961 : (font->min_byte1 < 0x80
6962 ? (font->max_byte1 < 0x80
6963 ? (font->min_char_or_byte2 < 0x80
6964 ? (font->max_char_or_byte2 < 0x80
6965 ? 0 /* 0x2020..0x7F7F */
6966 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6967 : 3) /* 0x20A0..0x7FFF */
6968 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6969 : (font->min_char_or_byte2 < 0x80
6970 ? (font->max_char_or_byte2 < 0x80
6971 ? 2 /* 0xA020..0xFF7F */
6972 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6973 : 1))); /* 0xA0A0..0xFFFF */
6976 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6977 fontp->baseline_offset
6978 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6979 ? (long) value : 0);
6980 fontp->relative_compose
6981 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6982 ? (long) value : 0);
6983 fontp->default_ascent
6984 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6985 ? (long) value : 0);
6986 #else
6987 fontp->baseline_offset = 0;
6988 fontp->relative_compose = 0;
6989 fontp->default_ascent = 0;
6990 #endif
6992 /* Set global flag fonts_changed_p to non-zero if the font loaded
6993 has a character with a smaller width than any other character
6994 before, or if the font loaded has a smalle>r height than any
6995 other font loaded before. If this happens, it will make a
6996 glyph matrix reallocation necessary. */
6997 fonts_changed_p = x_compute_min_glyph_bounds (f);
6998 UNBLOCK_INPUT;
6999 return fontp;
7004 /* Return a pointer to struct font_info of a font named FONTNAME for
7005 frame F. If no such font is loaded, return NULL. */
7007 struct font_info *
7008 x_query_font (f, fontname)
7009 struct frame *f;
7010 register char *fontname;
7012 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7013 int i;
7015 for (i = 0; i < dpyinfo->n_fonts; i++)
7016 if (dpyinfo->font_table[i].name
7017 && (!strcmp (dpyinfo->font_table[i].name, fontname)
7018 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
7019 return (dpyinfo->font_table + i);
7020 return NULL;
7024 /* Find a CCL program for a font specified by FONTP, and set the member
7025 `encoder' of the structure. */
7027 void
7028 x_find_ccl_program (fontp)
7029 struct font_info *fontp;
7031 Lisp_Object list, elt;
7033 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7035 elt = XCAR (list);
7036 if (CONSP (elt)
7037 && STRINGP (XCAR (elt))
7038 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7039 >= 0))
7040 break;
7042 if (! NILP (list))
7044 struct ccl_program *ccl
7045 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7047 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7048 xfree (ccl);
7049 else
7050 fontp->font_encoder = ccl;
7056 /* The Mac Event loop code */
7058 #if !TARGET_API_MAC_CARBON
7059 #include <Events.h>
7060 #include <Quickdraw.h>
7061 #include <Balloons.h>
7062 #include <Devices.h>
7063 #include <Fonts.h>
7064 #include <Gestalt.h>
7065 #include <Menus.h>
7066 #include <Processes.h>
7067 #include <Sound.h>
7068 #include <ToolUtils.h>
7069 #include <TextUtils.h>
7070 #include <Dialogs.h>
7071 #include <Script.h>
7072 #include <Types.h>
7073 #include <TextEncodingConverter.h>
7074 #include <Resources.h>
7076 #if __MWERKS__
7077 #include <unix.h>
7078 #endif
7079 #endif /* ! TARGET_API_MAC_CARBON */
7081 #define M_APPLE 128
7082 #define I_ABOUT 1
7084 #define WINDOW_RESOURCE 128
7085 #define TERM_WINDOW_RESOURCE 129
7087 #define DEFAULT_NUM_COLS 80
7089 #define MIN_DOC_SIZE 64
7090 #define MAX_DOC_SIZE 32767
7092 /* sleep time for WaitNextEvent */
7093 #define WNE_SLEEP_AT_SUSPEND 10
7094 #define WNE_SLEEP_AT_RESUME 1
7096 /* true when cannot handle any Mac OS events */
7097 static int handling_window_update = 0;
7099 #if 0
7100 /* the flag appl_is_suspended is used both for determining the sleep
7101 time to be passed to WaitNextEvent and whether the cursor should be
7102 drawn when updating the display. The cursor is turned off when
7103 Emacs is suspended. Redrawing it is unnecessary and what needs to
7104 be done depends on whether the cursor lies inside or outside the
7105 redraw region. So we might as well skip drawing it when Emacs is
7106 suspended. */
7107 static Boolean app_is_suspended = false;
7108 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
7109 #endif
7111 #define EXTRA_STACK_ALLOC (256 * 1024)
7113 #define ARGV_STRING_LIST_ID 129
7114 #define ABOUT_ALERT_ID 128
7115 #define RAM_TOO_LARGE_ALERT_ID 129
7117 Boolean terminate_flag = false;
7119 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7120 Lisp_Object Qreverse;
7122 /* True if using command key as meta key. */
7123 Lisp_Object Vmac_command_key_is_meta;
7125 /* Modifier associated with the option key, or nil for normal behavior. */
7126 Lisp_Object Vmac_option_modifier;
7128 /* True if the ctrl and meta keys should be reversed. */
7129 Lisp_Object Vmac_reverse_ctrl_meta;
7131 /* True if the option and command modifiers should be used to emulate
7132 a three button mouse */
7133 Lisp_Object Vmac_emulate_three_button_mouse;
7135 #if USE_CARBON_EVENTS
7136 /* True if the mouse wheel button (i.e. button 4) should map to
7137 mouse-2, instead of mouse-3. */
7138 Lisp_Object Vmac_wheel_button_is_mouse_2;
7140 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7141 for processing before Emacs sees it. */
7142 Lisp_Object Vmac_pass_command_to_system;
7144 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7145 for processing before Emacs sees it. */
7146 Lisp_Object Vmac_pass_control_to_system;
7147 #endif
7149 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7150 to this text encoding */
7151 int mac_keyboard_text_encoding;
7152 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7154 /* Set in term/mac-win.el to indicate that event loop can now generate
7155 drag and drop events. */
7156 Lisp_Object Qmac_ready_for_drag_n_drop;
7158 Lisp_Object drag_and_drop_file_list;
7160 Point saved_menu_event_location;
7162 /* Apple Events */
7163 static void init_required_apple_events (void);
7164 static pascal OSErr
7165 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7166 static pascal OSErr
7167 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7168 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7169 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7171 #if TARGET_API_MAC_CARBON
7172 /* Drag and Drop */
7173 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
7174 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7175 static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL;
7176 static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL;
7177 #endif
7179 #if USE_CARBON_EVENTS
7180 #ifdef MAC_OSX
7181 /* Preliminary Support for the OSX Services Menu */
7182 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7183 static void init_service_handler ();
7184 #endif
7185 /* Window Event Handler */
7186 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7187 EventRef, void *);
7188 #endif
7189 OSErr install_window_handler (WindowPtr);
7191 extern void init_emacs_passwd_dir ();
7192 extern int emacs_main (int, char **, char **);
7193 extern void check_alarm ();
7195 extern void initialize_applescript();
7196 extern void terminate_applescript();
7198 static unsigned int
7199 #if USE_CARBON_EVENTS
7200 mac_to_emacs_modifiers (UInt32 mods)
7201 #else
7202 mac_to_emacs_modifiers (EventModifiers mods)
7203 #endif
7205 unsigned int result = 0;
7206 if (mods & macShiftKey)
7207 result |= shift_modifier;
7208 if (mods & macCtrlKey)
7209 result |= ctrl_modifier;
7210 if (mods & macMetaKey)
7211 result |= meta_modifier;
7212 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7213 result |= alt_modifier;
7214 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7215 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7216 if (!NILP(val))
7217 result |= XUINT(val);
7220 return result;
7223 static int
7224 mac_get_emulated_btn ( UInt32 modifiers )
7226 int result = 0;
7227 if (!NILP (Vmac_emulate_three_button_mouse)) {
7228 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7229 if (modifiers & cmdKey)
7230 result = cmdIs3 ? 2 : 1;
7231 else if (modifiers & optionKey)
7232 result = cmdIs3 ? 1 : 2;
7234 return result;
7237 #if USE_CARBON_EVENTS
7238 /* Obtains the event modifiers from the event ref and then calls
7239 mac_to_emacs_modifiers. */
7240 static int
7241 mac_event_to_emacs_modifiers (EventRef eventRef)
7243 UInt32 mods = 0;
7244 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7245 sizeof (UInt32), NULL, &mods);
7246 if (!NILP (Vmac_emulate_three_button_mouse) &&
7247 GetEventClass(eventRef) == kEventClassMouse)
7249 mods &= ~(optionKey | cmdKey);
7251 return mac_to_emacs_modifiers (mods);
7254 /* Given an event ref, return the code to use for the mouse button
7255 code in the emacs input_event. */
7256 static int
7257 mac_get_mouse_btn (EventRef ref)
7259 EventMouseButton result = kEventMouseButtonPrimary;
7260 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7261 sizeof (EventMouseButton), NULL, &result);
7262 switch (result)
7264 case kEventMouseButtonPrimary:
7265 if (NILP (Vmac_emulate_three_button_mouse))
7266 return 0;
7267 else {
7268 UInt32 mods = 0;
7269 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7270 sizeof (UInt32), NULL, &mods);
7271 return mac_get_emulated_btn(mods);
7273 case kEventMouseButtonSecondary:
7274 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7275 case kEventMouseButtonTertiary:
7276 case 4: /* 4 is the number for the mouse wheel button */
7277 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7278 default:
7279 return 0;
7283 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7284 events. However the click of the mouse wheel is not converted to a
7285 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7286 checks to see if it is a mouse up or down carbon event that has not
7287 been converted, and if so, converts it by hand (to be picked up in
7288 the XTread_socket loop). */
7289 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7291 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7292 /* Do special case for mouse wheel button. */
7293 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7295 UInt32 kind = GetEventKind (eventRef);
7296 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7298 eventRec->what = mouseDown;
7299 result=1;
7301 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7303 eventRec->what = mouseUp;
7304 result=1;
7306 if (result)
7308 /* Need where and when. */
7309 UInt32 mods;
7310 GetEventParameter (eventRef, kEventParamMouseLocation,
7311 typeQDPoint, NULL, sizeof (Point),
7312 NULL, &eventRec->where);
7313 /* Use two step process because new event modifiers are
7314 32-bit and old are 16-bit. Currently, only loss is
7315 NumLock & Fn. */
7316 GetEventParameter (eventRef, kEventParamKeyModifiers,
7317 typeUInt32, NULL, sizeof (UInt32),
7318 NULL, &mods);
7319 eventRec->modifiers = mods;
7321 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7324 return result;
7327 #endif
7329 static void
7330 do_get_menus (void)
7332 Handle menubar_handle;
7333 MenuHandle menu_handle;
7335 menubar_handle = GetNewMBar (128);
7336 if(menubar_handle == NULL)
7337 abort ();
7338 SetMenuBar (menubar_handle);
7339 DrawMenuBar ();
7341 menu_handle = GetMenuHandle (M_APPLE);
7342 if(menu_handle != NULL)
7343 AppendResMenu (menu_handle,'DRVR');
7344 else
7345 abort ();
7349 static void
7350 do_init_managers (void)
7352 #if !TARGET_API_MAC_CARBON
7353 InitGraf (&qd.thePort);
7354 InitFonts ();
7355 FlushEvents (everyEvent, 0);
7356 InitWindows ();
7357 InitMenus ();
7358 TEInit ();
7359 InitDialogs (NULL);
7360 #endif /* !TARGET_API_MAC_CARBON */
7361 InitCursor ();
7363 #if !TARGET_API_MAC_CARBON
7364 /* set up some extra stack space for use by emacs */
7365 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7367 /* MaxApplZone must be called for AppleScript to execute more
7368 complicated scripts */
7369 MaxApplZone ();
7370 MoreMasters ();
7371 #endif /* !TARGET_API_MAC_CARBON */
7374 static void
7375 do_check_ram_size (void)
7377 SInt32 physical_ram_size, logical_ram_size;
7379 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7380 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7381 || physical_ram_size > (1 << VALBITS)
7382 || logical_ram_size > (1 << VALBITS))
7384 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7385 exit (1);
7389 static void
7390 do_window_update (WindowPtr win)
7392 struct frame *f = mac_window_to_frame (win);
7394 BeginUpdate (win);
7396 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7397 below. */
7398 if (win != tip_window)
7400 if (f->async_visible == 0)
7402 f->async_visible = 1;
7403 f->async_iconified = 0;
7404 SET_FRAME_GARBAGED (f);
7406 /* An update event is equivalent to MapNotify on X, so report
7407 visibility changes properly. */
7408 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7409 /* Force a redisplay sooner or later to update the
7410 frame titles in case this is the second frame. */
7411 record_asynch_buffer_change ();
7413 else
7415 Rect r;
7417 handling_window_update = 1;
7419 #if TARGET_API_MAC_CARBON
7421 RgnHandle region = NewRgn ();
7423 GetPortVisibleRegion (GetWindowPort (win), region);
7424 GetRegionBounds (region, &r);
7425 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7426 UpdateControls (win, region);
7427 DisposeRgn (region);
7429 #else
7430 r = (*win->visRgn)->rgnBBox;
7431 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7432 UpdateControls (win, win->visRgn);
7433 #endif
7435 handling_window_update = 0;
7439 EndUpdate (win);
7442 static int
7443 is_emacs_window (WindowPtr win)
7445 Lisp_Object tail, frame;
7447 if (!win)
7448 return 0;
7450 FOR_EACH_FRAME (tail, frame)
7451 if (FRAME_MAC_P (XFRAME (frame)))
7452 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7453 return 1;
7455 return 0;
7458 static void
7459 do_app_resume ()
7461 /* Window-activate events will do the job. */
7462 #if 0
7463 WindowPtr wp;
7464 struct frame *f;
7466 wp = front_emacs_window ();
7467 if (wp)
7469 f = mac_window_to_frame (wp);
7471 if (f)
7473 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7474 activate_scroll_bars (f);
7478 app_is_suspended = false;
7479 app_sleep_time = WNE_SLEEP_AT_RESUME;
7480 #endif
7483 static void
7484 do_app_suspend ()
7486 /* Window-deactivate events will do the job. */
7487 #if 0
7488 WindowPtr wp;
7489 struct frame *f;
7491 wp = front_emacs_window ();
7492 if (wp)
7494 f = mac_window_to_frame (wp);
7496 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7498 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7499 deactivate_scroll_bars (f);
7503 app_is_suspended = true;
7504 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7505 #endif
7509 static void
7510 do_mouse_moved (mouse_pos, f)
7511 Point mouse_pos;
7512 FRAME_PTR *f;
7514 WindowPtr wp = front_emacs_window ();
7515 struct x_display_info *dpyinfo;
7517 if (wp)
7519 *f = mac_window_to_frame (wp);
7520 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7522 if (dpyinfo->mouse_face_hidden)
7524 dpyinfo->mouse_face_hidden = 0;
7525 clear_mouse_face (dpyinfo);
7528 SetPortWindowPort (wp);
7530 GlobalToLocal (&mouse_pos);
7532 if (dpyinfo->grabbed && tracked_scroll_bar)
7533 x_scroll_bar_note_movement (tracked_scroll_bar,
7534 mouse_pos.v
7535 - XINT (tracked_scroll_bar->top),
7536 TickCount() * (1000 / 60));
7537 else
7538 note_mouse_movement (*f, &mouse_pos);
7543 static void
7544 do_apple_menu (SInt16 menu_item)
7546 #if !TARGET_API_MAC_CARBON
7547 Str255 item_name;
7548 SInt16 da_driver_refnum;
7550 if (menu_item == I_ABOUT)
7551 NoteAlert (ABOUT_ALERT_ID, NULL);
7552 else
7554 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7555 da_driver_refnum = OpenDeskAcc (item_name);
7557 #endif /* !TARGET_API_MAC_CARBON */
7560 void
7561 do_menu_choice (SInt32 menu_choice)
7563 SInt16 menu_id, menu_item;
7565 menu_id = HiWord (menu_choice);
7566 menu_item = LoWord (menu_choice);
7568 if (menu_id == 0)
7569 return;
7571 switch (menu_id)
7573 case M_APPLE:
7574 do_apple_menu (menu_item);
7575 break;
7577 default:
7579 struct frame *f = mac_window_to_frame (front_emacs_window ());
7580 MenuHandle menu = GetMenuHandle (menu_id);
7581 if (menu)
7583 UInt32 refcon;
7585 GetMenuItemRefCon (menu, menu_item, &refcon);
7586 menubar_selection_callback (f, refcon);
7591 HiliteMenu (0);
7595 /* Handle drags in size box. Based on code contributed by Ben
7596 Mesander and IM - Window Manager A. */
7598 static void
7599 do_grow_window (WindowPtr w, EventRecord *e)
7601 Rect limit_rect;
7602 int rows, columns, width, height;
7603 struct frame *f = mac_window_to_frame (w);
7604 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7605 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7606 #if TARGET_API_MAC_CARBON
7607 Rect new_rect;
7608 #else
7609 long grow_size;
7610 #endif
7612 if (size_hints->flags & PMinSize)
7614 min_width = size_hints->min_width;
7615 min_height = size_hints->min_height;
7617 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
7619 #if TARGET_API_MAC_CARBON
7620 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7621 return;
7622 height = new_rect.bottom - new_rect.top;
7623 width = new_rect.right - new_rect.left;
7624 #else
7625 grow_size = GrowWindow (w, e->where, &limit_rect);
7626 /* see if it really changed size */
7627 if (grow_size == 0)
7628 return;
7629 height = HiWord (grow_size);
7630 width = LoWord (grow_size);
7631 #endif
7633 if (width != FRAME_PIXEL_WIDTH (f)
7634 || height != FRAME_PIXEL_HEIGHT (f))
7636 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7637 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7639 x_set_window_size (f, 0, columns, rows);
7644 /* Handle clicks in zoom box. Calculation of "standard state" based
7645 on code in IM - Window Manager A and code contributed by Ben
7646 Mesander. The standard state of an Emacs window is 80-characters
7647 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7649 static void
7650 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7652 GrafPtr save_port;
7653 Rect zoom_rect, port_rect;
7654 Point top_left;
7655 int w_title_height, columns, rows, width, height;
7656 struct frame *f = mac_window_to_frame (w);
7658 #if TARGET_API_MAC_CARBON
7660 Point standard_size;
7662 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7663 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7665 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7666 zoom_in_or_out = inZoomIn;
7667 else
7669 /* Adjust the standard size according to character boundaries. */
7671 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7672 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7673 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7674 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7675 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7676 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7677 && port_rect.left == zoom_rect.left
7678 && port_rect.top == zoom_rect.top)
7679 zoom_in_or_out = inZoomIn;
7680 else
7681 zoom_in_or_out = inZoomOut;
7684 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7686 #else /* not TARGET_API_MAC_CARBON */
7687 GetPort (&save_port);
7689 SetPortWindowPort (w);
7691 /* Clear window to avoid flicker. */
7692 EraseRect (&(w->portRect));
7693 if (zoom_in_or_out == inZoomOut)
7695 SetPt (&top_left, w->portRect.left, w->portRect.top);
7696 LocalToGlobal (&top_left);
7698 /* calculate height of window's title bar */
7699 w_title_height = top_left.v - 1
7700 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7702 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7703 zoom_rect = qd.screenBits.bounds;
7704 zoom_rect.top += w_title_height;
7705 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7707 zoom_rect.right = zoom_rect.left
7708 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7710 /* Adjust the standard size according to character boundaries. */
7711 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7712 zoom_rect.bottom =
7713 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7715 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7716 = zoom_rect;
7719 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7721 SetPort (save_port);
7722 #endif /* not TARGET_API_MAC_CARBON */
7724 /* retrieve window size and update application values */
7725 #if TARGET_API_MAC_CARBON
7726 GetWindowPortBounds (w, &port_rect);
7727 #else
7728 port_rect = w->portRect;
7729 #endif
7730 height = port_rect.bottom - port_rect.top;
7731 width = port_rect.right - port_rect.left;
7733 if (width != FRAME_PIXEL_WIDTH (f)
7734 || height != FRAME_PIXEL_HEIGHT (f))
7736 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7737 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7739 change_frame_size (f, rows, columns, 0, 1, 0);
7740 SET_FRAME_GARBAGED (f);
7741 cancel_mouse_face (f);
7743 FRAME_PIXEL_WIDTH (f) = width;
7744 FRAME_PIXEL_HEIGHT (f) = height;
7746 x_real_positions (f, &f->left_pos, &f->top_pos);
7749 /* Intialize AppleEvent dispatcher table for the required events. */
7750 void
7751 init_required_apple_events ()
7753 OSErr err;
7754 long result;
7756 /* Make sure we have apple events before starting. */
7757 err = Gestalt (gestaltAppleEventsAttr, &result);
7758 if (err != noErr)
7759 abort ();
7761 if (!(result & (1 << gestaltAppleEventsPresent)))
7762 abort ();
7764 #if TARGET_API_MAC_CARBON
7765 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7766 NewAEEventHandlerUPP
7767 ((AEEventHandlerProcPtr) do_ae_open_application),
7768 0L, false);
7769 #else
7770 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7771 NewAEEventHandlerProc
7772 ((AEEventHandlerProcPtr) do_ae_open_application),
7773 0L, false);
7774 #endif
7775 if (err != noErr)
7776 abort ();
7778 #if TARGET_API_MAC_CARBON
7779 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7780 NewAEEventHandlerUPP
7781 ((AEEventHandlerProcPtr) do_ae_open_documents),
7782 0L, false);
7783 #else
7784 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7785 NewAEEventHandlerProc
7786 ((AEEventHandlerProcPtr) do_ae_open_documents),
7787 0L, false);
7788 #endif
7789 if (err != noErr)
7790 abort ();
7792 #if TARGET_API_MAC_CARBON
7793 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7794 NewAEEventHandlerUPP
7795 ((AEEventHandlerProcPtr) do_ae_print_documents),
7796 0L, false);
7797 #else
7798 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7799 NewAEEventHandlerProc
7800 ((AEEventHandlerProcPtr) do_ae_print_documents),
7801 0L, false);
7802 #endif
7803 if (err != noErr)
7804 abort ();
7806 #if TARGET_API_MAC_CARBON
7807 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7808 NewAEEventHandlerUPP
7809 ((AEEventHandlerProcPtr) do_ae_quit_application),
7810 0L, false);
7811 #else
7812 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7813 NewAEEventHandlerProc
7814 ((AEEventHandlerProcPtr) do_ae_quit_application),
7815 0L, false);
7816 #endif
7817 if (err != noErr)
7818 abort ();
7821 #if USE_CARBON_EVENTS
7822 #ifdef MAC_OSX
7823 void
7824 init_service_handler ()
7826 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7827 {kEventClassService, kEventServiceCopy},
7828 {kEventClassService, kEventServicePaste}};
7829 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7830 3, specs, NULL, NULL);
7834 MAC_TODO: Check to see if this is called by AEProcessDesc...
7836 OSStatus
7837 mac_handle_service_event (EventHandlerCallRef callRef,
7838 EventRef event, void *data)
7840 OSStatus err = noErr;
7841 switch (GetEventKind (event))
7843 case kEventServiceGetTypes:
7845 CFMutableArrayRef copyTypes, pasteTypes;
7846 CFStringRef type;
7847 Boolean selection = true;
7849 GetEventParameter(event, kEventParamServicePasteTypes,
7850 typeCFMutableArrayRef, NULL,
7851 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7853 GetEventParameter(event, kEventParamServiceCopyTypes,
7854 typeCFMutableArrayRef, NULL,
7855 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7856 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7857 if (type) {
7858 CFArrayAppendValue (copyTypes, type);
7859 //CFArrayAppendValue (pasteTypes, type);
7860 CFRelease (type);
7863 case kEventServiceCopy:
7865 ScrapRef currentScrap, specificScrap;
7866 char * buf = "";
7867 Size byteCount = 0;
7869 GetCurrentScrap (&currentScrap);
7871 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7872 if (err == noErr)
7874 void *buffer = xmalloc (byteCount);
7875 if (buffer != NULL)
7877 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7878 sizeof (ScrapRef), NULL, &specificScrap);
7880 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7881 &byteCount, buffer);
7882 if (err == noErr)
7883 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7884 kScrapFlavorMaskNone, byteCount, buffer);
7885 xfree (buffer);
7888 err = noErr;
7890 case kEventServicePaste:
7893 // Get the current location
7894 Size byteCount;
7895 ScrapRef specificScrap;
7896 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7897 sizeof(ScrapRef), NULL, &specificScrap);
7898 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7899 if (err == noErr) {
7900 void * buffer = xmalloc(byteCount);
7901 if (buffer != NULL ) {
7902 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7903 &byteCount, buffer);
7904 if (err == noErr) {
7905 // Actually place in the buffer
7906 BLOCK_INPUT;
7907 // Get the current "selection" string here
7908 UNBLOCK_INPUT;
7911 xfree(buffer);
7916 return err;
7918 #endif
7920 static pascal OSStatus
7921 mac_handle_window_event (next_handler, event, data)
7922 EventHandlerCallRef next_handler;
7923 EventRef event;
7924 void *data;
7926 WindowPtr wp;
7927 OSStatus result;
7928 UInt32 attributes;
7929 XSizeHints *size_hints;
7931 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
7932 NULL, sizeof (WindowPtr), NULL, &wp);
7934 switch (GetEventKind (event))
7936 case kEventWindowUpdate:
7937 result = CallNextEventHandler (next_handler, event);
7938 if (result != eventNotHandledErr)
7939 return result;
7941 do_window_update (wp);
7942 break;
7944 case kEventWindowBoundsChanging:
7945 result = CallNextEventHandler (next_handler, event);
7946 if (result != eventNotHandledErr)
7947 return result;
7949 GetEventParameter (event, kEventParamAttributes, typeUInt32,
7950 NULL, sizeof (UInt32), NULL, &attributes);
7951 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
7952 if ((attributes & kWindowBoundsChangeUserResize)
7953 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
7954 == (PResizeInc | PBaseSize | PMinSize)))
7956 Rect bounds;
7957 int width, height;
7959 GetEventParameter (event, kEventParamCurrentBounds,
7960 typeQDRectangle,
7961 NULL, sizeof (Rect), NULL, &bounds);
7962 width = bounds.right - bounds.left;
7963 height = bounds.bottom - bounds.top;
7965 if (width < size_hints->min_width)
7966 width = size_hints->min_width;
7967 else
7968 width = size_hints->base_width
7969 + (int) ((width - size_hints->base_width)
7970 / (float) size_hints->width_inc + .5)
7971 * size_hints->width_inc;
7973 if (height < size_hints->min_height)
7974 height = size_hints->min_height;
7975 else
7976 height = size_hints->base_height
7977 + (int) ((height - size_hints->base_height)
7978 / (float) size_hints->height_inc + .5)
7979 * size_hints->height_inc;
7981 bounds.right = bounds.left + width;
7982 bounds.bottom = bounds.top + height;
7983 SetEventParameter (event, kEventParamCurrentBounds,
7984 typeQDRectangle, sizeof (Rect), &bounds);
7985 return noErr;
7987 break;
7990 return eventNotHandledErr;
7992 #endif /* USE_CARBON_EVENTS */
7995 OSErr
7996 install_window_handler (window)
7997 WindowPtr window;
7999 OSErr err = noErr;
8000 #if USE_CARBON_EVENTS
8001 EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate},
8002 {kEventClassWindow, kEventWindowBoundsChanging}};
8003 static EventHandlerUPP handle_window_event_UPP = NULL;
8005 if (handle_window_event_UPP == NULL)
8006 handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
8008 err = InstallWindowEventHandler (window, handle_window_event_UPP,
8009 GetEventTypeCount (specs), specs,
8010 NULL, NULL);
8011 #endif
8012 #if TARGET_API_MAC_CARBON
8013 if (mac_do_track_dragUPP == NULL)
8014 mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag);
8015 if (mac_do_receive_dragUPP == NULL)
8016 mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag);
8018 if (err == noErr)
8019 err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL);
8020 if (err == noErr)
8021 err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL);
8022 #endif
8023 return err;
8026 void
8027 remove_window_handler (window)
8028 WindowPtr window;
8030 #if TARGET_API_MAC_CARBON
8031 if (mac_do_track_dragUPP)
8032 RemoveTrackingHandler (mac_do_track_dragUPP, window);
8033 if (mac_do_receive_dragUPP)
8034 RemoveReceiveHandler (mac_do_receive_dragUPP, window);
8035 #endif
8038 /* Open Application Apple Event */
8039 static pascal OSErr
8040 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
8042 return noErr;
8046 /* Defined in mac.c. */
8047 extern int
8048 path_from_vol_dir_name (char *, int, short, long, char *);
8051 /* Called when we receive an AppleEvent with an ID of
8052 "kAEOpenDocuments". This routine gets the direct parameter,
8053 extracts the FSSpecs in it, and puts their names on a list. */
8054 #pragma options align=mac68k
8055 typedef struct SelectionRange {
8056 short unused1; // 0 (not used)
8057 short lineNum; // line to select (<0 to specify range)
8058 long startRange; // start of selection range (if line < 0)
8059 long endRange; // end of selection range (if line < 0)
8060 long unused2; // 0 (not used)
8061 long theDate; // modification date/time
8062 } SelectionRange;
8063 #pragma options align=reset
8065 static pascal OSErr
8066 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
8068 OSErr err, err2;
8069 AEDesc the_desc;
8070 AEKeyword keyword;
8071 DescType actual_type;
8072 Size actual_size;
8073 SelectionRange position;
8075 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
8076 if (err != noErr)
8077 goto descriptor_error_exit;
8079 err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
8080 if (err == noErr)
8081 drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1),
8082 make_number (position.startRange + 1),
8083 make_number (position.endRange + 1)),
8084 drag_and_drop_file_list);
8086 /* Check to see that we got all of the required parameters from the
8087 event descriptor. For an 'odoc' event this should just be the
8088 file list. */
8089 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
8090 &actual_type, (Ptr) &keyword,
8091 sizeof (keyword), &actual_size);
8092 /* No error means that we found some unused parameters.
8093 errAEDescNotFound means that there are no more parameters. If we
8094 get an error code other than that, flag it. */
8095 if ((err == noErr) || (err != errAEDescNotFound))
8097 err = errAEEventNotHandled;
8098 goto error_exit;
8100 err = noErr;
8102 /* Got all the parameters we need. Now, go through the direct
8103 object list and parse it up. */
8105 long num_files_to_open;
8107 err = AECountItems (&the_desc, &num_files_to_open);
8108 if (err == noErr)
8110 int i;
8112 /* AE file list is one based so just use that for indexing here. */
8113 for (i = 1; i <= num_files_to_open; i++)
8115 char unix_path_name[MAXPATHLEN];
8116 #ifdef MAC_OSX
8117 FSRef fref;
8119 err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
8120 &actual_type, &fref, sizeof (FSRef),
8121 &actual_size);
8122 if (err != noErr || actual_type != typeFSRef)
8123 continue;
8125 if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
8126 == noErr)
8127 #else
8128 FSSpec fs;
8130 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
8131 (Ptr) &fs, sizeof (fs), &actual_size);
8132 if (err != noErr) continue;
8134 if (fsspec_to_posix_pathname (&fs, unix_path_name,
8135 sizeof (unix_path_name) - 1) == noErr)
8136 #endif
8137 /* x-dnd functions expect undecoded filenames. */
8138 drag_and_drop_file_list =
8139 Fcons (make_unibyte_string (unix_path_name,
8140 strlen (unix_path_name)),
8141 drag_and_drop_file_list);
8146 error_exit:
8147 /* Nuke the coerced file list in any case */
8148 err2 = AEDisposeDesc(&the_desc);
8150 descriptor_error_exit:
8151 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8152 return err;
8156 #if TARGET_API_MAC_CARBON
8157 static pascal OSErr
8158 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
8159 void *handlerRefCon, DragReference theDrag)
8161 static int can_accept;
8162 short items;
8163 short index;
8164 ItemReference theItem;
8165 FlavorFlags theFlags;
8166 OSErr result;
8168 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8169 return dragNotAcceptedErr;
8171 switch (message)
8173 case kDragTrackingEnterHandler:
8174 CountDragItems (theDrag, &items);
8175 can_accept = 0;
8176 for (index = 1; index <= items; index++)
8178 GetDragItemReferenceNumber (theDrag, index, &theItem);
8179 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8180 if (result == noErr)
8182 can_accept = 1;
8183 break;
8186 break;
8188 case kDragTrackingEnterWindow:
8189 if (can_accept)
8191 RgnHandle hilite_rgn = NewRgn ();
8192 Rect r;
8193 struct frame *f = mac_window_to_frame (window);
8195 GetWindowPortBounds (window, &r);
8196 OffsetRect (&r, -r.left, -r.top);
8197 RectRgn (hilite_rgn, &r);
8198 ShowDragHilite (theDrag, hilite_rgn, true);
8199 DisposeRgn (hilite_rgn);
8200 SetThemeCursor (kThemeCopyArrowCursor);
8202 break;
8204 case kDragTrackingInWindow:
8205 break;
8207 case kDragTrackingLeaveWindow:
8208 if (can_accept)
8210 struct frame *f = mac_window_to_frame (window);
8212 HideDragHilite (theDrag);
8213 SetThemeCursor (kThemeArrowCursor);
8215 break;
8217 case kDragTrackingLeaveHandler:
8218 break;
8221 return noErr;
8224 static pascal OSErr
8225 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8226 DragReference theDrag)
8228 short items;
8229 short index;
8230 FlavorFlags theFlags;
8231 Point mouse;
8232 OSErr result;
8233 ItemReference theItem;
8234 HFSFlavor data;
8235 Size size = sizeof (HFSFlavor);
8237 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8238 return dragNotAcceptedErr;
8240 drag_and_drop_file_list = Qnil;
8241 GetDragMouse (theDrag, &mouse, 0L);
8242 CountDragItems (theDrag, &items);
8243 for (index = 1; index <= items; index++)
8245 /* Only handle file references. */
8246 GetDragItemReferenceNumber (theDrag, index, &theItem);
8247 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8248 if (result == noErr)
8250 #ifdef MAC_OSX
8251 FSRef fref;
8252 #endif
8253 char unix_path_name[MAXPATHLEN];
8255 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8256 #ifdef MAC_OSX
8257 /* Use Carbon routines, otherwise it converts the file name
8258 to /Macintosh HD/..., which is not correct. */
8259 FSpMakeFSRef (&data.fileSpec, &fref);
8260 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8261 #else
8262 if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name,
8263 sizeof (unix_path_name) - 1) == noErr)
8264 #endif
8265 /* x-dnd functions expect undecoded filenames. */
8266 drag_and_drop_file_list =
8267 Fcons (make_unibyte_string (unix_path_name,
8268 strlen (unix_path_name)),
8269 drag_and_drop_file_list);
8272 /* If there are items in the list, construct an event and post it to
8273 the queue like an interrupt using kbd_buffer_store_event. */
8274 if (!NILP (drag_and_drop_file_list))
8276 struct input_event event;
8277 Lisp_Object frame;
8278 struct frame *f = mac_window_to_frame (window);
8279 SInt16 modifiers;
8281 GlobalToLocal (&mouse);
8282 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
8284 event.kind = DRAG_N_DROP_EVENT;
8285 event.code = 0;
8286 event.modifiers = mac_to_emacs_modifiers (modifiers);
8287 event.timestamp = TickCount () * (1000 / 60);
8288 XSETINT (event.x, mouse.h);
8289 XSETINT (event.y, mouse.v);
8290 XSETFRAME (frame, f);
8291 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8292 event.arg = Qnil;
8293 /* Post to the interrupt queue */
8294 kbd_buffer_store_event (&event);
8295 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8297 ProcessSerialNumber psn;
8298 GetCurrentProcess (&psn);
8299 SetFrontProcess (&psn);
8302 return noErr;
8304 else
8305 return dragNotAcceptedErr;
8307 #endif
8310 /* Print Document Apple Event */
8311 static pascal OSErr
8312 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8314 return errAEEventNotHandled;
8318 static pascal OSErr
8319 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8321 /* FixMe: Do we need an unwind-protect or something here? And what
8322 do we do about unsaved files. Currently just forces quit rather
8323 than doing recursive callback to get user input. */
8325 terminate_flag = true;
8327 /* Fkill_emacs doesn't return. We have to return. (TI) */
8328 return noErr;
8332 #if __profile__
8333 void
8334 profiler_exit_proc ()
8336 ProfilerDump ("\pEmacs.prof");
8337 ProfilerTerm ();
8339 #endif
8341 /* These few functions implement Emacs as a normal Mac application
8342 (almost): set up the heap and the Toolbox, handle necessary
8343 system events plus a few simple menu events. They also set up
8344 Emacs's access to functions defined in the rest of this file.
8345 Emacs uses function hooks to perform all its terminal I/O. A
8346 complete list of these functions appear in termhooks.h. For what
8347 they do, read the comments there and see also w32term.c and
8348 xterm.c. What's noticeably missing here is the event loop, which
8349 is normally present in most Mac application. After performing the
8350 necessary Mac initializations, main passes off control to
8351 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8352 mac_read_socket (defined further below) to read input. This is
8353 where WaitNextEvent is called to process Mac events. This is also
8354 where check_alarm in sysdep.c is called to simulate alarm signals.
8355 This makes the cursor jump back to its correct position after
8356 briefly jumping to that of the matching parenthesis, print useful
8357 hints and prompts in the minibuffer after the user stops typing for
8358 a wait, etc. */
8360 #ifdef MAC_OS8
8361 #undef main
8363 main (void)
8365 #if __profile__ /* is the profiler on? */
8366 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8367 exit(1);
8368 #endif
8370 #if __MWERKS__
8371 /* set creator and type for files created by MSL */
8372 _fcreator = 'EMAx';
8373 _ftype = 'TEXT';
8374 #endif
8376 do_init_managers ();
8378 do_get_menus ();
8380 #ifndef USE_LSB_TAG
8381 do_check_ram_size ();
8382 #endif
8384 init_emacs_passwd_dir ();
8386 init_environ ();
8388 initialize_applescript ();
8390 init_required_apple_events ();
8393 char **argv;
8394 int argc = 0;
8396 /* set up argv array from STR# resource */
8397 get_string_list (&argv, ARGV_STRING_LIST_ID);
8398 while (argv[argc])
8399 argc++;
8401 /* free up AppleScript resources on exit */
8402 atexit (terminate_applescript);
8404 #if __profile__ /* is the profiler on? */
8405 atexit (profiler_exit_proc);
8406 #endif
8408 /* 3rd param "envp" never used in emacs_main */
8409 (void) emacs_main (argc, argv, 0);
8412 /* Never reached - real exit in Fkill_emacs */
8413 return 0;
8415 #endif
8417 /* Table for translating Mac keycode to X keysym values. Contributed
8418 by Sudhir Shenoy.
8419 Mapping for special keys is now identical to that in Apple X11
8420 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
8421 on the right of the Cmd key on laptops, and fn + `enter' (->
8422 <linefeed>). */
8423 static unsigned char keycode_to_xkeysym_table[] = {
8424 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8425 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8426 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8428 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8429 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
8430 /*0x38*/ 0, 0, 0, 0,
8431 /*0x3C*/ 0, 0, 0, 0,
8433 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8434 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
8435 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8436 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8438 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8439 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8440 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8441 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8443 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8444 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8445 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8446 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
8448 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
8449 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
8450 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8451 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8454 static int
8455 keycode_to_xkeysym (int keyCode, int *xKeySym)
8457 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8458 return *xKeySym != 0;
8461 #if !USE_CARBON_EVENTS
8462 static RgnHandle mouse_region = NULL;
8464 Boolean
8465 mac_wait_next_event (er, sleep_time, dequeue)
8466 EventRecord *er;
8467 UInt32 sleep_time;
8468 Boolean dequeue;
8470 static EventRecord er_buf = {nullEvent};
8471 UInt32 target_tick, current_tick;
8472 EventMask event_mask;
8474 if (mouse_region == NULL)
8475 mouse_region = NewRgn ();
8477 event_mask = everyEvent;
8478 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8479 event_mask -= highLevelEventMask;
8481 current_tick = TickCount ();
8482 target_tick = current_tick + sleep_time;
8484 if (er_buf.what == nullEvent)
8485 while (!WaitNextEvent (event_mask, &er_buf,
8486 target_tick - current_tick, mouse_region))
8488 current_tick = TickCount ();
8489 if (target_tick <= current_tick)
8490 return false;
8493 *er = er_buf;
8494 if (dequeue)
8495 er_buf.what = nullEvent;
8496 return true;
8498 #endif /* not USE_CARBON_EVENTS */
8500 /* Emacs calls this whenever it wants to read an input event from the
8501 user. */
8503 XTread_socket (sd, expected, hold_quit)
8504 int sd, expected;
8505 struct input_event *hold_quit;
8507 struct input_event inev;
8508 int count = 0;
8509 #if USE_CARBON_EVENTS
8510 EventRef eventRef;
8511 EventTargetRef toolbox_dispatcher;
8512 #endif
8513 EventRecord er;
8514 struct mac_display_info *dpyinfo = &one_mac_display_info;
8516 if (interrupt_input_blocked)
8518 interrupt_input_pending = 1;
8519 return -1;
8522 interrupt_input_pending = 0;
8523 BLOCK_INPUT;
8525 /* So people can tell when we have read the available input. */
8526 input_signal_count++;
8528 /* Don't poll for events to process (specifically updateEvt) if
8529 window update currently already in progress. A call to redisplay
8530 (in do_window_update) can be preempted by another call to
8531 redisplay, causing blank regions to be left on the screen and the
8532 cursor to be left at strange places. */
8533 if (handling_window_update)
8535 UNBLOCK_INPUT;
8536 return 0;
8539 if (terminate_flag)
8540 Fkill_emacs (make_number (1));
8542 #if USE_CARBON_EVENTS
8543 toolbox_dispatcher = GetEventDispatcherTarget ();
8545 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8546 kEventRemoveFromQueue, &eventRef))
8547 #else /* !USE_CARBON_EVENTS */
8548 while (mac_wait_next_event (&er, 0, true))
8549 #endif /* !USE_CARBON_EVENTS */
8551 int do_help = 0;
8552 struct frame *f;
8554 /* It is necessary to set this (additional) argument slot of an
8555 event to nil because keyboard.c protects incompletely
8556 processed event from being garbage collected by placing them
8557 in the kbd_buffer_gcpro vector. */
8558 EVENT_INIT (inev);
8559 inev.kind = NO_EVENT;
8560 inev.arg = Qnil;
8562 #if USE_CARBON_EVENTS
8563 /* Handle new events */
8564 if (!mac_convert_event_ref (eventRef, &er))
8565 switch (GetEventClass (eventRef))
8567 case kEventClassWindow:
8568 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8570 WindowPtr window_ptr;
8571 GetEventParameter(eventRef, kEventParamDirectObject,
8572 typeWindowRef, NULL, sizeof(WindowPtr),
8573 NULL, &window_ptr);
8574 f = mac_window_to_frame (window_ptr);
8575 if (f && !f->async_iconified)
8576 x_real_positions (f, &f->left_pos, &f->top_pos);
8577 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8579 break;
8580 case kEventClassMouse:
8581 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8583 SInt32 delta;
8584 Point point;
8585 WindowPtr window_ptr = front_emacs_window ();
8587 if (!IsValidWindowPtr (window_ptr))
8589 SysBeep(1);
8590 break;
8593 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8594 typeSInt32, NULL, sizeof (SInt32),
8595 NULL, &delta);
8596 GetEventParameter(eventRef, kEventParamMouseLocation,
8597 typeQDPoint, NULL, sizeof (Point),
8598 NULL, &point);
8599 inev.kind = WHEEL_EVENT;
8600 inev.code = 0;
8601 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8602 | ((delta < 0) ? down_modifier
8603 : up_modifier));
8604 SetPortWindowPort (window_ptr);
8605 GlobalToLocal (&point);
8606 XSETINT (inev.x, point.h);
8607 XSETINT (inev.y, point.v);
8608 XSETFRAME (inev.frame_or_window,
8609 mac_window_to_frame (window_ptr));
8610 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8612 else
8613 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8615 break;
8617 default:
8618 /* Send the event to the appropriate receiver. */
8619 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8621 else
8622 #endif /* USE_CARBON_EVENTS */
8623 switch (er.what)
8625 case mouseDown:
8626 case mouseUp:
8628 WindowPtr window_ptr;
8629 SInt16 part_code;
8630 int tool_bar_p = 0;
8632 #if USE_CARBON_EVENTS
8633 /* This is needed to send mouse events like aqua window
8634 buttons to the correct handler. */
8635 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8636 != eventNotHandledErr)
8637 break;
8638 #endif
8640 if (dpyinfo->grabbed && last_mouse_frame
8641 && FRAME_LIVE_P (last_mouse_frame))
8643 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8644 part_code = inContent;
8646 else
8648 part_code = FindWindow (er.where, &window_ptr);
8649 if (tip_window && window_ptr == tip_window)
8651 HideWindow (tip_window);
8652 part_code = FindWindow (er.where, &window_ptr);
8656 if (er.what != mouseDown && part_code != inContent)
8657 break;
8659 switch (part_code)
8661 case inMenuBar:
8662 f = mac_window_to_frame (front_emacs_window ());
8663 saved_menu_event_location = er.where;
8664 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8665 XSETFRAME (inev.frame_or_window, f);
8666 break;
8668 case inContent:
8669 if (window_ptr != front_emacs_window ())
8670 SelectWindow (window_ptr);
8671 else
8673 SInt16 control_part_code;
8674 ControlHandle ch;
8675 Point mouse_loc = er.where;
8677 f = mac_window_to_frame (window_ptr);
8678 /* convert to local coordinates of new window */
8679 SetPortWindowPort (window_ptr);
8681 GlobalToLocal (&mouse_loc);
8682 #if TARGET_API_MAC_CARBON
8683 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8684 &control_part_code);
8685 #else
8686 control_part_code = FindControl (mouse_loc, window_ptr,
8687 &ch);
8688 #endif
8690 #if USE_CARBON_EVENTS
8691 inev.code = mac_get_mouse_btn (eventRef);
8692 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8693 #else
8694 inev.code = mac_get_emulated_btn (er.modifiers);
8695 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8696 #endif
8697 XSETINT (inev.x, mouse_loc.h);
8698 XSETINT (inev.y, mouse_loc.v);
8699 inev.timestamp = er.when * (1000 / 60);
8700 /* ticks to milliseconds */
8702 if (dpyinfo->grabbed && tracked_scroll_bar
8703 /* control_part_code becomes kControlNoPart if
8704 a progress indicator is clicked. */
8705 || ch != 0 && control_part_code != kControlNoPart)
8707 struct scroll_bar *bar;
8709 if (dpyinfo->grabbed && tracked_scroll_bar)
8711 bar = tracked_scroll_bar;
8712 control_part_code = kControlIndicatorPart;
8714 else
8715 bar = (struct scroll_bar *) GetControlReference (ch);
8716 x_scroll_bar_handle_click (bar, control_part_code,
8717 &er, &inev);
8718 if (er.what == mouseDown
8719 && control_part_code == kControlIndicatorPart)
8720 tracked_scroll_bar = bar;
8721 else
8722 tracked_scroll_bar = NULL;
8724 else
8726 Lisp_Object window;
8727 int x = mouse_loc.h;
8728 int y = mouse_loc.v;
8730 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8731 if (EQ (window, f->tool_bar_window))
8733 if (er.what == mouseDown)
8734 handle_tool_bar_click (f, x, y, 1, 0);
8735 else
8736 handle_tool_bar_click (f, x, y, 0,
8737 inev.modifiers);
8738 tool_bar_p = 1;
8740 else
8742 XSETFRAME (inev.frame_or_window, f);
8743 inev.kind = MOUSE_CLICK_EVENT;
8747 if (er.what == mouseDown)
8749 dpyinfo->grabbed |= (1 << inev.code);
8750 last_mouse_frame = f;
8751 /* Ignore any mouse motion that happened
8752 before this event; any subsequent
8753 mouse-movement Emacs events should reflect
8754 only motion after the ButtonPress. */
8755 if (f != 0)
8756 f->mouse_moved = 0;
8758 if (!tool_bar_p)
8759 last_tool_bar_item = -1;
8761 else
8763 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8764 /* If a button is released though it was not
8765 previously pressed, that would be because
8766 of multi-button emulation. */
8767 dpyinfo->grabbed = 0;
8768 else
8769 dpyinfo->grabbed &= ~(1 << inev.code);
8772 switch (er.what)
8774 case mouseDown:
8775 inev.modifiers |= down_modifier;
8776 break;
8777 case mouseUp:
8778 inev.modifiers |= up_modifier;
8779 break;
8782 break;
8784 case inDrag:
8785 #if TARGET_API_MAC_CARBON
8786 DragWindow (window_ptr, er.where, NULL);
8787 #else /* not TARGET_API_MAC_CARBON */
8788 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8789 #endif /* not TARGET_API_MAC_CARBON */
8790 /* Update the frame parameters. */
8792 struct frame *f = mac_window_to_frame (window_ptr);
8794 if (f && !f->async_iconified)
8795 x_real_positions (f, &f->left_pos, &f->top_pos);
8797 break;
8799 case inGoAway:
8800 if (TrackGoAway (window_ptr, er.where))
8802 inev.kind = DELETE_WINDOW_EVENT;
8803 XSETFRAME (inev.frame_or_window,
8804 mac_window_to_frame (window_ptr));
8806 break;
8808 /* window resize handling added --ben */
8809 case inGrow:
8810 do_grow_window (window_ptr, &er);
8811 break;
8813 /* window zoom handling added --ben */
8814 case inZoomIn:
8815 case inZoomOut:
8816 if (TrackBox (window_ptr, er.where, part_code))
8817 do_zoom_window (window_ptr, part_code);
8818 break;
8820 default:
8821 break;
8824 break;
8826 case updateEvt:
8827 #if USE_CARBON_EVENTS
8828 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8829 != eventNotHandledErr)
8830 break;
8831 #else
8832 do_window_update ((WindowPtr) er.message);
8833 #endif
8834 break;
8836 case osEvt:
8837 #if USE_CARBON_EVENTS
8838 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8839 != eventNotHandledErr)
8840 break;
8841 #endif
8842 switch ((er.message >> 24) & 0x000000FF)
8844 case suspendResumeMessage:
8845 if ((er.message & resumeFlag) == 1)
8846 do_app_resume ();
8847 else
8848 do_app_suspend ();
8849 break;
8851 case mouseMovedMessage:
8852 #if !USE_CARBON_EVENTS
8853 SetRectRgn (mouse_region, er.where.h, er.where.v,
8854 er.where.h + 1, er.where.v + 1);
8855 #endif
8856 previous_help_echo_string = help_echo_string;
8857 help_echo_string = help_echo_object = help_echo_window = Qnil;
8858 help_echo_pos = -1;
8860 do_mouse_moved (er.where, &f);
8862 /* If the contents of the global variable
8863 help_echo_string has changed, generate a
8864 HELP_EVENT. */
8865 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8866 do_help = 1;
8867 break;
8869 break;
8871 case activateEvt:
8873 WindowPtr window_ptr = (WindowPtr) er.message;
8874 ControlRef root_control;
8876 #if USE_CARBON_EVENTS
8877 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8878 != eventNotHandledErr)
8879 break;
8880 #endif
8881 if (window_ptr == tip_window)
8883 HideWindow (tip_window);
8884 break;
8887 if (!is_emacs_window (window_ptr))
8888 break;
8890 f = mac_window_to_frame (window_ptr);
8891 GetRootControl (window_ptr, &root_control);
8893 if ((er.modifiers & activeFlag) != 0)
8895 /* A window has been activated */
8896 Point mouse_loc = er.where;
8898 x_new_focus_frame (dpyinfo, f);
8899 ActivateControl (root_control);
8901 SetPortWindowPort (window_ptr);
8902 GlobalToLocal (&mouse_loc);
8903 /* Window-activated event counts as mouse movement,
8904 so update things that depend on mouse position. */
8905 note_mouse_movement (mac_window_to_frame (window_ptr),
8906 &mouse_loc);
8908 else
8910 /* A window has been deactivated */
8911 dpyinfo->grabbed = 0;
8913 if (f == dpyinfo->x_focus_frame)
8915 x_new_focus_frame (dpyinfo, 0);
8916 DeactivateControl (root_control);
8920 if (f == dpyinfo->mouse_face_mouse_frame)
8922 /* If we move outside the frame, then we're
8923 certainly no longer on any text in the
8924 frame. */
8925 clear_mouse_face (dpyinfo);
8926 dpyinfo->mouse_face_mouse_frame = 0;
8929 /* Generate a nil HELP_EVENT to cancel a help-echo.
8930 Do it only if there's something to cancel.
8931 Otherwise, the startup message is cleared when the
8932 mouse leaves the frame. */
8933 if (any_help_event_p)
8934 do_help = -1;
8937 break;
8939 case keyDown:
8940 case autoKey:
8942 int keycode = (er.message & keyCodeMask) >> 8;
8943 int xkeysym;
8945 #if USE_CARBON_EVENTS && defined (MAC_OSX)
8946 /* When using Carbon Events, we need to pass raw keyboard
8947 events to the TSM ourselves. If TSM handles it, it
8948 will pass back noErr, otherwise it will pass back
8949 "eventNotHandledErr" and we can process it
8950 normally. */
8951 if ((!NILP (Vmac_pass_command_to_system)
8952 || !(er.modifiers & cmdKey))
8953 && (!NILP (Vmac_pass_control_to_system)
8954 || !(er.modifiers & controlKey)))
8955 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8956 != eventNotHandledErr)
8957 break;
8958 #endif
8960 #if TARGET_API_MAC_CARBON
8961 if (!IsValidWindowPtr (front_emacs_window ()))
8963 SysBeep (1);
8964 break;
8966 #endif
8968 ObscureCursor ();
8970 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8972 clear_mouse_face (dpyinfo);
8973 dpyinfo->mouse_face_hidden = 1;
8976 if (keycode_to_xkeysym (keycode, &xkeysym))
8978 inev.code = 0xff00 | xkeysym;
8979 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8981 else
8983 if (er.modifiers & (controlKey |
8984 (NILP (Vmac_command_key_is_meta) ? optionKey
8985 : cmdKey)))
8987 /* This code comes from Keyboard Resource,
8988 Appendix C of IM - Text. This is necessary
8989 since shift is ignored in KCHR table
8990 translation when option or command is pressed.
8991 It also does not translate correctly
8992 control-shift chars like C-% so mask off shift
8993 here also */
8994 int new_modifiers = er.modifiers & 0xe600;
8995 /* mask off option and command */
8996 int new_keycode = keycode | new_modifiers;
8997 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8998 unsigned long some_state = 0;
8999 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9000 &some_state) & 0xff;
9001 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
9003 /* When using the option key as an emacs modifier, convert
9004 the pressed key code back to one without the Mac option
9005 modifier applied. */
9006 int new_modifiers = er.modifiers & ~optionKey;
9007 int new_keycode = keycode | new_modifiers;
9008 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9009 unsigned long some_state = 0;
9010 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9011 &some_state) & 0xff;
9013 else
9014 inev.code = er.message & charCodeMask;
9015 inev.kind = ASCII_KEYSTROKE_EVENT;
9019 /* If variable mac-convert-keyboard-input-to-latin-1 is
9020 non-nil, convert non-ASCII characters typed at the Mac
9021 keyboard (presumed to be in the Mac Roman encoding) to
9022 iso-latin-1 encoding before they are passed to Emacs.
9023 This enables the Mac keyboard to be used to enter
9024 non-ASCII iso-latin-1 characters directly. */
9025 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
9026 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
9028 static TECObjectRef converter = NULL;
9029 OSStatus the_err = noErr;
9030 OSStatus convert_status = noErr;
9032 if (converter == NULL)
9034 the_err = TECCreateConverter (&converter,
9035 kTextEncodingMacRoman,
9036 mac_keyboard_text_encoding);
9037 current_mac_keyboard_text_encoding
9038 = mac_keyboard_text_encoding;
9040 else if (mac_keyboard_text_encoding
9041 != current_mac_keyboard_text_encoding)
9043 /* Free the converter for the current encoding
9044 before creating a new one. */
9045 TECDisposeConverter (converter);
9046 the_err = TECCreateConverter (&converter,
9047 kTextEncodingMacRoman,
9048 mac_keyboard_text_encoding);
9049 current_mac_keyboard_text_encoding
9050 = mac_keyboard_text_encoding;
9053 if (the_err == noErr)
9055 unsigned char ch = inev.code;
9056 ByteCount actual_input_length, actual_output_length;
9057 unsigned char outbuf[32];
9059 convert_status = TECConvertText (converter, &ch, 1,
9060 &actual_input_length,
9061 outbuf, 1,
9062 &actual_output_length);
9063 if (convert_status == noErr
9064 && actual_input_length == 1
9065 && actual_output_length == 1)
9066 inev.code = *outbuf;
9068 /* Reset internal states of the converter object.
9069 If it fails, create another one. */
9070 convert_status = TECFlushText (converter, outbuf,
9071 sizeof (outbuf),
9072 &actual_output_length);
9073 if (convert_status != noErr)
9075 TECDisposeConverter (converter);
9076 TECCreateConverter (&converter,
9077 kTextEncodingMacRoman,
9078 mac_keyboard_text_encoding);
9083 #if USE_CARBON_EVENTS
9084 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9085 #else
9086 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9087 #endif
9088 XSETFRAME (inev.frame_or_window,
9089 mac_window_to_frame (front_emacs_window ()));
9090 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
9091 break;
9093 case kHighLevelEvent:
9094 drag_and_drop_file_list = Qnil;
9096 AEProcessAppleEvent(&er);
9098 /* Build a DRAG_N_DROP_EVENT type event as is done in
9099 constuct_drag_n_drop in w32term.c. */
9100 if (!NILP (drag_and_drop_file_list))
9102 struct frame *f = NULL;
9103 WindowPtr wp;
9104 Lisp_Object frame;
9106 wp = front_emacs_window ();
9108 if (!wp)
9110 struct frame *f = XFRAME (XCAR (Vframe_list));
9111 CollapseWindow (FRAME_MAC_WINDOW (f), false);
9112 wp = front_emacs_window ();
9115 if (wp)
9116 f = mac_window_to_frame (wp);
9118 inev.kind = DRAG_N_DROP_EVENT;
9119 inev.code = 0;
9120 inev.timestamp = er.when * (1000 / 60);
9121 /* ticks to milliseconds */
9122 #if USE_CARBON_EVENTS
9123 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9124 #else
9125 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9126 #endif
9128 XSETINT (inev.x, 0);
9129 XSETINT (inev.y, 0);
9131 XSETFRAME (frame, f);
9132 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
9134 /* Regardless of whether Emacs was suspended or in the
9135 foreground, ask it to redraw its entire screen.
9136 Otherwise parts of the screen can be left in an
9137 inconsistent state. */
9138 if (wp)
9139 #if TARGET_API_MAC_CARBON
9141 Rect r;
9143 GetWindowPortBounds (wp, &r);
9144 InvalWindowRect (wp, &r);
9146 #else /* not TARGET_API_MAC_CARBON */
9147 InvalRect (&(wp->portRect));
9148 #endif /* not TARGET_API_MAC_CARBON */
9150 default:
9151 break;
9153 #if USE_CARBON_EVENTS
9154 ReleaseEvent (eventRef);
9155 #endif
9157 if (inev.kind != NO_EVENT)
9159 kbd_buffer_store_event_hold (&inev, hold_quit);
9160 count++;
9163 if (do_help
9164 && !(hold_quit && hold_quit->kind != NO_EVENT))
9166 Lisp_Object frame;
9168 if (f)
9169 XSETFRAME (frame, f);
9170 else
9171 frame = Qnil;
9173 if (do_help > 0)
9175 any_help_event_p = 1;
9176 gen_help_event (help_echo_string, frame, help_echo_window,
9177 help_echo_object, help_echo_pos);
9179 else
9181 help_echo_string = Qnil;
9182 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9184 count++;
9189 /* If the focus was just given to an autoraising frame,
9190 raise it now. */
9191 /* ??? This ought to be able to handle more than one such frame. */
9192 if (pending_autoraise_frame)
9194 x_raise_frame (pending_autoraise_frame);
9195 pending_autoraise_frame = 0;
9198 #if !TARGET_API_MAC_CARBON
9199 check_alarm (); /* simulate the handling of a SIGALRM */
9200 #endif
9202 UNBLOCK_INPUT;
9203 return count;
9207 /* Need to override CodeWarrior's input function so no conversion is
9208 done on newlines Otherwise compiled functions in .elc files will be
9209 read incorrectly. Defined in ...:MSL C:MSL
9210 Common:Source:buffer_io.c. */
9211 #ifdef __MWERKS__
9212 void
9213 __convert_to_newlines (unsigned char * p, size_t * n)
9215 #pragma unused(p,n)
9218 void
9219 __convert_from_newlines (unsigned char * p, size_t * n)
9221 #pragma unused(p,n)
9223 #endif
9225 #ifdef MAC_OS8
9226 void
9227 make_mac_terminal_frame (struct frame *f)
9229 Lisp_Object frame;
9230 Rect r;
9232 XSETFRAME (frame, f);
9234 f->output_method = output_mac;
9235 f->output_data.mac = (struct mac_output *)
9236 xmalloc (sizeof (struct mac_output));
9237 bzero (f->output_data.mac, sizeof (struct mac_output));
9239 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9241 FRAME_COLS (f) = 96;
9242 FRAME_LINES (f) = 4;
9244 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9245 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9247 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9249 f->output_data.mac->cursor_pixel = 0;
9250 f->output_data.mac->border_pixel = 0x00ff00;
9251 f->output_data.mac->mouse_pixel = 0xff00ff;
9252 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9254 f->output_data.mac->text_cursor = kThemeIBeamCursor;
9255 f->output_data.mac->nontext_cursor = kThemeArrowCursor;
9256 f->output_data.mac->modeline_cursor = kThemeArrowCursor;
9257 f->output_data.mac->hand_cursor = kThemePointingHandCursor;
9258 f->output_data.mac->hourglass_cursor = kThemeWatchCursor;
9259 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor;
9261 FRAME_FONTSET (f) = -1;
9262 f->output_data.mac->explicit_parent = 0;
9263 f->left_pos = 8;
9264 f->top_pos = 32;
9265 f->border_width = 0;
9267 f->internal_border_width = 0;
9269 f->auto_raise = 1;
9270 f->auto_lower = 1;
9272 f->new_text_cols = 0;
9273 f->new_text_lines = 0;
9275 SetRect (&r, f->left_pos, f->top_pos,
9276 f->left_pos + FRAME_PIXEL_WIDTH (f),
9277 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9279 BLOCK_INPUT;
9281 if (!(FRAME_MAC_WINDOW (f) =
9282 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9283 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9284 abort ();
9285 /* so that update events can find this mac_output struct */
9286 f->output_data.mac->mFP = f; /* point back to emacs frame */
9288 UNBLOCK_INPUT;
9290 x_make_gc (f);
9292 /* Need to be initialized for unshow_buffer in window.c. */
9293 selected_window = f->selected_window;
9295 Fmodify_frame_parameters (frame,
9296 Fcons (Fcons (Qfont,
9297 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9298 Fmodify_frame_parameters (frame,
9299 Fcons (Fcons (Qforeground_color,
9300 build_string ("black")), Qnil));
9301 Fmodify_frame_parameters (frame,
9302 Fcons (Fcons (Qbackground_color,
9303 build_string ("white")), Qnil));
9305 #endif
9308 /***********************************************************************
9309 Initialization
9310 ***********************************************************************/
9312 int mac_initialized = 0;
9314 void
9315 mac_initialize_display_info ()
9317 struct mac_display_info *dpyinfo = &one_mac_display_info;
9318 GDHandle main_device_handle;
9320 bzero (dpyinfo, sizeof (*dpyinfo));
9322 #ifdef MAC_OSX
9323 dpyinfo->mac_id_name
9324 = (char *) xmalloc (SCHARS (Vinvocation_name)
9325 + SCHARS (Vsystem_name)
9326 + 2);
9327 sprintf (dpyinfo->mac_id_name, "%s@%s",
9328 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9329 #else
9330 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9331 strcpy (dpyinfo->mac_id_name, "Mac Display");
9332 #endif
9334 main_device_handle = LMGetMainDevice();
9336 dpyinfo->reference_count = 0;
9337 dpyinfo->resx = 75.0;
9338 dpyinfo->resy = 75.0;
9339 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
9340 #ifdef MAC_OSX
9341 /* HasDepth returns true if it is possible to have a 32 bit display,
9342 but this may not be what is actually used. Mac OSX can do better.
9343 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9344 header for CGGetActiveDisplayList says that the first display returned
9345 is the active one, so we use that. */
9347 CGDirectDisplayID disp_id[1];
9348 CGDisplayCount disp_count;
9349 CGDisplayErr error_code;
9351 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9352 if (error_code != 0)
9353 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9355 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9357 #else
9358 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9359 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9360 gdDevType, dpyinfo->color_p))
9361 break;
9362 #endif
9363 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9364 dpyinfo->width = (**main_device_handle).gdRect.right;
9365 dpyinfo->grabbed = 0;
9366 dpyinfo->root_window = NULL;
9367 dpyinfo->image_cache = make_image_cache ();
9369 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9370 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9371 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9372 dpyinfo->mouse_face_window = Qnil;
9373 dpyinfo->mouse_face_overlay = Qnil;
9374 dpyinfo->mouse_face_hidden = 0;
9378 static XrmDatabase
9379 mac_make_rdb (xrm_option)
9380 char *xrm_option;
9382 XrmDatabase database;
9384 database = xrm_get_preference_database (NULL);
9385 if (xrm_option)
9386 xrm_merge_string_database (database, xrm_option);
9388 return database;
9391 struct mac_display_info *
9392 mac_term_init (display_name, xrm_option, resource_name)
9393 Lisp_Object display_name;
9394 char *xrm_option;
9395 char *resource_name;
9397 struct mac_display_info *dpyinfo;
9399 BLOCK_INPUT;
9401 if (!mac_initialized)
9403 mac_initialize ();
9404 mac_initialized = 1;
9407 if (x_display_list)
9408 error ("Sorry, this version can only handle one display");
9410 mac_initialize_display_info ();
9412 dpyinfo = &one_mac_display_info;
9414 dpyinfo->xrdb = mac_make_rdb (xrm_option);
9416 /* Put this display on the chain. */
9417 dpyinfo->next = x_display_list;
9418 x_display_list = dpyinfo;
9420 /* Put it on x_display_name_list. */
9421 x_display_name_list = Fcons (Fcons (display_name,
9422 Fcons (Qnil, dpyinfo->xrdb)),
9423 x_display_name_list);
9424 dpyinfo->name_list_element = XCAR (x_display_name_list);
9426 UNBLOCK_INPUT;
9428 return dpyinfo;
9430 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9432 void
9433 x_delete_display (dpyinfo)
9434 struct mac_display_info *dpyinfo;
9436 int i;
9438 /* Discard this display from x_display_name_list and x_display_list.
9439 We can't use Fdelq because that can quit. */
9440 if (! NILP (x_display_name_list)
9441 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9442 x_display_name_list = XCDR (x_display_name_list);
9443 else
9445 Lisp_Object tail;
9447 tail = x_display_name_list;
9448 while (CONSP (tail) && CONSP (XCDR (tail)))
9450 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9452 XSETCDR (tail, XCDR (XCDR (tail)));
9453 break;
9455 tail = XCDR (tail);
9459 if (x_display_list == dpyinfo)
9460 x_display_list = dpyinfo->next;
9461 else
9463 struct x_display_info *tail;
9465 for (tail = x_display_list; tail; tail = tail->next)
9466 if (tail->next == dpyinfo)
9467 tail->next = tail->next->next;
9470 /* Free the font names in the font table. */
9471 for (i = 0; i < dpyinfo->n_fonts; i++)
9472 if (dpyinfo->font_table[i].name)
9474 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9475 xfree (dpyinfo->font_table[i].full_name);
9476 xfree (dpyinfo->font_table[i].name);
9479 if (dpyinfo->font_table->font_encoder)
9480 xfree (dpyinfo->font_table->font_encoder);
9482 xfree (dpyinfo->font_table);
9483 xfree (dpyinfo->mac_id_name);
9485 if (x_display_list == 0)
9487 mac_clear_font_name_table ();
9488 bzero (dpyinfo, sizeof (*dpyinfo));
9493 #ifdef MAC_OSX
9494 void
9495 mac_check_bundle()
9497 extern int inhibit_window_system;
9498 extern int noninteractive;
9499 CFBundleRef appsBundle;
9500 pid_t child;
9502 /* No need to test if already -nw*/
9503 if (inhibit_window_system || noninteractive)
9504 return;
9506 appsBundle = CFBundleGetMainBundle();
9507 if (appsBundle != NULL)
9509 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9510 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9511 /* We found the bundle identifier, now we know we are valid. */
9512 if (res != NULL)
9514 CFRelease(res);
9515 return;
9518 /* MAC_TODO: Have this start the bundled executable */
9520 /* For now, prevent the fatal error by bringing it up in the terminal */
9521 inhibit_window_system = 1;
9524 void
9525 MakeMeTheFrontProcess ()
9527 ProcessSerialNumber psn;
9528 OSErr err;
9530 err = GetCurrentProcess (&psn);
9531 if (err == noErr)
9532 (void) SetFrontProcess (&psn);
9535 /***** Code to handle C-g testing *****/
9537 /* Contains the Mac modifier formed from quit_char */
9538 static mac_quit_char_modifiers = 0;
9539 static mac_quit_char_keycode;
9540 extern int quit_char;
9542 static void
9543 mac_determine_quit_char_modifiers()
9545 /* Todo: Determine modifiers from quit_char. */
9546 UInt32 qc_modifiers = ctrl_modifier;
9548 /* Map modifiers */
9549 mac_quit_char_modifiers = 0;
9550 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9551 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9552 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9553 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9556 static void
9557 init_quit_char_handler ()
9559 /* TODO: Let this support keys other the 'g' */
9560 mac_quit_char_keycode = 5;
9561 /* Look at <architecture/adb_kb_map.h> for details */
9562 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9564 mac_determine_quit_char_modifiers();
9567 static Boolean
9568 quit_char_comp (EventRef inEvent, void *inCompData)
9570 if (GetEventClass(inEvent) != kEventClassKeyboard)
9571 return false;
9572 if (GetEventKind(inEvent) != kEventRawKeyDown)
9573 return false;
9575 UInt32 keyCode;
9576 UInt32 keyModifiers;
9577 GetEventParameter(inEvent, kEventParamKeyCode,
9578 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9579 if (keyCode != mac_quit_char_keycode)
9580 return false;
9581 GetEventParameter(inEvent, kEventParamKeyModifiers,
9582 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9583 if (keyModifiers != mac_quit_char_modifiers)
9584 return false;
9586 return true;
9589 void
9590 mac_check_for_quit_char ()
9592 EventRef event;
9593 static EMACS_TIME last_check_time = { 0, 0 };
9594 static EMACS_TIME one_second = { 1, 0 };
9595 EMACS_TIME now, t;
9597 /* If windows are not initialized, return immediately (keep it bouncin'). */
9598 if (!mac_quit_char_modifiers)
9599 return;
9601 /* Don't check if last check is less than a second ago. */
9602 EMACS_GET_TIME (now);
9603 EMACS_SUB_TIME (t, now, last_check_time);
9604 if (EMACS_TIME_LT (t, one_second))
9605 return;
9606 last_check_time = now;
9608 /* Redetermine modifiers because they are based on lisp variables */
9609 mac_determine_quit_char_modifiers ();
9611 /* Fill the queue with events */
9612 BLOCK_INPUT;
9613 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9614 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9615 NULL);
9616 UNBLOCK_INPUT;
9617 if (event)
9619 struct input_event e;
9621 /* Use an input_event to emulate what the interrupt handler does. */
9622 EVENT_INIT (e);
9623 e.kind = ASCII_KEYSTROKE_EVENT;
9624 e.code = quit_char;
9625 e.arg = Qnil;
9626 e.modifiers = NULL;
9627 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9628 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9629 /* Remove event from queue to prevent looping. */
9630 RemoveEventFromQueue (GetMainEventQueue (), event);
9631 ReleaseEvent (event);
9632 kbd_buffer_store_event (&e);
9636 #endif /* MAC_OSX */
9638 /* Set up use of X before we make the first connection. */
9640 extern frame_parm_handler mac_frame_parm_handlers[];
9642 static struct redisplay_interface x_redisplay_interface =
9644 mac_frame_parm_handlers,
9645 x_produce_glyphs,
9646 x_write_glyphs,
9647 x_insert_glyphs,
9648 x_clear_end_of_line,
9649 x_scroll_run,
9650 x_after_update_window_line,
9651 x_update_window_begin,
9652 x_update_window_end,
9653 x_cursor_to,
9654 x_flush,
9655 0, /* flush_display_optional */
9656 x_clear_window_mouse_face,
9657 x_get_glyph_overhangs,
9658 x_fix_overlapping_area,
9659 x_draw_fringe_bitmap,
9660 0, /* define_fringe_bitmap */
9661 0, /* destroy_fringe_bitmap */
9662 mac_per_char_metric,
9663 mac_encode_char,
9664 mac_compute_glyph_string_overhangs,
9665 x_draw_glyph_string,
9666 mac_define_frame_cursor,
9667 mac_clear_frame_area,
9668 mac_draw_window_cursor,
9669 mac_draw_vertical_window_border,
9670 mac_shift_glyphs_for_insert
9673 void
9674 mac_initialize ()
9676 rif = &x_redisplay_interface;
9678 clear_frame_hook = x_clear_frame;
9679 ins_del_lines_hook = x_ins_del_lines;
9680 delete_glyphs_hook = x_delete_glyphs;
9681 ring_bell_hook = XTring_bell;
9682 reset_terminal_modes_hook = XTreset_terminal_modes;
9683 set_terminal_modes_hook = XTset_terminal_modes;
9684 update_begin_hook = x_update_begin;
9685 update_end_hook = x_update_end;
9686 set_terminal_window_hook = XTset_terminal_window;
9687 read_socket_hook = XTread_socket;
9688 frame_up_to_date_hook = XTframe_up_to_date;
9689 mouse_position_hook = XTmouse_position;
9690 frame_rehighlight_hook = XTframe_rehighlight;
9691 frame_raise_lower_hook = XTframe_raise_lower;
9693 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9694 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9695 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9696 judge_scroll_bars_hook = XTjudge_scroll_bars;
9698 scroll_region_ok = 1; /* we'll scroll partial frames */
9699 char_ins_del_ok = 1;
9700 line_ins_del_ok = 1; /* we'll just blt 'em */
9701 fast_clear_end_of_line = 1; /* X does this well */
9702 memory_below_frame = 0; /* we don't remember what scrolls
9703 off the bottom */
9704 baud_rate = 19200;
9706 x_noop_count = 0;
9707 last_tool_bar_item = -1;
9708 any_help_event_p = 0;
9710 /* Try to use interrupt input; if we can't, then start polling. */
9711 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9713 #ifdef USE_X_TOOLKIT
9714 XtToolkitInitialize ();
9715 Xt_app_con = XtCreateApplicationContext ();
9716 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9718 /* Install an asynchronous timer that processes Xt timeout events
9719 every 0.1s. This is necessary because some widget sets use
9720 timeouts internally, for example the LessTif menu bar, or the
9721 Xaw3d scroll bar. When Xt timouts aren't processed, these
9722 widgets don't behave normally. */
9724 EMACS_TIME interval;
9725 EMACS_SET_SECS_USECS (interval, 0, 100000);
9726 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9728 #endif
9730 #if USE_TOOLKIT_SCROLL_BARS
9731 xaw3d_arrow_scroll = False;
9732 xaw3d_pick_top = True;
9733 #endif
9735 #if 0
9736 /* Note that there is no real way portable across R3/R4 to get the
9737 original error handler. */
9738 XSetErrorHandler (x_error_handler);
9739 XSetIOErrorHandler (x_io_error_quitter);
9741 /* Disable Window Change signals; they are handled by X events. */
9742 #ifdef SIGWINCH
9743 signal (SIGWINCH, SIG_DFL);
9744 #endif /* ! defined (SIGWINCH) */
9746 signal (SIGPIPE, x_connection_signal);
9747 #endif
9749 BLOCK_INPUT;
9751 #if TARGET_API_MAC_CARBON
9752 init_required_apple_events ();
9754 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9755 init_service_handler ();
9757 init_quit_char_handler ();
9758 #endif
9760 DisableMenuCommand (NULL, kHICommandQuit);
9762 #ifdef MAC_OSX
9763 if (!inhibit_window_system)
9764 MakeMeTheFrontProcess ();
9765 #endif
9766 #endif
9767 UNBLOCK_INPUT;
9771 void
9772 syms_of_macterm ()
9774 #if 0
9775 staticpro (&x_error_message_string);
9776 x_error_message_string = Qnil;
9777 #endif
9779 Qmodifier_value = intern ("modifier-value");
9780 Qalt = intern ("alt");
9781 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9782 Qhyper = intern ("hyper");
9783 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9784 Qsuper = intern ("super");
9785 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9787 #ifdef MAC_OSX
9788 Fprovide (intern ("mac-carbon"), Qnil);
9789 #endif
9791 staticpro (&Qreverse);
9792 Qreverse = intern ("reverse");
9794 staticpro (&x_display_name_list);
9795 x_display_name_list = Qnil;
9797 staticpro (&last_mouse_scroll_bar);
9798 last_mouse_scroll_bar = Qnil;
9800 staticpro (&Qvendor_specific_keysyms);
9801 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9803 staticpro (&last_mouse_press_frame);
9804 last_mouse_press_frame = Qnil;
9806 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9807 staticpro (&Qmac_ready_for_drag_n_drop);
9809 Qbig5 = intern ("big5");
9810 staticpro (&Qbig5);
9812 Qcn_gb = intern ("cn-gb");
9813 staticpro (&Qcn_gb);
9815 Qsjis = intern ("sjis");
9816 staticpro (&Qsjis);
9818 Qeuc_kr = intern ("euc-kr");
9819 staticpro (&Qeuc_kr);
9821 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9822 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9823 x_autoselect_window_p = 0;
9825 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9826 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9827 Vx_toolkit_scroll_bars = Qt;
9829 DEFVAR_BOOL ("x-use-underline-position-properties",
9830 &x_use_underline_position_properties,
9831 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9832 nil means ignore them. If you encounter fonts with bogus
9833 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9834 to 4.1, set this to nil. */);
9835 x_use_underline_position_properties = 0;
9837 staticpro (&last_mouse_motion_frame);
9838 last_mouse_motion_frame = Qnil;
9840 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9841 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9842 Otherwise the option key is used. */);
9843 Vmac_command_key_is_meta = Qt;
9845 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9846 doc: /* Modifier to use for the Mac alt/option key. The value can
9847 be alt, hyper, or super for the respective modifier. If the value is
9848 nil then the key will act as the normal Mac option modifier. */);
9849 Vmac_option_modifier = Qnil;
9851 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9852 doc: /* Non-nil means that the control and meta keys are reversed. This is
9853 useful for non-standard keyboard layouts. */);
9854 Vmac_reverse_ctrl_meta = Qnil;
9856 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9857 &Vmac_emulate_three_button_mouse,
9858 doc: /* t means that when the option-key is held down while pressing the
9859 mouse button, the click will register as mouse-2 and while the
9860 command-key is held down, the click will register as mouse-3.
9861 'reverse means that the the option-key will register for mouse-3
9862 and the command-key will register for mouse-2. nil means that
9863 no emulation should be done and the modifiers should be placed
9864 on the mouse-1 event. */);
9865 Vmac_emulate_three_button_mouse = Qnil;
9867 #if USE_CARBON_EVENTS
9868 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9869 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9870 the right click will be mouse-3.
9871 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9872 Vmac_wheel_button_is_mouse_2 = Qt;
9874 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9875 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9876 Toolbox for processing before Emacs sees it. */);
9877 Vmac_pass_command_to_system = Qt;
9879 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9880 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9881 Toolbox for processing before Emacs sees it. */);
9882 Vmac_pass_control_to_system = Qt;
9884 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9885 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9886 Toolbox for processing before Emacs sees it. */);
9887 Vmac_pass_control_to_system = Qt;
9888 #endif
9890 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
9891 doc: /* If non-nil, allow anti-aliasing.
9892 The text will be rendered using Core Graphics text rendering which
9893 may anti-alias the text. */);
9894 Vmac_use_core_graphics = Qnil;
9896 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9897 doc: /* One of the Text Encoding Base constant values defined in the
9898 Basic Text Constants section of Inside Macintosh - Text Encoding
9899 Conversion Manager. Its value determines the encoding characters
9900 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9901 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9902 its default value, no conversion takes place. If it is set to
9903 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9904 characters typed on Mac keyboard are first converted into the
9905 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9906 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9907 command, this enables the Mac keyboard to be used to enter non-ASCII
9908 characters directly. */);
9909 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9912 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9913 (do not change this comment) */