*** empty log message ***
[emacs.git] / src / macterm.c
blob69c1840149c9d0da8acb63ab75e182d51fca1a14
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
31 #include "macterm.h"
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
37 #ifdef MAC_OSX
38 #undef mktime
39 #undef DEBUG
40 #undef free
41 #undef malloc
42 #undef realloc
43 /* Macros max and min defined in lisp.h conflict with those in
44 precompiled header Carbon.h. */
45 #undef max
46 #undef min
47 #undef init_process
48 #include <Carbon/Carbon.h>
49 #undef free
50 #define free unexec_free
51 #undef malloc
52 #define malloc unexec_malloc
53 #undef realloc
54 #define realloc unexec_realloc
55 #undef min
56 #define min(a, b) ((a) < (b) ? (a) : (b))
57 #undef max
58 #define max(a, b) ((a) > (b) ? (a) : (b))
59 #undef init_process
60 #define init_process emacs_init_process
61 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
62 obtain events from the event queue. If set to 0, WaitNextEvent is
63 used instead. */
64 #define USE_CARBON_EVENTS 1
65 #else /* not MAC_OSX */
66 #include <Quickdraw.h>
67 #include <ToolUtils.h>
68 #include <Sound.h>
69 #include <Events.h>
70 #include <Script.h>
71 #include <Resources.h>
72 #include <Fonts.h>
73 #include <TextUtils.h>
74 #include <LowMem.h>
75 #include <Controls.h>
76 #if defined (__MRC__) || (__MSL__ >= 0x6000)
77 #include <ControlDefinitions.h>
78 #endif
79 #include <Gestalt.h>
81 #if __profile__
82 #include <profiler.h>
83 #endif
84 #endif /* not MAC_OSX */
86 #include "systty.h"
87 #include "systime.h"
88 #include "atimer.h"
89 #include "keymap.h"
91 #include <ctype.h>
92 #include <errno.h>
93 #include <setjmp.h>
94 #include <sys/stat.h>
96 #include "keyboard.h"
97 #include "frame.h"
98 #include "dispextern.h"
99 #include "fontset.h"
100 #include "termhooks.h"
101 #include "termopts.h"
102 #include "termchar.h"
103 #include "gnu.h"
104 #include "disptab.h"
105 #include "buffer.h"
106 #include "window.h"
107 #include "intervals.h"
108 #include "composite.h"
109 #include "coding.h"
111 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
112 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
113 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
114 #define macShiftKey (shiftKey)
115 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
116 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
117 : controlKey)
118 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
122 /* Non-nil means Emacs uses toolkit scroll bars. */
124 Lisp_Object Vx_toolkit_scroll_bars;
126 /* Non-zero means that a HELP_EVENT has been generated since Emacs
127 start. */
129 static int any_help_event_p;
131 /* Non-zero means autoselect window with the mouse cursor. */
133 int x_autoselect_window_p;
135 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
137 int x_use_underline_position_properties;
139 /* Non-zero means draw block and hollow cursor as wide as the glyph
140 under it. For example, if a block cursor is over a tab, it will be
141 drawn as wide as that tab on the display. */
144 /* This is a chain of structures for all the X displays currently in
145 use. */
147 struct x_display_info *x_display_list;
149 /* This is a list of cons cells, each of the form (NAME
150 . FONT-LIST-CACHE), one for each element of x_display_list and in
151 the same order. NAME is the name of the frame. FONT-LIST-CACHE
152 records previous values returned by x-list-fonts. */
154 Lisp_Object x_display_name_list;
156 /* This is display since Mac does not support multiple ones. */
157 struct mac_display_info one_mac_display_info;
159 /* Frame being updated by update_frame. This is declared in term.c.
160 This is set by update_begin and looked at by all the XT functions.
161 It is zero while not inside an update. In that case, the XT
162 functions assume that `selected_frame' is the frame to apply to. */
164 extern struct frame *updating_frame;
166 extern int waiting_for_input;
168 /* This is a frame waiting to be auto-raised, within XTread_socket. */
170 struct frame *pending_autoraise_frame;
172 /* Non-zero means user is interacting with a toolkit scroll bar. */
174 static int toolkit_scroll_bar_interaction;
176 /* Mouse movement.
178 Formerly, we used PointerMotionHintMask (in standard_event_mask)
179 so that we would have to call XQueryPointer after each MotionNotify
180 event to ask for another such event. However, this made mouse tracking
181 slow, and there was a bug that made it eventually stop.
183 Simply asking for MotionNotify all the time seems to work better.
185 In order to avoid asking for motion events and then throwing most
186 of them away or busy-polling the server for mouse positions, we ask
187 the server for pointer motion hints. This means that we get only
188 one event per group of mouse movements. "Groups" are delimited by
189 other kinds of events (focus changes and button clicks, for
190 example), or by XQueryPointer calls; when one of these happens, we
191 get another MotionNotify event the next time the mouse moves. This
192 is at least as efficient as getting motion events when mouse
193 tracking is on, and I suspect only negligibly worse when tracking
194 is off. */
196 /* Where the mouse was last time we reported a mouse event. */
198 static Rect last_mouse_glyph;
199 static Lisp_Object last_mouse_press_frame;
201 /* The scroll bar in which the last X motion event occurred.
203 If the last X motion event occurred in a scroll bar, we set this so
204 XTmouse_position can know whether to report a scroll bar motion or
205 an ordinary motion.
207 If the last X motion event didn't occur in a scroll bar, we set
208 this to Qnil, to tell XTmouse_position to return an ordinary motion
209 event. */
211 static Lisp_Object last_mouse_scroll_bar;
213 /* This is a hack. We would really prefer that XTmouse_position would
214 return the time associated with the position it returns, but there
215 doesn't seem to be any way to wrest the time-stamp from the server
216 along with the position query. So, we just keep track of the time
217 of the last movement we received, and return that in hopes that
218 it's somewhat accurate. */
220 static Time last_mouse_movement_time;
222 enum mouse_tracking_type {
223 mouse_tracking_none,
224 mouse_tracking_mouse_movement,
225 mouse_tracking_scroll_bar
228 enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
230 struct scroll_bar *tracked_scroll_bar = NULL;
232 /* Incremented by XTread_socket whenever it really tries to read
233 events. */
235 #ifdef __STDC__
236 static int volatile input_signal_count;
237 #else
238 static int input_signal_count;
239 #endif
241 /* Used locally within XTread_socket. */
243 static int x_noop_count;
245 /* Initial values of argv and argc. */
247 extern char **initial_argv;
248 extern int initial_argc;
250 extern Lisp_Object Vcommand_line_args, Vsystem_name;
252 /* Tells if a window manager is present or not. */
254 extern Lisp_Object Vx_no_window_manager;
256 extern int errno;
258 /* A mask of extra modifier bits to put into every keyboard char. */
260 extern int extra_keyboard_modifiers;
262 static Lisp_Object Qvendor_specific_keysyms;
264 #if 0
265 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
266 #endif
268 extern int inhibit_window_system;
270 #if __MRC__
271 QDGlobals qd; /* QuickDraw global information structure. */
272 #endif
275 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
276 struct mac_display_info *mac_display_info_for_display (Display *);
277 static void x_update_window_end P_ ((struct window *, int, int));
278 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
279 static int x_io_error_quitter P_ ((Display *));
280 int x_catch_errors P_ ((Display *));
281 void x_uncatch_errors P_ ((Display *, int));
282 void x_lower_frame P_ ((struct frame *));
283 void x_scroll_bar_clear P_ ((struct frame *));
284 int x_had_errors_p P_ ((Display *));
285 void x_wm_set_size_hint P_ ((struct frame *, long, int));
286 void x_raise_frame P_ ((struct frame *));
287 void x_set_window_size P_ ((struct frame *, int, int, int));
288 void x_wm_set_window_state P_ ((struct frame *, int));
289 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
290 void mac_initialize P_ ((void));
291 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
292 static int x_compute_min_glyph_bounds P_ ((struct frame *));
293 static void x_update_end P_ ((struct frame *));
294 static void XTframe_up_to_date P_ ((struct frame *));
295 static void XTreassert_line_highlight P_ ((int, int));
296 static void x_change_line_highlight P_ ((int, int, int, int));
297 static void XTset_terminal_modes P_ ((void));
298 static void XTreset_terminal_modes P_ ((void));
299 static void x_clear_frame P_ ((void));
300 static void frame_highlight P_ ((struct frame *));
301 static void frame_unhighlight P_ ((struct frame *));
302 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
303 static void XTframe_rehighlight P_ ((struct frame *));
304 static void x_frame_rehighlight P_ ((struct x_display_info *));
305 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
306 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
307 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
308 static void x_flush P_ ((struct frame *f));
309 static void x_update_begin P_ ((struct frame *));
310 static void x_update_window_begin P_ ((struct window *));
311 static void x_after_update_window_line P_ ((struct glyph_row *));
313 void activate_scroll_bars (FRAME_PTR);
314 void deactivate_scroll_bars (FRAME_PTR);
316 static int is_emacs_window (WindowPtr);
318 extern int image_ascent (struct image *, struct face *);
319 int x_bitmap_icon (struct frame *, Lisp_Object);
320 void x_make_frame_visible (struct frame *);
322 extern void window_scroll (Lisp_Object, int, int, int);
324 /* Defined in macmenu.h. */
325 extern void menubar_selection_callback (FRAME_PTR, int);
326 extern void set_frame_menubar (FRAME_PTR, int, int);
328 /* X display function emulation */
330 static void
331 XFreePixmap (display, pixmap)
332 Display *display;
333 Pixmap pixmap;
335 PixMap *p = (PixMap *) pixmap;
337 xfree (p->baseAddr);
338 xfree (p);
342 /* Set foreground color for subsequent QuickDraw commands. Assume
343 graphic port has already been set. */
345 static void
346 mac_set_forecolor (unsigned long color)
348 RGBColor fg_color;
350 fg_color.red = RED_FROM_ULONG (color) * 256;
351 fg_color.green = GREEN_FROM_ULONG (color) * 256;
352 fg_color.blue = BLUE_FROM_ULONG (color) * 256;
354 RGBForeColor (&fg_color);
358 /* Set background color for subsequent QuickDraw commands. Assume
359 graphic port has already been set. */
361 static void
362 mac_set_backcolor (unsigned long color)
364 RGBColor bg_color;
366 bg_color.red = RED_FROM_ULONG (color) * 256;
367 bg_color.green = GREEN_FROM_ULONG (color) * 256;
368 bg_color.blue = BLUE_FROM_ULONG (color) * 256;
370 RGBBackColor (&bg_color);
373 /* Set foreground and background color for subsequent QuickDraw
374 commands. Assume that the graphic port has already been set. */
376 static void
377 mac_set_colors (GC gc)
379 mac_set_forecolor (gc->foreground);
380 mac_set_backcolor (gc->background);
383 /* Mac version of XDrawLine. */
385 static void
386 XDrawLine (display, w, gc, x1, y1, x2, y2)
387 Display *display;
388 WindowPtr w;
389 GC gc;
390 int x1, y1, x2, y2;
392 #if TARGET_API_MAC_CARBON
393 SetPort (GetWindowPort (w));
394 #else
395 SetPort (w);
396 #endif
398 mac_set_colors (gc);
400 MoveTo (x1, y1);
401 LineTo (x2, y2);
404 /* Mac version of XClearArea. */
406 void
407 XClearArea (display, w, x, y, width, height, exposures)
408 Display *display;
409 WindowPtr w;
410 int x, y;
411 unsigned int width, height;
412 int exposures;
414 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
415 Rect r;
416 XGCValues xgc;
418 xgc.foreground = mwp->x_compatible.foreground_pixel;
419 xgc.background = mwp->x_compatible.background_pixel;
421 #if TARGET_API_MAC_CARBON
422 SetPort (GetWindowPort (w));
423 #else
424 SetPort (w);
425 #endif
427 mac_set_colors (&xgc);
428 SetRect (&r, x, y, x + width, y + height);
430 EraseRect (&r);
433 /* Mac version of XClearWindow. */
435 static void
436 XClearWindow (display, w)
437 Display *display;
438 WindowPtr w;
440 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
441 XGCValues xgc;
443 xgc.foreground = mwp->x_compatible.foreground_pixel;
444 xgc.background = mwp->x_compatible.background_pixel;
446 #if TARGET_API_MAC_CARBON
447 SetPort (GetWindowPort (w));
448 #else
449 SetPort (w);
450 #endif
452 mac_set_colors (&xgc);
454 #if TARGET_API_MAC_CARBON
456 Rect r;
458 GetWindowPortBounds (w, &r);
459 EraseRect (&r);
461 #else /* not TARGET_API_MAC_CARBON */
462 EraseRect (&(w->portRect));
463 #endif /* not TARGET_API_MAC_CARBON */
467 /* Mac replacement for XCopyArea. */
469 static void
470 mac_draw_bitmap (display, w, gc, x, y, bitmap)
471 Display *display;
472 WindowPtr w;
473 GC gc;
474 int x, y;
475 BitMap *bitmap;
477 Rect r;
479 #if TARGET_API_MAC_CARBON
480 SetPort (GetWindowPort (w));
481 #else
482 SetPort (w);
483 #endif
485 mac_set_colors (gc);
486 SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
488 #if TARGET_API_MAC_CARBON
490 PixMapHandle pmh;
492 LockPortBits (GetWindowPort (w));
493 pmh = GetPortPixMap (GetWindowPort (w));
494 CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
495 UnlockPortBits (GetWindowPort (w));
497 #else /* not TARGET_API_MAC_CARBON */
498 CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
499 #endif /* not TARGET_API_MAC_CARBON */
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 #if TARGET_API_MAC_CARBON
512 SetPort (GetWindowPort (w));
513 #else
514 SetPort (w);
515 #endif
517 ClipRect (r);
521 /* Mac replacement for XSetClipMask. */
523 static void
524 mac_reset_clipping (display, w)
525 Display *display;
526 WindowPtr w;
528 Rect r;
530 #if TARGET_API_MAC_CARBON
531 SetPort (GetWindowPort (w));
532 #else
533 SetPort (w);
534 #endif
536 SetRect (&r, -32767, -32767, 32767, 32767);
537 ClipRect (&r);
541 /* Mac replacement for XCreateBitmapFromBitmapData. */
543 static void
544 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
545 BitMap *bitmap;
546 char *bits;
547 int w, h;
549 int bytes_per_row, i, j;
551 bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
552 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
553 if (!bitmap->baseAddr)
554 abort ();
556 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
557 for (i = 0; i < h; i++)
558 for (j = 0; j < w; j++)
559 if (BitTst (bits, i * w + j))
560 BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
562 SetRect (&(bitmap->bounds), 0, 0, w, h);
566 static void
567 mac_free_bitmap (bitmap)
568 BitMap *bitmap;
570 xfree (bitmap->baseAddr);
573 /* Mac replacement for XFillRectangle. */
575 static void
576 XFillRectangle (display, w, gc, x, y, width, height)
577 Display *display;
578 WindowPtr w;
579 GC gc;
580 int x, y;
581 unsigned int width, height;
583 Rect r;
585 #if TARGET_API_MAC_CARBON
586 SetPort (GetWindowPort (w));
587 #else
588 SetPort (w);
589 #endif
591 mac_set_colors (gc);
592 SetRect (&r, x, y, x + width, y + height);
594 PaintRect (&r); /* using foreground color of gc */
598 /* Mac replacement for XDrawRectangle: dest is a window. */
600 static void
601 mac_draw_rectangle (display, w, gc, x, y, width, height)
602 Display *display;
603 WindowPtr w;
604 GC gc;
605 int x, y;
606 unsigned int width, height;
608 Rect r;
610 #if TARGET_API_MAC_CARBON
611 SetPort (GetWindowPort (w));
612 #else
613 SetPort (w);
614 #endif
616 mac_set_colors (gc);
617 SetRect (&r, x, y, x + width + 1, y + height + 1);
619 FrameRect (&r); /* using foreground color of gc */
623 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
625 static void
626 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
627 Display *display;
628 Pixmap p;
629 GC gc;
630 int x, y;
631 unsigned int width, height;
633 #if 0 /* MAC_TODO: draw a rectangle in a PixMap */
634 Rect r;
636 #if TARGET_API_MAC_CARBON
637 SetPort (GetWindowPort (w));
638 #else
639 SetPort (w);
640 #endif
642 mac_set_colors (gc);
643 SetRect (&r, x, y, x + width, y + height);
645 FrameRect (&r); /* using foreground color of gc */
646 #endif /* 0 */
650 static void
651 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
652 bytes_per_char)
653 Display *display;
654 WindowPtr w;
655 GC gc;
656 int x, y;
657 char *buf;
658 int nchars, mode, bytes_per_char;
660 #if TARGET_API_MAC_CARBON
661 SetPort (GetWindowPort (w));
662 #else
663 SetPort (w);
664 #endif
666 mac_set_colors (gc);
668 TextFont (gc->font->mac_fontnum);
669 TextSize (gc->font->mac_fontsize);
670 TextFace (gc->font->mac_fontface);
671 TextMode (mode);
673 MoveTo (x, y);
674 DrawText (buf, 0, nchars * bytes_per_char);
678 /* Mac replacement for XDrawString. */
680 static void
681 XDrawString (display, w, gc, x, y, buf, nchars)
682 Display *display;
683 WindowPtr w;
684 GC gc;
685 int x, y;
686 char *buf;
687 int nchars;
689 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
693 /* Mac replacement for XDrawString16. */
695 static void
696 XDrawString16 (display, w, gc, x, y, buf, nchars)
697 Display *display;
698 WindowPtr w;
699 GC gc;
700 int x, y;
701 XChar2b *buf;
702 int nchars;
704 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
709 /* Mac replacement for XDrawImageString. */
711 static void
712 XDrawImageString (display, w, gc, x, y, buf, nchars)
713 Display *display;
714 WindowPtr w;
715 GC gc;
716 int x, y;
717 char *buf;
718 int nchars;
720 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
724 /* Mac replacement for XDrawString16. */
726 static void
727 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
728 Display *display;
729 WindowPtr w;
730 GC gc;
731 int x, y;
732 XChar2b *buf;
733 int nchars;
735 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
740 /* Mac replacement for XCopyArea: dest must be window. */
742 static void
743 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
744 dest_y)
745 Display *display;
746 Pixmap src;
747 WindowPtr dest;
748 GC gc;
749 int src_x, src_y;
750 unsigned int width, height;
751 int dest_x, dest_y;
753 Rect src_r, dest_r;
755 #if TARGET_API_MAC_CARBON
756 SetPort (GetWindowPort (dest));
757 #else
758 SetPort (dest);
759 #endif
761 mac_set_colors (gc);
763 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
764 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
766 #if TARGET_API_MAC_CARBON
768 PixMapHandle pmh;
770 LockPortBits (GetWindowPort (dest));
771 pmh = GetPortPixMap (GetWindowPort (dest));
772 CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
773 UnlockPortBits (GetWindowPort (dest));
775 #else /* not TARGET_API_MAC_CARBON */
776 CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
777 #endif /* not TARGET_API_MAC_CARBON */
781 #if 0
782 /* Convert a pair of local coordinates to global (screen) coordinates.
783 Assume graphic port has been properly set. */
784 static void
785 local_to_global_coord (short *h, short *v)
787 Point p;
789 p.h = *h;
790 p.v = *v;
792 LocalToGlobal (&p);
794 *h = p.h;
795 *v = p.v;
797 #endif
799 /* Mac replacement for XCopyArea: used only for scrolling. */
801 static void
802 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
803 Display *display;
804 WindowPtr w;
805 GC gc;
806 int src_x, src_y;
807 unsigned int width, height;
808 int dest_x, dest_y;
810 #if TARGET_API_MAC_CARBON
811 Rect gw_r, src_r, dest_r;
812 PixMapHandle pmh;
814 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
815 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
817 SetPort (GetWindowPort (w));
819 ForeColor (blackColor);
820 BackColor (whiteColor);
822 LockPortBits (GetWindowPort (w));
823 pmh = GetPortPixMap (GetWindowPort (w));
824 CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
825 UnlockPortBits (GetWindowPort (w));
827 mac_set_colors (gc);
828 #else /* not TARGET_API_MAC_CARBON */
829 Rect src_r, dest_r;
831 SetPort (w);
832 #if 0
833 mac_set_colors (gc);
834 #endif
836 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
837 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
839 #if 0
840 /* Need to use global coordinates and screenBits since src and dest
841 areas overlap in general. */
842 local_to_global_coord (&src_r.left, &src_r.top);
843 local_to_global_coord (&src_r.right, &src_r.bottom);
844 local_to_global_coord (&dest_r.left, &dest_r.top);
845 local_to_global_coord (&dest_r.right, &dest_r.bottom);
847 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
848 #else
849 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
850 color mapping in CopyBits. Otherwise, it will be slow. */
851 ForeColor (blackColor);
852 BackColor (whiteColor);
853 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
855 mac_set_colors (gc);
856 #endif
857 #endif /* not TARGET_API_MAC_CARBON */
861 /* Mac replacement for XCopyArea: dest must be Pixmap. */
863 static void
864 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
865 dest_x, dest_y)
866 Display *display;
867 Pixmap src;
868 Pixmap dest;
869 GC gc;
870 int src_x, src_y;
871 unsigned int width, height;
872 int dest_x, dest_y;
874 Rect src_r, dest_r;
875 int src_right = ((PixMap *) src)->bounds.right;
876 int src_bottom = ((PixMap *) src)->bounds.bottom;
877 int w = src_right - src_x;
878 int h = src_bottom - src_y;
880 mac_set_colors (gc);
882 SetRect (&src_r, src_x, src_y, src_right, src_bottom);
883 SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
885 CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
889 /* Mac replacement for XChangeGC. */
891 static void
892 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
893 XGCValues *xgcv)
895 if (mask & GCForeground)
896 gc->foreground = xgcv->foreground;
897 if (mask & GCBackground)
898 gc->background = xgcv->background;
899 if (mask & GCFont)
900 gc->font = xgcv->font;
904 /* Mac replacement for XCreateGC. */
906 XGCValues *
907 XCreateGC (void * ignore, Window window, unsigned long mask,
908 XGCValues *xgcv)
910 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
911 bzero (gc, sizeof (XGCValues));
913 XChangeGC (ignore, gc, mask, xgcv);
915 return gc;
919 /* Used in xfaces.c. */
921 void
922 XFreeGC (display, gc)
923 Display *display;
924 GC gc;
926 xfree (gc);
930 /* Mac replacement for XGetGCValues. */
932 static void
933 XGetGCValues (void* ignore, XGCValues *gc,
934 unsigned long mask, XGCValues *xgcv)
936 XChangeGC (ignore, xgcv, mask, gc);
940 /* Mac replacement for XSetForeground. */
942 static void
943 XSetForeground (display, gc, color)
944 Display *display;
945 GC gc;
946 unsigned long color;
948 gc->foreground = color;
952 /* Mac replacement for XSetFont. */
954 static void
955 XSetFont (display, gc, font)
956 Display *display;
957 GC gc;
958 XFontStruct *font;
960 gc->font = font;
964 static void
965 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
966 int *direction,int *font_ascent,
967 int *font_descent, XCharStruct *cs)
969 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
973 /* x_sync is a no-op on Mac. */
974 void
975 x_sync (f)
976 void *f;
981 /* Remove calls to XFlush by defining XFlush to an empty replacement.
982 Calls to XFlush should be unnecessary because the X output buffer
983 is flushed automatically as needed by calls to XPending,
984 XNextEvent, or XWindowEvent according to the XFlush man page.
985 XTread_socket calls XPending. Removing XFlush improves
986 performance. */
988 #if TARGET_API_MAC_CARBON
989 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
990 #else
991 #define XFlush(DISPLAY) (void) 0
992 #endif
994 /* Flush display of frame F, or of all frames if F is null. */
996 void
997 x_flush (f)
998 struct frame *f;
1000 #if TARGET_API_MAC_CARBON
1001 BLOCK_INPUT;
1002 if (f == NULL)
1004 Lisp_Object rest, frame;
1005 FOR_EACH_FRAME (rest, frame)
1006 x_flush (XFRAME (frame));
1008 else if (FRAME_X_P (f))
1009 XFlush (FRAME_MAC_DISPLAY (f));
1010 UNBLOCK_INPUT;
1011 #endif /* TARGET_API_MAC_CARBON */
1016 /* Return the struct mac_display_info corresponding to DPY. There's
1017 only one. */
1019 struct mac_display_info *
1020 mac_display_info_for_display (dpy)
1021 Display *dpy;
1023 return &one_mac_display_info;
1028 /***********************************************************************
1029 Starting and ending an update
1030 ***********************************************************************/
1032 /* Start an update of frame F. This function is installed as a hook
1033 for update_begin, i.e. it is called when update_begin is called.
1034 This function is called prior to calls to x_update_window_begin for
1035 each window being updated. */
1037 static void
1038 x_update_begin (f)
1039 struct frame *f;
1041 /* Nothing to do. */
1045 /* Start update of window W. Set the global variable updated_window
1046 to the window being updated and set output_cursor to the cursor
1047 position of W. */
1049 static void
1050 x_update_window_begin (w)
1051 struct window *w;
1053 struct frame *f = XFRAME (WINDOW_FRAME (w));
1054 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1056 updated_window = w;
1057 set_output_cursor (&w->cursor);
1059 BLOCK_INPUT;
1061 if (f == display_info->mouse_face_mouse_frame)
1063 /* Don't do highlighting for mouse motion during the update. */
1064 display_info->mouse_face_defer = 1;
1066 /* If F needs to be redrawn, simply forget about any prior mouse
1067 highlighting. */
1068 if (FRAME_GARBAGED_P (f))
1069 display_info->mouse_face_window = Qnil;
1071 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1072 their mouse_face_p flag set, which means that they are always
1073 unequal to rows in a desired matrix which never have that
1074 flag set. So, rows containing mouse-face glyphs are never
1075 scrolled, and we don't have to switch the mouse highlight off
1076 here to prevent it from being scrolled. */
1078 /* Can we tell that this update does not affect the window
1079 where the mouse highlight is? If so, no need to turn off.
1080 Likewise, don't do anything if the frame is garbaged;
1081 in that case, the frame's current matrix that we would use
1082 is all wrong, and we will redisplay that line anyway. */
1083 if (!NILP (display_info->mouse_face_window)
1084 && w == XWINDOW (display_info->mouse_face_window))
1086 int i;
1088 for (i = 0; i < w->desired_matrix->nrows; ++i)
1089 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1090 break;
1092 if (i < w->desired_matrix->nrows)
1093 clear_mouse_face (display_info);
1095 #endif /* 0 */
1098 UNBLOCK_INPUT;
1102 /* Draw a vertical window border from (x,y0) to (x,y1) */
1104 static void
1105 mac_draw_vertical_window_border (w, x, y0, y1)
1106 struct window *w;
1107 int x, y0, y1;
1109 struct frame *f = XFRAME (WINDOW_FRAME (w));
1111 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1112 f->output_data.mac->normal_gc, x, y0, x, y1);
1116 /* End update of window W (which is equal to updated_window).
1118 Draw vertical borders between horizontally adjacent windows, and
1119 display W's cursor if CURSOR_ON_P is non-zero.
1121 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1122 glyphs in mouse-face were overwritten. In that case we have to
1123 make sure that the mouse-highlight is properly redrawn.
1125 W may be a menu bar pseudo-window in case we don't have X toolkit
1126 support. Such windows don't have a cursor, so don't display it
1127 here. */
1129 static void
1130 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1131 struct window *w;
1132 int cursor_on_p, mouse_face_overwritten_p;
1134 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1136 if (!w->pseudo_window_p)
1138 BLOCK_INPUT;
1140 if (cursor_on_p)
1141 display_and_set_cursor (w, 1, output_cursor.hpos,
1142 output_cursor.vpos,
1143 output_cursor.x, output_cursor.y);
1145 x_draw_vertical_border (w);
1147 draw_window_fringes (w);
1149 UNBLOCK_INPUT;
1152 /* If a row with mouse-face was overwritten, arrange for
1153 XTframe_up_to_date to redisplay the mouse highlight. */
1154 if (mouse_face_overwritten_p)
1156 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1157 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1158 dpyinfo->mouse_face_window = Qnil;
1161 #if 0
1162 /* Unhide the caret. This won't actually show the cursor, unless it
1163 was visible before the corresponding call to HideCaret in
1164 x_update_window_begin. */
1165 if (w32_use_visible_system_caret)
1166 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1167 #endif
1169 updated_window = NULL;
1173 /* End update of frame F. This function is installed as a hook in
1174 update_end. */
1176 static void
1177 x_update_end (f)
1178 struct frame *f;
1180 /* Reset the background color of Mac OS Window to that of the frame after
1181 update so that it is used by Mac Toolbox to clear the update region before
1182 an update event is generated. */
1183 #if TARGET_API_MAC_CARBON
1184 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1185 #else
1186 SetPort (FRAME_MAC_WINDOW (f));
1187 #endif
1189 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1191 /* Mouse highlight may be displayed again. */
1192 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1194 BLOCK_INPUT;
1195 XFlush (FRAME_MAC_DISPLAY (f));
1196 UNBLOCK_INPUT;
1200 /* This function is called from various places in xdisp.c whenever a
1201 complete update has been performed. The global variable
1202 updated_window is not available here. */
1204 static void
1205 XTframe_up_to_date (f)
1206 struct frame *f;
1208 if (FRAME_X_P (f))
1210 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1212 if (dpyinfo->mouse_face_deferred_gc
1213 || f == dpyinfo->mouse_face_mouse_frame)
1215 BLOCK_INPUT;
1216 if (dpyinfo->mouse_face_mouse_frame)
1217 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1218 dpyinfo->mouse_face_mouse_x,
1219 dpyinfo->mouse_face_mouse_y);
1220 dpyinfo->mouse_face_deferred_gc = 0;
1221 UNBLOCK_INPUT;
1227 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1228 arrow bitmaps, or clear the fringes if no bitmaps are required
1229 before DESIRED_ROW is made current. The window being updated is
1230 found in updated_window. This function is called from
1231 update_window_line only if it is known that there are differences
1232 between bitmaps to be drawn between current row and DESIRED_ROW. */
1234 static void
1235 x_after_update_window_line (desired_row)
1236 struct glyph_row *desired_row;
1238 struct window *w = updated_window;
1239 struct frame *f;
1240 int width, height;
1242 xassert (w);
1244 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1245 desired_row->redraw_fringe_bitmaps_p = 1;
1247 /* When a window has disappeared, make sure that no rest of
1248 full-width rows stays visible in the internal border. Could
1249 check here if updated_window is the leftmost/rightmost window,
1250 but I guess it's not worth doing since vertically split windows
1251 are almost never used, internal border is rarely set, and the
1252 overhead is very small. */
1253 if (windows_or_buffers_changed
1254 && desired_row->full_width_p
1255 && (f = XFRAME (w->frame),
1256 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1257 width != 0)
1258 && (height = desired_row->visible_height,
1259 height > 0))
1261 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1262 /* Internal border is drawn below the tool bar. */
1263 if (WINDOWP (f->tool_bar_window)
1264 && w == XWINDOW (f->tool_bar_window))
1265 y -= width;
1267 BLOCK_INPUT;
1269 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1270 0, y, width, height, 0);
1271 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1272 FRAME_PIXEL_WIDTH (f) - width, y,
1273 width, height, 0);
1275 UNBLOCK_INPUT;
1280 /* Draw the bitmap WHICH in one of the left or right fringes of
1281 window W. ROW is the glyph row for which to display the bitmap; it
1282 determines the vertical position at which the bitmap has to be
1283 drawn. */
1285 static void
1286 x_draw_fringe_bitmap (w, row, p)
1287 struct window *w;
1288 struct glyph_row *row;
1289 struct draw_fringe_bitmap_params *p;
1291 struct frame *f = XFRAME (WINDOW_FRAME (w));
1292 Display *display = FRAME_MAC_DISPLAY (f);
1293 WindowPtr window = FRAME_MAC_WINDOW (f);
1294 XGCValues gcv;
1295 GC gc = f->output_data.mac->normal_gc;
1296 struct face *face = p->face;
1297 int rowY;
1299 /* Must clip because of partially visible lines. */
1300 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1301 if (p->y < rowY)
1303 /* Adjust position of "bottom aligned" bitmap on partially
1304 visible last row. */
1305 int oldY = row->y;
1306 int oldVH = row->visible_height;
1307 row->visible_height = p->h;
1308 row->y -= rowY - p->y;
1309 x_clip_to_row (w, row, gc);
1310 row->y = oldY;
1311 row->visible_height = oldVH;
1313 else
1314 x_clip_to_row (w, row, gc);
1316 if (p->bx >= 0)
1318 XGCValues gcv;
1319 gcv.foreground = face->background;
1321 #if 0 /* MAC_TODO: stipple */
1322 /* In case the same realized face is used for fringes and
1323 for something displayed in the text (e.g. face `region' on
1324 mono-displays, the fill style may have been changed to
1325 FillSolid in x_draw_glyph_string_background. */
1326 if (face->stipple)
1327 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1328 else
1329 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1330 #endif
1332 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1333 &gcv,
1334 p->bx, p->by, p->nx, p->ny);
1336 #if 0 /* MAC_TODO: stipple */
1337 if (!face->stipple)
1338 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1339 #endif
1342 if (p->which != NO_FRINGE_BITMAP)
1344 unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
1345 BitMap bitmap;
1347 mac_create_bitmap_from_bitmap_data (&bitmap, bits, p->wd, p->h);
1348 gcv.foreground = face->foreground;
1349 gcv.background = face->background;
1351 mac_draw_bitmap (display, window, &gcv, p->x, p->y, &bitmap);
1353 mac_free_bitmap (&bitmap);
1356 mac_reset_clipping (display, window);
1360 /* This is called when starting Emacs and when restarting after
1361 suspend. When starting Emacs, no window is mapped. And nothing
1362 must be done to Emacs's own window if it is suspended (though that
1363 rarely happens). */
1365 static void
1366 XTset_terminal_modes ()
1370 /* This is called when exiting or suspending Emacs. Exiting will make
1371 the windows go away, and suspending requires no action. */
1373 static void
1374 XTreset_terminal_modes ()
1379 /***********************************************************************
1380 Display Iterator
1381 ***********************************************************************/
1383 /* Function prototypes of this page. */
1385 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1386 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1389 /* Return a pointer to per-char metric information in FONT of a
1390 character pointed by B which is a pointer to an XChar2b. */
1392 #define PER_CHAR_METRIC(font, b) \
1393 ((font)->per_char \
1394 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1395 + (((font)->min_byte1 || (font)->max_byte1) \
1396 ? (((b)->byte1 - (font)->min_byte1) \
1397 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1398 : 0)) \
1399 : &((font)->max_bounds))
1402 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1403 is not contained in the font. */
1405 static INLINE XCharStruct *
1406 x_per_char_metric (font, char2b)
1407 XFontStruct *font;
1408 XChar2b *char2b;
1410 /* The result metric information. */
1411 XCharStruct *pcm = NULL;
1413 xassert (font && char2b);
1415 if (font->per_char != NULL)
1417 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1419 /* min_char_or_byte2 specifies the linear character index
1420 corresponding to the first element of the per_char array,
1421 max_char_or_byte2 is the index of the last character. A
1422 character with non-zero CHAR2B->byte1 is not in the font.
1423 A character with byte2 less than min_char_or_byte2 or
1424 greater max_char_or_byte2 is not in the font. */
1425 if (char2b->byte1 == 0
1426 && char2b->byte2 >= font->min_char_or_byte2
1427 && char2b->byte2 <= font->max_char_or_byte2)
1428 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1430 else
1432 /* If either min_byte1 or max_byte1 are nonzero, both
1433 min_char_or_byte2 and max_char_or_byte2 are less than
1434 256, and the 2-byte character index values corresponding
1435 to the per_char array element N (counting from 0) are:
1437 byte1 = N/D + min_byte1
1438 byte2 = N\D + min_char_or_byte2
1440 where:
1442 D = max_char_or_byte2 - min_char_or_byte2 + 1
1443 / = integer division
1444 \ = integer modulus */
1445 if (char2b->byte1 >= font->min_byte1
1446 && char2b->byte1 <= font->max_byte1
1447 && char2b->byte2 >= font->min_char_or_byte2
1448 && char2b->byte2 <= font->max_char_or_byte2)
1450 pcm = (font->per_char
1451 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1452 * (char2b->byte1 - font->min_byte1))
1453 + (char2b->byte2 - font->min_char_or_byte2));
1457 else
1459 /* If the per_char pointer is null, all glyphs between the first
1460 and last character indexes inclusive have the same
1461 information, as given by both min_bounds and max_bounds. */
1462 if (char2b->byte2 >= font->min_char_or_byte2
1463 && char2b->byte2 <= font->max_char_or_byte2)
1464 pcm = &font->max_bounds;
1467 return ((pcm == NULL
1468 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1469 ? NULL : pcm);
1472 /* RIF:
1475 static XCharStruct *
1476 mac_per_char_metric (font, char2b, font_type)
1477 XFontStruct *font;
1478 XChar2b *char2b;
1479 int font_type;
1481 return x_per_char_metric (font, char2b);
1484 /* RIF:
1485 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1486 the two-byte form of C. Encoding is returned in *CHAR2B. */
1488 static int
1489 mac_encode_char (c, char2b, font_info, two_byte_p)
1490 int c;
1491 XChar2b *char2b;
1492 struct font_info *font_info;
1493 int *two_byte_p;
1495 int charset = CHAR_CHARSET (c);
1496 XFontStruct *font = font_info->font;
1498 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1499 This may be either a program in a special encoder language or a
1500 fixed encoding. */
1501 if (font_info->font_encoder)
1503 /* It's a program. */
1504 struct ccl_program *ccl = font_info->font_encoder;
1506 if (CHARSET_DIMENSION (charset) == 1)
1508 ccl->reg[0] = charset;
1509 ccl->reg[1] = char2b->byte2;
1511 else
1513 ccl->reg[0] = charset;
1514 ccl->reg[1] = char2b->byte1;
1515 ccl->reg[2] = char2b->byte2;
1518 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1520 /* We assume that MSBs are appropriately set/reset by CCL
1521 program. */
1522 if (font->max_byte1 == 0) /* 1-byte font */
1523 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1524 else
1525 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1527 else if (font_info->encoding[charset])
1529 /* Fixed encoding scheme. See fontset.h for the meaning of the
1530 encoding numbers. */
1531 int enc = font_info->encoding[charset];
1533 if ((enc == 1 || enc == 2)
1534 && CHARSET_DIMENSION (charset) == 2)
1535 char2b->byte1 |= 0x80;
1537 if (enc == 1 || enc == 3)
1538 char2b->byte2 |= 0x80;
1540 if (enc == 4)
1542 int sjis1, sjis2;
1544 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1545 char2b->byte1 = sjis1;
1546 char2b->byte2 = sjis2;
1550 if (two_byte_p)
1551 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1553 return FONT_TYPE_UNKNOWN;
1558 /***********************************************************************
1559 Glyph display
1560 ***********************************************************************/
1563 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1564 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1565 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1566 int));
1567 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1568 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1569 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1570 static void x_draw_glyph_string P_ ((struct glyph_string *));
1571 static void x_set_cursor_gc P_ ((struct glyph_string *));
1572 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1573 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1574 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1575 unsigned long *, double, int));*/
1576 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1577 double, int, unsigned long));
1578 static void x_setup_relief_colors P_ ((struct glyph_string *));
1579 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1580 static void x_draw_image_relief P_ ((struct glyph_string *));
1581 static void x_draw_image_foreground P_ ((struct glyph_string *));
1582 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1583 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1584 int, int, int));
1585 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1586 int, int, int, int, Rect *));
1587 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1588 int, int, int, Rect *));
1590 #if GLYPH_DEBUG
1591 static void x_check_font P_ ((struct frame *, XFontStruct *));
1592 #endif
1595 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1596 face. */
1598 static void
1599 x_set_cursor_gc (s)
1600 struct glyph_string *s;
1602 if (s->font == FRAME_FONT (s->f)
1603 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1604 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1605 && !s->cmp)
1606 s->gc = s->f->output_data.mac->cursor_gc;
1607 else
1609 /* Cursor on non-default face: must merge. */
1610 XGCValues xgcv;
1611 unsigned long mask;
1613 xgcv.background = s->f->output_data.mac->cursor_pixel;
1614 xgcv.foreground = s->face->background;
1616 /* If the glyph would be invisible, try a different foreground. */
1617 if (xgcv.foreground == xgcv.background)
1618 xgcv.foreground = s->face->foreground;
1619 if (xgcv.foreground == xgcv.background)
1620 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1621 if (xgcv.foreground == xgcv.background)
1622 xgcv.foreground = s->face->foreground;
1624 /* Make sure the cursor is distinct from text in this face. */
1625 if (xgcv.background == s->face->background
1626 && xgcv.foreground == s->face->foreground)
1628 xgcv.background = s->face->foreground;
1629 xgcv.foreground = s->face->background;
1632 IF_DEBUG (x_check_font (s->f, s->font));
1633 xgcv.font = s->font;
1634 mask = GCForeground | GCBackground | GCFont;
1636 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1637 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1638 mask, &xgcv);
1639 else
1640 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1641 = XCreateGC (s->display, s->window, mask, &xgcv);
1643 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1648 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1650 static void
1651 x_set_mouse_face_gc (s)
1652 struct glyph_string *s;
1654 int face_id;
1655 struct face *face;
1657 /* What face has to be used last for the mouse face? */
1658 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1659 face = FACE_FROM_ID (s->f, face_id);
1660 if (face == NULL)
1661 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1663 if (s->first_glyph->type == CHAR_GLYPH)
1664 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1665 else
1666 face_id = FACE_FOR_CHAR (s->f, face, 0);
1667 s->face = FACE_FROM_ID (s->f, face_id);
1668 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1670 /* If font in this face is same as S->font, use it. */
1671 if (s->font == s->face->font)
1672 s->gc = s->face->gc;
1673 else
1675 /* Otherwise construct scratch_cursor_gc with values from FACE
1676 but font FONT. */
1677 XGCValues xgcv;
1678 unsigned long mask;
1680 xgcv.background = s->face->background;
1681 xgcv.foreground = s->face->foreground;
1682 IF_DEBUG (x_check_font (s->f, s->font));
1683 xgcv.font = s->font;
1684 mask = GCForeground | GCBackground | GCFont;
1686 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1687 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1688 mask, &xgcv);
1689 else
1690 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1691 = XCreateGC (s->display, s->window, mask, &xgcv);
1693 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1696 xassert (s->gc != 0);
1700 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1701 Faces to use in the mode line have already been computed when the
1702 matrix was built, so there isn't much to do, here. */
1704 static INLINE void
1705 x_set_mode_line_face_gc (s)
1706 struct glyph_string *s;
1708 s->gc = s->face->gc;
1712 /* Set S->gc of glyph string S for drawing that glyph string. Set
1713 S->stippled_p to a non-zero value if the face of S has a stipple
1714 pattern. */
1716 static INLINE void
1717 x_set_glyph_string_gc (s)
1718 struct glyph_string *s;
1720 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1722 if (s->hl == DRAW_NORMAL_TEXT)
1724 s->gc = s->face->gc;
1725 s->stippled_p = s->face->stipple != 0;
1727 else if (s->hl == DRAW_INVERSE_VIDEO)
1729 x_set_mode_line_face_gc (s);
1730 s->stippled_p = s->face->stipple != 0;
1732 else if (s->hl == DRAW_CURSOR)
1734 x_set_cursor_gc (s);
1735 s->stippled_p = 0;
1737 else if (s->hl == DRAW_MOUSE_FACE)
1739 x_set_mouse_face_gc (s);
1740 s->stippled_p = s->face->stipple != 0;
1742 else if (s->hl == DRAW_IMAGE_RAISED
1743 || s->hl == DRAW_IMAGE_SUNKEN)
1745 s->gc = s->face->gc;
1746 s->stippled_p = s->face->stipple != 0;
1748 else
1750 s->gc = s->face->gc;
1751 s->stippled_p = s->face->stipple != 0;
1754 /* GC must have been set. */
1755 xassert (s->gc != 0);
1759 /* Set clipping for output of glyph string S. S may be part of a mode
1760 line or menu if we don't have X toolkit support. */
1762 static INLINE void
1763 x_set_glyph_string_clipping (s)
1764 struct glyph_string *s;
1766 Rect r;
1767 get_glyph_string_clip_rect (s, &r);
1768 mac_set_clip_rectangle (s->display, s->window, &r);
1772 /* RIF:
1773 Compute left and right overhang of glyph string S. If S is a glyph
1774 string for a composition, assume overhangs don't exist. */
1776 static void
1777 mac_compute_glyph_string_overhangs (s)
1778 struct glyph_string *s;
1780 #if 0
1781 /* MAC_TODO: XTextExtents16 does nothing yet... */
1783 if (s->cmp == NULL
1784 && s->first_glyph->type == CHAR_GLYPH)
1786 XCharStruct cs;
1787 int direction, font_ascent, font_descent;
1788 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
1789 &font_ascent, &font_descent, &cs);
1790 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
1791 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
1793 #endif
1797 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1799 static INLINE void
1800 x_clear_glyph_string_rect (s, x, y, w, h)
1801 struct glyph_string *s;
1802 int x, y, w, h;
1804 XGCValues xgcv;
1806 xgcv.foreground = s->gc->background;
1807 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
1811 /* Draw the background of glyph_string S. If S->background_filled_p
1812 is non-zero don't draw it. FORCE_P non-zero means draw the
1813 background even if it wouldn't be drawn normally. This is used
1814 when a string preceding S draws into the background of S, or S
1815 contains the first component of a composition. */
1817 static void
1818 x_draw_glyph_string_background (s, force_p)
1819 struct glyph_string *s;
1820 int force_p;
1822 /* Nothing to do if background has already been drawn or if it
1823 shouldn't be drawn in the first place. */
1824 if (!s->background_filled_p)
1826 int box_line_width = max (s->face->box_line_width, 0);
1828 #if 0 /* MAC_TODO: stipple */
1829 if (s->stippled_p)
1831 /* Fill background with a stipple pattern. */
1832 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1833 XFillRectangle (s->display, s->window, s->gc, s->x,
1834 s->y + box_line_width,
1835 s->background_width,
1836 s->height - 2 * box_line_width);
1837 XSetFillStyle (s->display, s->gc, FillSolid);
1838 s->background_filled_p = 1;
1840 else
1841 #endif
1842 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1843 || s->font_not_found_p
1844 || s->extends_to_end_of_line_p
1845 || force_p)
1847 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1848 s->background_width,
1849 s->height - 2 * box_line_width);
1850 s->background_filled_p = 1;
1856 /* Draw the foreground of glyph string S. */
1858 static void
1859 x_draw_glyph_string_foreground (s)
1860 struct glyph_string *s;
1862 int i, x;
1864 /* If first glyph of S has a left box line, start drawing the text
1865 of S to the right of that box line. */
1866 if (s->face->box != FACE_NO_BOX
1867 && s->first_glyph->left_box_line_p)
1868 x = s->x + abs (s->face->box_line_width);
1869 else
1870 x = s->x;
1872 /* Draw characters of S as rectangles if S's font could not be
1873 loaded. */
1874 if (s->font_not_found_p)
1876 for (i = 0; i < s->nchars; ++i)
1878 struct glyph *g = s->first_glyph + i;
1879 mac_draw_rectangle (s->display, s->window,
1880 s->gc, x, s->y, g->pixel_width - 1,
1881 s->height - 1);
1882 x += g->pixel_width;
1885 else
1887 char *char1b = (char *) s->char2b;
1888 int boff = s->font_info->baseline_offset;
1890 if (s->font_info->vertical_centering)
1891 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
1893 /* If we can use 8-bit functions, condense S->char2b. */
1894 if (!s->two_byte_p)
1895 for (i = 0; i < s->nchars; ++i)
1896 char1b[i] = s->char2b[i].byte2;
1898 /* Draw text with XDrawString if background has already been
1899 filled. Otherwise, use XDrawImageString. (Note that
1900 XDrawImageString is usually faster than XDrawString.) Always
1901 use XDrawImageString when drawing the cursor so that there is
1902 no chance that characters under a box cursor are invisible. */
1903 if (s->for_overlaps_p
1904 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1906 /* Draw characters with 16-bit or 8-bit functions. */
1907 if (s->two_byte_p)
1908 XDrawString16 (s->display, s->window, s->gc, x,
1909 s->ybase - boff, s->char2b, s->nchars);
1910 else
1911 XDrawString (s->display, s->window, s->gc, x,
1912 s->ybase - boff, char1b, s->nchars);
1914 else
1916 if (s->two_byte_p)
1917 XDrawImageString16 (s->display, s->window, s->gc, x,
1918 s->ybase - boff, s->char2b, s->nchars);
1919 else
1920 XDrawImageString (s->display, s->window, s->gc, x,
1921 s->ybase - boff, char1b, s->nchars);
1926 /* Draw the foreground of composite glyph string S. */
1928 static void
1929 x_draw_composite_glyph_string_foreground (s)
1930 struct glyph_string *s;
1932 int i, x;
1934 /* If first glyph of S has a left box line, start drawing the text
1935 of S to the right of that box line. */
1936 if (s->face->box != FACE_NO_BOX
1937 && s->first_glyph->left_box_line_p)
1938 x = s->x + abs (s->face->box_line_width);
1939 else
1940 x = s->x;
1942 /* S is a glyph string for a composition. S->gidx is the index of
1943 the first character drawn for glyphs of this composition.
1944 S->gidx == 0 means we are drawing the very first character of
1945 this composition. */
1947 /* Draw a rectangle for the composition if the font for the very
1948 first character of the composition could not be loaded. */
1949 if (s->font_not_found_p)
1951 if (s->gidx == 0)
1952 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
1953 s->width - 1, s->height - 1);
1955 else
1957 for (i = 0; i < s->nchars; i++, ++s->gidx)
1958 XDrawString16 (s->display, s->window, s->gc,
1959 x + s->cmp->offsets[s->gidx * 2],
1960 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1961 s->char2b + i, 1);
1966 #ifdef USE_X_TOOLKIT
1968 static struct frame *x_frame_of_widget P_ ((Widget));
1971 /* Return the frame on which widget WIDGET is used.. Abort if frame
1972 cannot be determined. */
1974 static struct frame *
1975 x_frame_of_widget (widget)
1976 Widget widget;
1978 struct x_display_info *dpyinfo;
1979 Lisp_Object tail;
1980 struct frame *f;
1982 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1984 /* Find the top-level shell of the widget. Note that this function
1985 can be called when the widget is not yet realized, so XtWindow
1986 (widget) == 0. That's the reason we can't simply use
1987 x_any_window_to_frame. */
1988 while (!XtIsTopLevelShell (widget))
1989 widget = XtParent (widget);
1991 /* Look for a frame with that top-level widget. Allocate the color
1992 on that frame to get the right gamma correction value. */
1993 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
1994 if (GC_FRAMEP (XCAR (tail))
1995 && (f = XFRAME (XCAR (tail)),
1996 (f->output_data.nothing != 1
1997 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
1998 && f->output_data.x->widget == widget)
1999 return f;
2001 abort ();
2005 /* Allocate the color COLOR->pixel on the screen and display of
2006 widget WIDGET in colormap CMAP. If an exact match cannot be
2007 allocated, try the nearest color available. Value is non-zero
2008 if successful. This is called from lwlib. */
2011 x_alloc_nearest_color_for_widget (widget, cmap, color)
2012 Widget widget;
2013 Colormap cmap;
2014 XColor *color;
2016 struct frame *f = x_frame_of_widget (widget);
2017 return x_alloc_nearest_color (f, cmap, color);
2021 #endif /* USE_X_TOOLKIT */
2023 #if 0 /* MAC_TODO */
2025 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2026 CMAP. If an exact match can't be allocated, try the nearest color
2027 available. Value is non-zero if successful. Set *COLOR to the
2028 color allocated. */
2031 x_alloc_nearest_color (f, cmap, color)
2032 struct frame *f;
2033 Colormap cmap;
2034 XColor *color;
2036 Display *display = FRAME_X_DISPLAY (f);
2037 Screen *screen = FRAME_X_SCREEN (f);
2038 int rc;
2040 gamma_correct (f, color);
2041 rc = XAllocColor (display, cmap, color);
2042 if (rc == 0)
2044 /* If we got to this point, the colormap is full, so we're going
2045 to try to get the next closest color. The algorithm used is
2046 a least-squares matching, which is what X uses for closest
2047 color matching with StaticColor visuals. */
2048 int nearest, i;
2049 unsigned long nearest_delta = ~0;
2050 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2051 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2053 for (i = 0; i < ncells; ++i)
2054 cells[i].pixel = i;
2055 XQueryColors (display, cmap, cells, ncells);
2057 for (nearest = i = 0; i < ncells; ++i)
2059 long dred = (color->red >> 8) - (cells[i].red >> 8);
2060 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2061 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2062 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2064 if (delta < nearest_delta)
2066 nearest = i;
2067 nearest_delta = delta;
2071 color->red = cells[nearest].red;
2072 color->green = cells[nearest].green;
2073 color->blue = cells[nearest].blue;
2074 rc = XAllocColor (display, cmap, color);
2077 #ifdef DEBUG_X_COLORS
2078 if (rc)
2079 register_color (color->pixel);
2080 #endif /* DEBUG_X_COLORS */
2082 return rc;
2086 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2087 It's necessary to do this instead of just using PIXEL directly to
2088 get color reference counts right. */
2090 unsigned long
2091 x_copy_color (f, pixel)
2092 struct frame *f;
2093 unsigned long pixel;
2095 XColor color;
2097 color.pixel = pixel;
2098 BLOCK_INPUT;
2099 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2100 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2101 UNBLOCK_INPUT;
2102 #ifdef DEBUG_X_COLORS
2103 register_color (pixel);
2104 #endif
2105 return color.pixel;
2109 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2110 It's necessary to do this instead of just using PIXEL directly to
2111 get color reference counts right. */
2113 unsigned long
2114 x_copy_dpy_color (dpy, cmap, pixel)
2115 Display *dpy;
2116 Colormap cmap;
2117 unsigned long pixel;
2119 XColor color;
2121 color.pixel = pixel;
2122 BLOCK_INPUT;
2123 XQueryColor (dpy, cmap, &color);
2124 XAllocColor (dpy, cmap, &color);
2125 UNBLOCK_INPUT;
2126 #ifdef DEBUG_X_COLORS
2127 register_color (pixel);
2128 #endif
2129 return color.pixel;
2132 #endif /* MAC_TODO */
2134 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2135 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2136 If this produces the same color as COLOR, try a color where all RGB
2137 values have DELTA added. Return the allocated color in *COLOR.
2138 DISPLAY is the X display, CMAP is the colormap to operate on.
2139 Value is non-zero if successful. */
2141 static int
2142 mac_alloc_lighter_color (f, color, factor, delta)
2143 struct frame *f;
2144 unsigned long *color;
2145 double factor;
2146 int delta;
2148 unsigned long new;
2150 /* Change RGB values by specified FACTOR. Avoid overflow! */
2151 xassert (factor >= 0);
2152 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2153 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2154 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2155 if (new == *color)
2156 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2157 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2158 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2160 /* MAC_TODO: Map to palette and retry with delta if same? */
2161 /* MAC_TODO: Free colors (if using palette)? */
2163 if (new == *color)
2164 return 0;
2166 *color = new;
2168 return 1;
2172 /* Set up the foreground color for drawing relief lines of glyph
2173 string S. RELIEF is a pointer to a struct relief containing the GC
2174 with which lines will be drawn. Use a color that is FACTOR or
2175 DELTA lighter or darker than the relief's background which is found
2176 in S->f->output_data.x->relief_background. If such a color cannot
2177 be allocated, use DEFAULT_PIXEL, instead. */
2179 static void
2180 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2181 struct frame *f;
2182 struct relief *relief;
2183 double factor;
2184 int delta;
2185 unsigned long default_pixel;
2187 XGCValues xgcv;
2188 struct mac_output *di = f->output_data.mac;
2189 unsigned long mask = GCForeground;
2190 unsigned long pixel;
2191 unsigned long background = di->relief_background;
2192 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2194 /* MAC_TODO: Free colors (if using palette)? */
2196 /* Allocate new color. */
2197 xgcv.foreground = default_pixel;
2198 pixel = background;
2199 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
2201 relief->allocated_p = 1;
2202 xgcv.foreground = relief->pixel = pixel;
2205 if (relief->gc == 0)
2207 #if 0 /* MAC_TODO: stipple */
2208 xgcv.stipple = dpyinfo->gray;
2209 mask |= GCStipple;
2210 #endif
2211 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2213 else
2214 XChangeGC (NULL, relief->gc, mask, &xgcv);
2218 /* Set up colors for the relief lines around glyph string S. */
2220 static void
2221 x_setup_relief_colors (s)
2222 struct glyph_string *s;
2224 struct mac_output *di = s->f->output_data.mac;
2225 unsigned long color;
2227 if (s->face->use_box_color_for_shadows_p)
2228 color = s->face->box_color;
2229 else
2231 XGCValues xgcv;
2233 /* Get the background color of the face. */
2234 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2235 color = xgcv.background;
2238 if (di->white_relief.gc == 0
2239 || color != di->relief_background)
2241 di->relief_background = color;
2242 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2243 WHITE_PIX_DEFAULT (s->f));
2244 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2245 BLACK_PIX_DEFAULT (s->f));
2250 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2251 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2252 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2253 relief. LEFT_P non-zero means draw a relief on the left side of
2254 the rectangle. RIGHT_P non-zero means draw a relief on the right
2255 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2256 when drawing. */
2258 static void
2259 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2260 raised_p, left_p, right_p, clip_rect)
2261 struct frame *f;
2262 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
2263 Rect *clip_rect;
2265 int i;
2266 GC gc;
2268 if (raised_p)
2269 gc = f->output_data.mac->white_relief.gc;
2270 else
2271 gc = f->output_data.mac->black_relief.gc;
2272 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
2274 /* Top. */
2275 for (i = 0; i < width; ++i)
2276 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2277 left_x + i * left_p, top_y + i,
2278 right_x + 1 - i * right_p, top_y + i);
2280 /* Left. */
2281 if (left_p)
2282 for (i = 0; i < width; ++i)
2283 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2284 left_x + i, top_y + i, left_x + i, bottom_y - i);
2286 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
2287 if (raised_p)
2288 gc = f->output_data.mac->black_relief.gc;
2289 else
2290 gc = f->output_data.mac->white_relief.gc;
2291 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2292 clip_rect);
2294 /* Bottom. */
2295 for (i = 0; i < width; ++i)
2296 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2297 left_x + i * left_p, bottom_y - i,
2298 right_x + 1 - i * right_p, bottom_y - i);
2300 /* Right. */
2301 if (right_p)
2302 for (i = 0; i < width; ++i)
2303 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2304 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
2306 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
2310 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2311 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2312 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2313 left side of the rectangle. RIGHT_P non-zero means draw a line
2314 on the right side of the rectangle. CLIP_RECT is the clipping
2315 rectangle to use when drawing. */
2317 static void
2318 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2319 left_p, right_p, clip_rect)
2320 struct glyph_string *s;
2321 int left_x, top_y, right_x, bottom_y, left_p, right_p;
2322 Rect *clip_rect;
2324 XGCValues xgcv;
2326 xgcv.foreground = s->face->box_color;
2327 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2329 /* Top. */
2330 XFillRectangle (s->display, s->window, &xgcv,
2331 left_x, top_y, right_x - left_x, width);
2333 /* Left. */
2334 if (left_p)
2335 XFillRectangle (s->display, s->window, &xgcv,
2336 left_x, top_y, width, bottom_y - top_y);
2338 /* Bottom. */
2339 XFillRectangle (s->display, s->window, &xgcv,
2340 left_x, bottom_y - width, right_x - left_x, width);
2342 /* Right. */
2343 if (right_p)
2344 XFillRectangle (s->display, s->window, &xgcv,
2345 right_x - width, top_y, width, bottom_y - top_y);
2347 mac_reset_clipping (s->display, s->window);
2351 /* Draw a box around glyph string S. */
2353 static void
2354 x_draw_glyph_string_box (s)
2355 struct glyph_string *s;
2357 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2358 int left_p, right_p;
2359 struct glyph *last_glyph;
2360 Rect clip_rect;
2362 last_x = window_box_right (s->w, s->area);
2363 if (s->row->full_width_p
2364 && !s->w->pseudo_window_p)
2366 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2367 if (s->area != RIGHT_MARGIN_AREA
2368 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2369 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2372 /* The glyph that may have a right box line. */
2373 last_glyph = (s->cmp || s->img
2374 ? s->first_glyph
2375 : s->first_glyph + s->nchars - 1);
2377 width = abs (s->face->box_line_width);
2378 raised_p = s->face->box == FACE_RAISED_BOX;
2379 left_x = s->x;
2380 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2381 ? last_x - 1
2382 : min (last_x, s->x + s->background_width) - 1));
2383 top_y = s->y;
2384 bottom_y = top_y + s->height - 1;
2386 left_p = (s->first_glyph->left_box_line_p
2387 || (s->hl == DRAW_MOUSE_FACE
2388 && (s->prev == NULL
2389 || s->prev->hl != s->hl)));
2390 right_p = (last_glyph->right_box_line_p
2391 || (s->hl == DRAW_MOUSE_FACE
2392 && (s->next == NULL
2393 || s->next->hl != s->hl)));
2395 get_glyph_string_clip_rect (s, &clip_rect);
2397 if (s->face->box == FACE_SIMPLE_BOX)
2398 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2399 left_p, right_p, &clip_rect);
2400 else
2402 x_setup_relief_colors (s);
2403 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2404 width, raised_p, left_p, right_p, &clip_rect);
2409 /* Draw foreground of image glyph string S. */
2411 static void
2412 x_draw_image_foreground (s)
2413 struct glyph_string *s;
2415 int x;
2416 int y = s->ybase - image_ascent (s->img, s->face);
2418 /* If first glyph of S has a left box line, start drawing it to the
2419 right of that line. */
2420 if (s->face->box != FACE_NO_BOX
2421 && s->first_glyph->left_box_line_p)
2422 x = s->x + abs (s->face->box_line_width);
2423 else
2424 x = s->x;
2426 /* If there is a margin around the image, adjust x- and y-position
2427 by that margin. */
2428 x += s->img->hmargin;
2429 y += s->img->vmargin;
2431 if (s->img->pixmap)
2433 #if 0 /* MAC_TODO: image mask */
2434 if (s->img->mask)
2436 /* We can't set both a clip mask and use XSetClipRectangles
2437 because the latter also sets a clip mask. We also can't
2438 trust on the shape extension to be available
2439 (XShapeCombineRegion). So, compute the rectangle to draw
2440 manually. */
2441 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2442 | GCFunction);
2443 XGCValues xgcv;
2444 XRectangle clip_rect, image_rect, r;
2446 xgcv.clip_mask = s->img->mask;
2447 xgcv.clip_x_origin = x;
2448 xgcv.clip_y_origin = y;
2449 xgcv.function = GXcopy;
2450 XChangeGC (s->display, s->gc, mask, &xgcv);
2452 get_glyph_string_clip_rect (s, &clip_rect);
2453 image_rect.x = x;
2454 image_rect.y = y;
2455 image_rect.width = s->img->width;
2456 image_rect.height = s->img->height;
2457 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2458 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2459 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
2461 else
2462 #endif /* MAC_TODO */
2464 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
2465 0, 0, s->img->width, s->img->height, x, y);
2467 /* When the image has a mask, we can expect that at
2468 least part of a mouse highlight or a block cursor will
2469 be visible. If the image doesn't have a mask, make
2470 a block cursor visible by drawing a rectangle around
2471 the image. I believe it's looking better if we do
2472 nothing here for mouse-face. */
2473 if (s->hl == DRAW_CURSOR)
2475 int r = s->img->relief;
2476 if (r < 0) r = -r;
2477 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2478 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2482 else
2483 /* Draw a rectangle if image could not be loaded. */
2484 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2485 s->img->width - 1, s->img->height - 1);
2490 /* Draw a relief around the image glyph string S. */
2492 static void
2493 x_draw_image_relief (s)
2494 struct glyph_string *s;
2496 int x0, y0, x1, y1, thick, raised_p;
2497 Rect r;
2498 int x;
2499 int y = s->ybase - image_ascent (s->img, s->face);
2501 /* If first glyph of S has a left box line, start drawing it to the
2502 right of that line. */
2503 if (s->face->box != FACE_NO_BOX
2504 && s->first_glyph->left_box_line_p)
2505 x = s->x + abs (s->face->box_line_width);
2506 else
2507 x = s->x;
2509 /* If there is a margin around the image, adjust x- and y-position
2510 by that margin. */
2511 x += s->img->hmargin;
2512 y += s->img->vmargin;
2514 if (s->hl == DRAW_IMAGE_SUNKEN
2515 || s->hl == DRAW_IMAGE_RAISED)
2517 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2518 raised_p = s->hl == DRAW_IMAGE_RAISED;
2520 else
2522 thick = abs (s->img->relief);
2523 raised_p = s->img->relief > 0;
2526 x0 = x - thick;
2527 y0 = y - thick;
2528 x1 = x + s->img->width + thick - 1;
2529 y1 = y + s->img->height + thick - 1;
2531 x_setup_relief_colors (s);
2532 get_glyph_string_clip_rect (s, &r);
2533 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
2537 /* Draw the foreground of image glyph string S to PIXMAP. */
2539 static void
2540 x_draw_image_foreground_1 (s, pixmap)
2541 struct glyph_string *s;
2542 Pixmap pixmap;
2544 int x;
2545 int y = s->ybase - s->y - image_ascent (s->img, s->face);
2547 /* If first glyph of S has a left box line, start drawing it to the
2548 right of that line. */
2549 if (s->face->box != FACE_NO_BOX
2550 && s->first_glyph->left_box_line_p)
2551 x = abs (s->face->box_line_width);
2552 else
2553 x = 0;
2555 /* If there is a margin around the image, adjust x- and y-position
2556 by that margin. */
2557 x += s->img->hmargin;
2558 y += s->img->vmargin;
2560 if (s->img->pixmap)
2562 #if 0 /* MAC_TODO: image mask */
2563 if (s->img->mask)
2565 /* We can't set both a clip mask and use XSetClipRectangles
2566 because the latter also sets a clip mask. We also can't
2567 trust on the shape extension to be available
2568 (XShapeCombineRegion). So, compute the rectangle to draw
2569 manually. */
2570 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2571 | GCFunction);
2572 XGCValues xgcv;
2574 xgcv.clip_mask = s->img->mask;
2575 xgcv.clip_x_origin = x;
2576 xgcv.clip_y_origin = y;
2577 xgcv.function = GXcopy;
2578 XChangeGC (s->display, s->gc, mask, &xgcv);
2580 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2581 0, 0, s->img->width, s->img->height, x, y);
2582 XSetClipMask (s->display, s->gc, None);
2584 else
2585 #endif /* MAC_TODO */
2587 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2588 0, 0, s->img->width, s->img->height, x, y);
2590 /* When the image has a mask, we can expect that at
2591 least part of a mouse highlight or a block cursor will
2592 be visible. If the image doesn't have a mask, make
2593 a block cursor visible by drawing a rectangle around
2594 the image. I believe it's looking better if we do
2595 nothing here for mouse-face. */
2596 if (s->hl == DRAW_CURSOR)
2598 int r = s->img->relief;
2599 if (r < 0) r = -r;
2600 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
2601 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2605 else
2606 /* Draw a rectangle if image could not be loaded. */
2607 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2608 s->img->width - 1, s->img->height - 1);
2612 /* Draw part of the background of glyph string S. X, Y, W, and H
2613 give the rectangle to draw. */
2615 static void
2616 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2617 struct glyph_string *s;
2618 int x, y, w, h;
2620 #if 0 /* MAC_TODO: stipple */
2621 if (s->stippled_p)
2623 /* Fill background with a stipple pattern. */
2624 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2625 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2626 XSetFillStyle (s->display, s->gc, FillSolid);
2628 else
2629 #endif /* MAC_TODO */
2630 x_clear_glyph_string_rect (s, x, y, w, h);
2634 /* Draw image glyph string S.
2636 s->y
2637 s->x +-------------------------
2638 | s->face->box
2640 | +-------------------------
2641 | | s->img->vmargin
2643 | | +-------------------
2644 | | | the image
2648 static void
2649 x_draw_image_glyph_string (s)
2650 struct glyph_string *s;
2652 int x, y;
2653 int box_line_hwidth = abs (s->face->box_line_width);
2654 int box_line_vwidth = max (s->face->box_line_width, 0);
2655 int height;
2656 Pixmap pixmap = 0;
2658 height = s->height - 2 * box_line_vwidth;
2660 /* Fill background with face under the image. Do it only if row is
2661 taller than image or if image has a clip mask to reduce
2662 flickering. */
2663 s->stippled_p = s->face->stipple != 0;
2664 if (height > s->img->height
2665 || s->img->hmargin
2666 || s->img->vmargin
2667 #if 0 /* TODO: image mask */
2668 || s->img->mask
2669 #endif
2670 || s->img->pixmap == 0
2671 || s->width != s->background_width)
2673 if (box_line_hwidth && s->first_glyph->left_box_line_p)
2674 x = s->x + box_line_hwidth;
2675 else
2676 x = s->x;
2678 y = s->y + box_line_vwidth;
2679 #if 0 /* TODO: image mask */
2680 if (s->img->mask)
2682 /* Create a pixmap as large as the glyph string. Fill it
2683 with the background color. Copy the image to it, using
2684 its mask. Copy the temporary pixmap to the display. */
2685 Screen *screen = FRAME_X_SCREEN (s->f);
2686 int depth = DefaultDepthOfScreen (screen);
2688 /* Create a pixmap as large as the glyph string. */
2689 pixmap = XCreatePixmap (s->display, s->window,
2690 s->background_width,
2691 s->height, depth);
2693 /* Don't clip in the following because we're working on the
2694 pixmap. */
2695 XSetClipMask (s->display, s->gc, None);
2697 /* Fill the pixmap with the background color/stipple. */
2698 if (s->stippled_p)
2700 /* Fill background with a stipple pattern. */
2701 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2702 XFillRectangle (s->display, pixmap, s->gc,
2703 0, 0, s->background_width, s->height);
2704 XSetFillStyle (s->display, s->gc, FillSolid);
2706 else
2708 XGCValues xgcv;
2709 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2710 &xgcv);
2711 XSetForeground (s->display, s->gc, xgcv.background);
2712 XFillRectangle (s->display, pixmap, s->gc,
2713 0, 0, s->background_width, s->height);
2714 XSetForeground (s->display, s->gc, xgcv.foreground);
2717 else
2718 #endif
2719 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2721 s->background_filled_p = 1;
2724 /* Draw the foreground. */
2725 if (pixmap != 0)
2727 x_draw_image_foreground_1 (s, pixmap);
2728 x_set_glyph_string_clipping (s);
2729 mac_copy_area (s->display, pixmap, s->window, s->gc,
2730 0, 0, s->background_width, s->height, s->x, s->y);
2731 mac_reset_clipping (s->display, s->window);
2732 XFreePixmap (s->display, pixmap);
2734 else
2735 x_draw_image_foreground (s);
2737 /* If we must draw a relief around the image, do it. */
2738 if (s->img->relief
2739 || s->hl == DRAW_IMAGE_RAISED
2740 || s->hl == DRAW_IMAGE_SUNKEN)
2741 x_draw_image_relief (s);
2745 /* Draw stretch glyph string S. */
2747 static void
2748 x_draw_stretch_glyph_string (s)
2749 struct glyph_string *s;
2751 xassert (s->first_glyph->type == STRETCH_GLYPH);
2752 s->stippled_p = s->face->stipple != 0;
2754 if (s->hl == DRAW_CURSOR
2755 && !x_stretch_cursor_p)
2757 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2758 as wide as the stretch glyph. */
2759 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2761 /* Draw cursor. */
2762 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2764 /* Clear rest using the GC of the original non-cursor face. */
2765 if (width < s->background_width)
2767 GC gc = s->face->gc;
2768 int x = s->x + width, y = s->y;
2769 int w = s->background_width - width, h = s->height;
2770 Rect r;
2772 if (s->row->mouse_face_p
2773 && cursor_in_mouse_face_p (s->w))
2775 x_set_mouse_face_gc (s);
2776 gc = s->gc;
2778 else
2779 gc = s->face->gc;
2781 get_glyph_string_clip_rect (s, &r);
2782 mac_set_clip_rectangle (s->display, s->window, &r);
2784 #if 0 /* MAC_TODO: stipple */
2785 if (s->face->stipple)
2787 /* Fill background with a stipple pattern. */
2788 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2789 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2790 XSetFillStyle (s->display, gc, FillSolid);
2792 else
2793 #endif /* MAC_TODO */
2795 XGCValues xgcv;
2796 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2797 XSetForeground (s->display, gc, xgcv.background);
2798 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2799 XSetForeground (s->display, gc, xgcv.foreground);
2802 mac_reset_clipping (s->display, s->window);
2805 else if (!s->background_filled_p)
2806 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2807 s->height);
2809 s->background_filled_p = 1;
2813 /* Draw glyph string S. */
2815 static void
2816 x_draw_glyph_string (s)
2817 struct glyph_string *s;
2819 int relief_drawn_p = 0;
2821 /* If S draws into the background of its successor, draw the
2822 background of the successor first so that S can draw into it.
2823 This makes S->next use XDrawString instead of XDrawImageString. */
2824 if (s->next && s->right_overhang && !s->for_overlaps_p)
2826 xassert (s->next->img == NULL);
2827 x_set_glyph_string_gc (s->next);
2828 x_set_glyph_string_clipping (s->next);
2829 x_draw_glyph_string_background (s->next, 1);
2833 /* Set up S->gc, set clipping and draw S. */
2834 x_set_glyph_string_gc (s);
2836 /* Draw relief (if any) in advance for char/composition so that the
2837 glyph string can be drawn over it. */
2838 if (!s->for_overlaps_p
2839 && s->face->box != FACE_NO_BOX
2840 && (s->first_glyph->type == CHAR_GLYPH
2841 || s->first_glyph->type == COMPOSITE_GLYPH))
2844 x_set_glyph_string_clipping (s);
2845 x_draw_glyph_string_background (s, 1);
2846 x_draw_glyph_string_box (s);
2847 x_set_glyph_string_clipping (s);
2848 relief_drawn_p = 1;
2850 else
2851 x_set_glyph_string_clipping (s);
2853 switch (s->first_glyph->type)
2855 case IMAGE_GLYPH:
2856 x_draw_image_glyph_string (s);
2857 break;
2859 case STRETCH_GLYPH:
2860 x_draw_stretch_glyph_string (s);
2861 break;
2863 case CHAR_GLYPH:
2864 if (s->for_overlaps_p)
2865 s->background_filled_p = 1;
2866 else
2867 x_draw_glyph_string_background (s, 0);
2868 x_draw_glyph_string_foreground (s);
2869 break;
2871 case COMPOSITE_GLYPH:
2872 if (s->for_overlaps_p || s->gidx > 0)
2873 s->background_filled_p = 1;
2874 else
2875 x_draw_glyph_string_background (s, 1);
2876 x_draw_composite_glyph_string_foreground (s);
2877 break;
2879 default:
2880 abort ();
2883 if (!s->for_overlaps_p)
2885 /* Draw underline. */
2886 if (s->face->underline_p)
2888 unsigned long h = 1;
2889 unsigned long dy = s->height - h;
2891 if (s->face->underline_defaulted_p)
2892 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2893 s->width, h);
2894 else
2896 XGCValues xgcv;
2897 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2898 XSetForeground (s->display, s->gc, s->face->underline_color);
2899 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2900 s->width, h);
2901 XSetForeground (s->display, s->gc, xgcv.foreground);
2905 /* Draw overline. */
2906 if (s->face->overline_p)
2908 unsigned long dy = 0, h = 1;
2910 if (s->face->overline_color_defaulted_p)
2911 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2912 s->width, h);
2913 else
2915 XGCValues xgcv;
2916 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2917 XSetForeground (s->display, s->gc, s->face->overline_color);
2918 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2919 s->width, h);
2920 XSetForeground (s->display, s->gc, xgcv.foreground);
2924 /* Draw strike-through. */
2925 if (s->face->strike_through_p)
2927 unsigned long h = 1;
2928 unsigned long dy = (s->height - h) / 2;
2930 if (s->face->strike_through_color_defaulted_p)
2931 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2932 s->width, h);
2933 else
2935 XGCValues xgcv;
2936 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2937 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2938 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2939 s->width, h);
2940 XSetForeground (s->display, s->gc, xgcv.foreground);
2944 /* Draw relief. */
2945 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2946 x_draw_glyph_string_box (s);
2949 /* Reset clipping. */
2950 mac_reset_clipping (s->display, s->window);
2953 /* Shift display to make room for inserted glyphs. */
2955 void
2956 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2957 struct frame *f;
2958 int x, y, width, height, shift_by;
2960 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2961 f->output_data.mac->normal_gc,
2962 x, y, width, height,
2963 x + shift_by, y);
2967 /* Delete N glyphs at the nominal cursor position. Not implemented
2968 for X frames. */
2970 static void
2971 x_delete_glyphs (n)
2972 register int n;
2974 abort ();
2978 /* Clear entire frame. If updating_frame is non-null, clear that
2979 frame. Otherwise clear the selected frame. */
2981 static void
2982 x_clear_frame ()
2984 struct frame *f;
2986 if (updating_frame)
2987 f = updating_frame;
2988 else
2989 f = SELECTED_FRAME ();
2991 /* Clearing the frame will erase any cursor, so mark them all as no
2992 longer visible. */
2993 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2994 output_cursor.hpos = output_cursor.vpos = 0;
2995 output_cursor.x = -1;
2997 /* We don't set the output cursor here because there will always
2998 follow an explicit cursor_to. */
2999 BLOCK_INPUT;
3000 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3002 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3003 /* We have to clear the scroll bars, too. If we have changed
3004 colors or something like that, then they should be notified. */
3005 x_scroll_bar_clear (f);
3006 #endif
3008 XFlush (FRAME_MAC_DISPLAY (f));
3009 UNBLOCK_INPUT;
3014 /* Invert the middle quarter of the frame for .15 sec. */
3016 /* We use the select system call to do the waiting, so we have to make
3017 sure it's available. If it isn't, we just won't do visual bells. */
3019 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3021 /* Subtract the `struct timeval' values X and Y, storing the result in
3022 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3024 static int
3025 timeval_subtract (result, x, y)
3026 struct timeval *result, x, y;
3028 /* Perform the carry for the later subtraction by updating y. This
3029 is safer because on some systems the tv_sec member is unsigned. */
3030 if (x.tv_usec < y.tv_usec)
3032 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3033 y.tv_usec -= 1000000 * nsec;
3034 y.tv_sec += nsec;
3037 if (x.tv_usec - y.tv_usec > 1000000)
3039 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3040 y.tv_usec += 1000000 * nsec;
3041 y.tv_sec -= nsec;
3044 /* Compute the time remaining to wait. tv_usec is certainly
3045 positive. */
3046 result->tv_sec = x.tv_sec - y.tv_sec;
3047 result->tv_usec = x.tv_usec - y.tv_usec;
3049 /* Return indication of whether the result should be considered
3050 negative. */
3051 return x.tv_sec < y.tv_sec;
3054 void
3055 XTflash (f)
3056 struct frame *f;
3058 BLOCK_INPUT;
3060 FlashMenuBar (0);
3063 struct timeval wakeup;
3065 EMACS_GET_TIME (wakeup);
3067 /* Compute time to wait until, propagating carry from usecs. */
3068 wakeup.tv_usec += 150000;
3069 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3070 wakeup.tv_usec %= 1000000;
3072 /* Keep waiting until past the time wakeup. */
3073 while (1)
3075 struct timeval timeout;
3077 EMACS_GET_TIME (timeout);
3079 /* In effect, timeout = wakeup - timeout.
3080 Break if result would be negative. */
3081 if (timeval_subtract (&timeout, wakeup, timeout))
3082 break;
3084 /* Try to wait that long--but we might wake up sooner. */
3085 select (0, NULL, NULL, NULL, &timeout);
3089 FlashMenuBar (0);
3091 UNBLOCK_INPUT;
3094 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3097 /* Make audible bell. */
3099 void
3100 XTring_bell ()
3102 struct frame *f = SELECTED_FRAME ();
3104 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3105 if (visible_bell)
3106 XTflash (f);
3107 else
3108 #endif
3110 BLOCK_INPUT;
3111 SysBeep (1);
3112 XFlush (FRAME_MAC_DISPLAY (f));
3113 UNBLOCK_INPUT;
3119 /* Specify how many text lines, from the top of the window,
3120 should be affected by insert-lines and delete-lines operations.
3121 This, and those operations, are used only within an update
3122 that is bounded by calls to x_update_begin and x_update_end. */
3124 void
3125 XTset_terminal_window (n)
3126 register int n;
3128 /* This function intentionally left blank. */
3133 /***********************************************************************
3134 Line Dance
3135 ***********************************************************************/
3137 /* Perform an insert-lines or delete-lines operation, inserting N
3138 lines or deleting -N lines at vertical position VPOS. */
3140 static void
3141 x_ins_del_lines (vpos, n)
3142 int vpos, n;
3144 abort ();
3148 /* Scroll part of the display as described by RUN. */
3150 static void
3151 x_scroll_run (w, run)
3152 struct window *w;
3153 struct run *run;
3155 struct frame *f = XFRAME (w->frame);
3156 int x, y, width, height, from_y, to_y, bottom_y;
3158 /* Get frame-relative bounding box of the text display area of W,
3159 without mode lines. Include in this box the left and right
3160 fringes of W. */
3161 window_box (w, -1, &x, &y, &width, &height);
3163 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3164 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3165 bottom_y = y + height;
3167 if (to_y < from_y)
3169 /* Scrolling up. Make sure we don't copy part of the mode
3170 line at the bottom. */
3171 if (from_y + run->height > bottom_y)
3172 height = bottom_y - from_y;
3173 else
3174 height = run->height;
3176 else
3178 /* Scolling down. Make sure we don't copy over the mode line.
3179 at the bottom. */
3180 if (to_y + run->height > bottom_y)
3181 height = bottom_y - to_y;
3182 else
3183 height = run->height;
3186 BLOCK_INPUT;
3188 /* Cursor off. Will be switched on again in x_update_window_end. */
3189 updated_window = w;
3190 x_clear_cursor (w);
3192 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3193 f->output_data.mac->normal_gc,
3194 x, from_y,
3195 width, height,
3196 x, to_y);
3198 UNBLOCK_INPUT;
3203 /***********************************************************************
3204 Exposure Events
3205 ***********************************************************************/
3208 static void
3209 frame_highlight (f)
3210 struct frame *f;
3212 x_update_cursor (f, 1);
3215 static void
3216 frame_unhighlight (f)
3217 struct frame *f;
3219 x_update_cursor (f, 1);
3222 /* The focus has changed. Update the frames as necessary to reflect
3223 the new situation. Note that we can't change the selected frame
3224 here, because the Lisp code we are interrupting might become confused.
3225 Each event gets marked with the frame in which it occurred, so the
3226 Lisp code can tell when the switch took place by examining the events. */
3228 static void
3229 x_new_focus_frame (dpyinfo, frame)
3230 struct x_display_info *dpyinfo;
3231 struct frame *frame;
3233 struct frame *old_focus = dpyinfo->x_focus_frame;
3235 if (frame != dpyinfo->x_focus_frame)
3237 /* Set this before calling other routines, so that they see
3238 the correct value of x_focus_frame. */
3239 dpyinfo->x_focus_frame = frame;
3241 if (old_focus && old_focus->auto_lower)
3242 x_lower_frame (old_focus);
3244 #if 0
3245 selected_frame = frame;
3246 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3247 selected_frame);
3248 Fselect_window (selected_frame->selected_window, Qnil);
3249 choose_minibuf_frame ();
3250 #endif /* ! 0 */
3252 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3253 pending_autoraise_frame = dpyinfo->x_focus_frame;
3254 else
3255 pending_autoraise_frame = 0;
3258 x_frame_rehighlight (dpyinfo);
3261 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3263 void
3264 x_mouse_leave (dpyinfo)
3265 struct x_display_info *dpyinfo;
3267 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3270 /* The focus has changed, or we have redirected a frame's focus to
3271 another frame (this happens when a frame uses a surrogate
3272 mini-buffer frame). Shift the highlight as appropriate.
3274 The FRAME argument doesn't necessarily have anything to do with which
3275 frame is being highlighted or un-highlighted; we only use it to find
3276 the appropriate X display info. */
3278 static void
3279 XTframe_rehighlight (frame)
3280 struct frame *frame;
3284 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3287 static void
3288 x_frame_rehighlight (dpyinfo)
3289 struct x_display_info *dpyinfo;
3291 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3293 if (dpyinfo->x_focus_frame)
3295 dpyinfo->x_highlight_frame
3296 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3297 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3298 : dpyinfo->x_focus_frame);
3299 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3301 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3302 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3305 else
3306 dpyinfo->x_highlight_frame = 0;
3308 if (dpyinfo->x_highlight_frame != old_highlight)
3310 if (old_highlight)
3311 frame_unhighlight (old_highlight);
3312 if (dpyinfo->x_highlight_frame)
3313 frame_highlight (dpyinfo->x_highlight_frame);
3319 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3321 #if 0 /* MAC_TODO */
3322 /* Initialize mode_switch_bit and modifier_meaning. */
3323 static void
3324 x_find_modifier_meanings (dpyinfo)
3325 struct x_display_info *dpyinfo;
3327 int min_code, max_code;
3328 KeySym *syms;
3329 int syms_per_code;
3330 XModifierKeymap *mods;
3332 dpyinfo->meta_mod_mask = 0;
3333 dpyinfo->shift_lock_mask = 0;
3334 dpyinfo->alt_mod_mask = 0;
3335 dpyinfo->super_mod_mask = 0;
3336 dpyinfo->hyper_mod_mask = 0;
3338 #ifdef HAVE_X11R4
3339 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3340 #else
3341 min_code = dpyinfo->display->min_keycode;
3342 max_code = dpyinfo->display->max_keycode;
3343 #endif
3345 syms = XGetKeyboardMapping (dpyinfo->display,
3346 min_code, max_code - min_code + 1,
3347 &syms_per_code);
3348 mods = XGetModifierMapping (dpyinfo->display);
3350 /* Scan the modifier table to see which modifier bits the Meta and
3351 Alt keysyms are on. */
3353 int row, col; /* The row and column in the modifier table. */
3355 for (row = 3; row < 8; row++)
3356 for (col = 0; col < mods->max_keypermod; col++)
3358 KeyCode code
3359 = mods->modifiermap[(row * mods->max_keypermod) + col];
3361 /* Zeroes are used for filler. Skip them. */
3362 if (code == 0)
3363 continue;
3365 /* Are any of this keycode's keysyms a meta key? */
3367 int code_col;
3369 for (code_col = 0; code_col < syms_per_code; code_col++)
3371 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3373 switch (sym)
3375 case XK_Meta_L:
3376 case XK_Meta_R:
3377 dpyinfo->meta_mod_mask |= (1 << row);
3378 break;
3380 case XK_Alt_L:
3381 case XK_Alt_R:
3382 dpyinfo->alt_mod_mask |= (1 << row);
3383 break;
3385 case XK_Hyper_L:
3386 case XK_Hyper_R:
3387 dpyinfo->hyper_mod_mask |= (1 << row);
3388 break;
3390 case XK_Super_L:
3391 case XK_Super_R:
3392 dpyinfo->super_mod_mask |= (1 << row);
3393 break;
3395 case XK_Shift_Lock:
3396 /* Ignore this if it's not on the lock modifier. */
3397 if ((1 << row) == LockMask)
3398 dpyinfo->shift_lock_mask = LockMask;
3399 break;
3406 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3407 if (! dpyinfo->meta_mod_mask)
3409 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3410 dpyinfo->alt_mod_mask = 0;
3413 /* If some keys are both alt and meta,
3414 make them just meta, not alt. */
3415 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3417 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3420 XFree ((char *) syms);
3421 XFreeModifiermap (mods);
3424 #endif /* MAC_TODO */
3426 /* Convert between the modifier bits X uses and the modifier bits
3427 Emacs uses. */
3429 static unsigned int
3430 x_mac_to_emacs_modifiers (dpyinfo, state)
3431 struct x_display_info *dpyinfo;
3432 unsigned short state;
3434 return (((state & shiftKey) ? shift_modifier : 0)
3435 | ((state & controlKey) ? ctrl_modifier : 0)
3436 | ((state & cmdKey) ? meta_modifier : 0)
3437 | ((state & optionKey) ? alt_modifier : 0));
3440 #if 0 /* MAC_TODO */
3441 static unsigned short
3442 x_emacs_to_x_modifiers (dpyinfo, state)
3443 struct x_display_info *dpyinfo;
3444 unsigned int state;
3446 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3447 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3448 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3449 | ((state & shift_modifier) ? ShiftMask : 0)
3450 | ((state & ctrl_modifier) ? ControlMask : 0)
3451 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3453 #endif /* MAC_TODO */
3455 /* Convert a keysym to its name. */
3457 char *
3458 x_get_keysym_name (keysym)
3459 int keysym;
3461 char *value;
3463 BLOCK_INPUT;
3464 #if 0
3465 value = XKeysymToString (keysym);
3466 #else
3467 value = 0;
3468 #endif
3469 UNBLOCK_INPUT;
3471 return value;
3476 /* Mouse clicks and mouse movement. Rah. */
3478 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3480 If the event is a button press, then note that we have grabbed
3481 the mouse. */
3483 static Lisp_Object
3484 construct_mouse_click (result, event, f)
3485 struct input_event *result;
3486 EventRecord *event;
3487 struct frame *f;
3489 Point mouseLoc;
3491 result->kind = MOUSE_CLICK_EVENT;
3492 result->code = 0; /* only one mouse button */
3493 result->timestamp = event->when;
3494 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3496 mouseLoc = event->where;
3498 #if TARGET_API_MAC_CARBON
3499 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
3500 #else
3501 SetPort (FRAME_MAC_WINDOW (f));
3502 #endif
3504 GlobalToLocal (&mouseLoc);
3505 XSETINT (result->x, mouseLoc.h);
3506 XSETINT (result->y, mouseLoc.v);
3508 XSETFRAME (result->frame_or_window, f);
3510 result->arg = Qnil;
3511 return Qnil;
3515 /* Function to report a mouse movement to the mainstream Emacs code.
3516 The input handler calls this.
3518 We have received a mouse movement event, which is given in *event.
3519 If the mouse is over a different glyph than it was last time, tell
3520 the mainstream emacs code by setting mouse_moved. If not, ask for
3521 another motion event, so we can check again the next time it moves. */
3523 static Point last_mouse_motion_position;
3524 static Lisp_Object last_mouse_motion_frame;
3526 static void
3527 note_mouse_movement (frame, pos)
3528 FRAME_PTR frame;
3529 Point *pos;
3531 #if TARGET_API_MAC_CARBON
3532 Rect r;
3533 #endif
3535 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3536 last_mouse_motion_position = *pos;
3537 XSETFRAME (last_mouse_motion_frame, frame);
3539 #if TARGET_API_MAC_CARBON
3540 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3541 #else
3542 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3543 #endif
3545 frame->mouse_moved = 1;
3546 last_mouse_scroll_bar = Qnil;
3547 note_mouse_highlight (frame, -1, -1);
3549 /* Has the mouse moved off the glyph it was on at the last sighting? */
3550 else if (pos->h < last_mouse_glyph.left
3551 || pos->h >= last_mouse_glyph.right
3552 || pos->v < last_mouse_glyph.top
3553 || pos->v >= last_mouse_glyph.bottom)
3555 frame->mouse_moved = 1;
3556 last_mouse_scroll_bar = Qnil;
3557 note_mouse_highlight (frame, pos->h, pos->v);
3561 /* This is used for debugging, to turn off note_mouse_highlight. */
3563 int disable_mouse_highlight;
3567 /************************************************************************
3568 Mouse Face
3569 ************************************************************************/
3571 static struct scroll_bar *x_window_to_scroll_bar ();
3572 static void x_scroll_bar_report_motion ();
3573 static void x_check_fullscreen P_ ((struct frame *));
3574 static void x_check_fullscreen_move P_ ((struct frame *));
3575 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3578 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3580 static void
3581 redo_mouse_highlight ()
3583 if (!NILP (last_mouse_motion_frame)
3584 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3585 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3586 last_mouse_motion_position.h,
3587 last_mouse_motion_position.v);
3591 /* Try to determine frame pixel position and size of the glyph under
3592 frame pixel coordinates X/Y on frame F . Return the position and
3593 size in *RECT. Value is non-zero if we could compute these
3594 values. */
3596 static int
3597 glyph_rect (f, x, y, rect)
3598 struct frame *f;
3599 int x, y;
3600 Rect *rect;
3602 Lisp_Object window;
3604 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3606 if (!NILP (window))
3608 struct window *w = XWINDOW (window);
3609 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3610 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3612 for (; r < end && r->enabled_p; ++r)
3613 if (r->y <= y && r->y + r->height > y)
3615 /* Found the row at y. */
3616 struct glyph *g = r->glyphs[TEXT_AREA];
3617 struct glyph *end = g + r->used[TEXT_AREA];
3618 int gx;
3620 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3621 rect->bottom = rect->top + r->height;
3623 if (x < r->x)
3625 /* x is to the left of the first glyph in the row. */
3626 /* Shouldn't this be a pixel value?
3627 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3628 ++KFS */
3629 rect->left = WINDOW_LEFT_EDGE_COL (w);
3630 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3631 return 1;
3634 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3635 if (gx <= x && gx + g->pixel_width > x)
3637 /* x is on a glyph. */
3638 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3639 rect->right = rect->left + g->pixel_width;
3640 return 1;
3643 /* x is to the right of the last glyph in the row. */
3644 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3645 /* Shouldn't this be a pixel value?
3646 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3647 ++KFS */
3648 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3649 return 1;
3653 /* The y is not on any row. */
3654 return 0;
3657 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3659 /* Record the position of the mouse in last_mouse_glyph. */
3660 static void
3661 remember_mouse_glyph (f1, gx, gy)
3662 struct frame * f1;
3663 int gx, gy;
3665 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3667 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3668 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3670 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3671 round down even for negative values. */
3672 if (gx < 0)
3673 gx -= width - 1;
3674 if (gy < 0)
3675 gy -= height - 1;
3676 #if 0
3677 /* This was the original code from XTmouse_position, but it seems
3678 to give the position of the glyph diagonally next to the one
3679 the mouse is over. */
3680 gx = (gx + width - 1) / width * width;
3681 gy = (gy + height - 1) / height * height;
3682 #else
3683 gx = gx / width * width;
3684 gy = gy / height * height;
3685 #endif
3687 last_mouse_glyph.left = gx;
3688 last_mouse_glyph.top = gy;
3689 last_mouse_glyph.right = gx + width;
3690 last_mouse_glyph.bottom = gy + height;
3695 /* Return the current position of the mouse.
3696 *fp should be a frame which indicates which display to ask about.
3698 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3699 and *part to the frame, window, and scroll bar part that the mouse
3700 is over. Set *x and *y to the portion and whole of the mouse's
3701 position on the scroll bar.
3703 If the mouse movement started elsewhere, set *fp to the frame the
3704 mouse is on, *bar_window to nil, and *x and *y to the character cell
3705 the mouse is over.
3707 Set *time to the server time-stamp for the time at which the mouse
3708 was at this position.
3710 Don't store anything if we don't have a valid set of values to report.
3712 This clears the mouse_moved flag, so we can wait for the next mouse
3713 movement. */
3715 static void
3716 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3717 FRAME_PTR *fp;
3718 int insist;
3719 Lisp_Object *bar_window;
3720 enum scroll_bar_part *part;
3721 Lisp_Object *x, *y;
3722 unsigned long *time;
3724 Point mouse_pos;
3725 int ignore1, ignore2;
3726 WindowPtr wp = FrontWindow ();
3727 struct frame *f;
3728 Lisp_Object frame, tail;
3730 if (is_emacs_window(wp))
3731 f = ((mac_output *) GetWRefCon (wp))->mFP;
3733 BLOCK_INPUT;
3735 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3736 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3737 else
3739 /* Clear the mouse-moved flag for every frame on this display. */
3740 FOR_EACH_FRAME (tail, frame)
3741 XFRAME (frame)->mouse_moved = 0;
3743 last_mouse_scroll_bar = Qnil;
3745 #if TARGET_API_MAC_CARBON
3746 SetPort (GetWindowPort (wp));
3747 #else
3748 SetPort (wp);
3749 #endif
3751 GetMouse (&mouse_pos);
3753 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3754 &last_mouse_glyph, insist);
3756 *bar_window = Qnil;
3757 *part = scroll_bar_handle;
3758 *fp = f;
3759 XSETINT (*x, mouse_pos.h);
3760 XSETINT (*y, mouse_pos.v);
3761 *time = last_mouse_movement_time;
3764 UNBLOCK_INPUT;
3768 /***********************************************************************
3769 Tool-bars
3770 ***********************************************************************/
3772 /* Handle mouse button event on the tool-bar of frame F, at
3773 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3774 or ButtonRelase. */
3776 static void
3777 mac_handle_tool_bar_click (f, button_event)
3778 struct frame *f;
3779 EventRecord *button_event;
3781 int x = button_event->where.h;
3782 int y = button_event->where.v;
3784 if (button_event->what == mouseDown)
3785 handle_tool_bar_click (f, x, y, 1, 0);
3786 else
3787 handle_tool_bar_click (f, x, y, 0,
3788 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
3789 button_event->modifiers));
3793 /************************************************************************
3794 Scroll bars, general
3795 ************************************************************************/
3797 /* Create a scroll bar and return the scroll bar vector for it. W is
3798 the Emacs window on which to create the scroll bar. TOP, LEFT,
3799 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
3800 scroll bar. */
3802 static struct scroll_bar *
3803 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
3804 struct window *w;
3805 int top, left, width, height, disp_top, disp_height;
3807 struct frame *f = XFRAME (w->frame);
3808 struct scroll_bar *bar
3809 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
3810 Rect r;
3811 ControlHandle ch;
3813 BLOCK_INPUT;
3815 r.left = left;
3816 r.top = disp_top;
3817 r.right = left + width;
3818 r.bottom = disp_top + disp_height;
3820 #ifdef TARGET_API_MAC_CARBON
3821 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
3822 kControlScrollBarProc, 0L);
3823 #else
3824 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
3825 0L);
3826 #endif
3827 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
3828 SetControlReference (ch, (long) bar);
3830 XSETWINDOW (bar->window, w);
3831 XSETINT (bar->top, top);
3832 XSETINT (bar->left, left);
3833 XSETINT (bar->width, width);
3834 XSETINT (bar->height, height);
3835 XSETINT (bar->start, 0);
3836 XSETINT (bar->end, 0);
3837 bar->dragging = Qnil;
3839 /* Add bar to its frame's list of scroll bars. */
3840 bar->next = FRAME_SCROLL_BARS (f);
3841 bar->prev = Qnil;
3842 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3843 if (!NILP (bar->next))
3844 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3846 UNBLOCK_INPUT;
3847 return bar;
3851 /* Draw BAR's handle in the proper position.
3853 If the handle is already drawn from START to END, don't bother
3854 redrawing it, unless REBUILD is non-zero; in that case, always
3855 redraw it. (REBUILD is handy for drawing the handle after expose
3856 events.)
3858 Normally, we want to constrain the start and end of the handle to
3859 fit inside its rectangle, but if the user is dragging the scroll
3860 bar handle, we want to let them drag it down all the way, so that
3861 the bar's top is as far down as it goes; otherwise, there's no way
3862 to move to the very end of the buffer. */
3864 static void
3865 x_scroll_bar_set_handle (bar, start, end, rebuild)
3866 struct scroll_bar *bar;
3867 int start, end;
3868 int rebuild;
3870 int dragging = ! NILP (bar->dragging);
3871 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
3872 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3873 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3874 int length = end - start;
3876 /* If the display is already accurate, do nothing. */
3877 if (! rebuild
3878 && start == XINT (bar->start)
3879 && end == XINT (bar->end))
3880 return;
3882 BLOCK_INPUT;
3884 /* Make sure the values are reasonable, and try to preserve the
3885 distance between start and end. */
3886 if (start < 0)
3887 start = 0;
3888 else if (start > top_range)
3889 start = top_range;
3890 end = start + length;
3892 if (end < start)
3893 end = start;
3894 else if (end > top_range && ! dragging)
3895 end = top_range;
3897 /* Store the adjusted setting in the scroll bar. */
3898 XSETINT (bar->start, start);
3899 XSETINT (bar->end, end);
3901 /* Clip the end position, just for display. */
3902 if (end > top_range)
3903 end = top_range;
3905 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
3906 top positions, to make sure the handle is always at least that
3907 many pixels tall. */
3908 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
3910 SetControlMinimum (ch, 0);
3911 /* Don't inadvertently activate deactivated scroll bars */
3912 if (GetControlMaximum (ch) != -1)
3913 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
3914 - (end - start));
3915 SetControlValue (ch, start);
3916 #if TARGET_API_MAC_CARBON
3917 SetControlViewSize (ch, end - start);
3918 #endif
3920 UNBLOCK_INPUT;
3924 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3925 nil. */
3927 static void
3928 x_scroll_bar_remove (bar)
3929 struct scroll_bar *bar;
3931 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3933 BLOCK_INPUT;
3935 /* Destroy the Mac scroll bar control */
3936 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
3938 /* Disassociate this scroll bar from its window. */
3939 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
3941 UNBLOCK_INPUT;
3944 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3945 that we are displaying PORTION characters out of a total of WHOLE
3946 characters, starting at POSITION. If WINDOW has no scroll bar,
3947 create one. */
3948 static void
3949 XTset_vertical_scroll_bar (w, portion, whole, position)
3950 struct window *w;
3951 int portion, whole, position;
3953 struct frame *f = XFRAME (w->frame);
3954 struct scroll_bar *bar;
3955 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
3956 int window_y, window_height;
3958 /* Get window dimensions. */
3959 window_box (w, -1, 0, &window_y, 0, &window_height);
3960 top = window_y;
3961 #ifdef MAC_OSX
3962 width = 16;
3963 #else
3964 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3965 #endif
3966 height = window_height;
3968 /* Compute the left edge of the scroll bar area. */
3969 left = WINDOW_SCROLL_BAR_AREA_X (w);
3971 /* Compute the width of the scroll bar which might be less than
3972 the width of the area reserved for the scroll bar. */
3973 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3974 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3975 else
3976 sb_width = width;
3978 /* Compute the left edge of the scroll bar. */
3979 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3980 sb_left = left + width - sb_width - (width - sb_width) / 2;
3981 else
3982 sb_left = left + (width - sb_width) / 2;
3984 /* Adjustments according to Inside Macintosh to make it look nice */
3985 disp_top = top;
3986 disp_height = height;
3987 if (disp_top == 0)
3989 disp_top = -1;
3990 disp_height++;
3992 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
3994 disp_top++;
3995 disp_height--;
3998 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
3999 sb_left++;
4001 /* Does the scroll bar exist yet? */
4002 if (NILP (w->vertical_scroll_bar))
4004 BLOCK_INPUT;
4005 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4006 left, top, width, height, 0);
4007 UNBLOCK_INPUT;
4008 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4009 disp_height);
4010 XSETVECTOR (w->vertical_scroll_bar, bar);
4012 else
4014 /* It may just need to be moved and resized. */
4015 ControlHandle ch;
4017 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4018 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4020 BLOCK_INPUT;
4022 /* If already correctly positioned, do nothing. */
4023 if (XINT (bar->left) == sb_left
4024 && XINT (bar->top) == top
4025 && XINT (bar->width) == sb_width
4026 && XINT (bar->height) == height)
4027 Draw1Control (ch);
4028 else
4030 /* Clear areas not covered by the scroll bar because it's not as
4031 wide as the area reserved for it . This makes sure a
4032 previous mode line display is cleared after C-x 2 C-x 1, for
4033 example. */
4034 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4035 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4036 left, top, area_width, height, 0);
4038 #if 0
4039 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4040 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4041 sb_left - 1, top, 1, height, 0);
4042 #endif
4044 HideControl (ch);
4045 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4046 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4047 disp_height);
4048 ShowControl (ch);
4050 /* Remember new settings. */
4051 XSETINT (bar->left, sb_left);
4052 XSETINT (bar->top, top);
4053 XSETINT (bar->width, sb_width);
4054 XSETINT (bar->height, height);
4057 UNBLOCK_INPUT;
4060 /* Set the scroll bar's current state, unless we're currently being
4061 dragged. */
4062 if (NILP (bar->dragging))
4064 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4066 if (whole == 0)
4067 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4068 else
4070 int start = ((double) position * top_range) / whole;
4071 int end = ((double) (position + portion) * top_range) / whole;
4072 x_scroll_bar_set_handle (bar, start, end, 0);
4078 /* The following three hooks are used when we're doing a thorough
4079 redisplay of the frame. We don't explicitly know which scroll bars
4080 are going to be deleted, because keeping track of when windows go
4081 away is a real pain - "Can you say set-window-configuration, boys
4082 and girls?" Instead, we just assert at the beginning of redisplay
4083 that *all* scroll bars are to be removed, and then save a scroll bar
4084 from the fiery pit when we actually redisplay its window. */
4086 /* Arrange for all scroll bars on FRAME to be removed at the next call
4087 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4088 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4090 static void
4091 XTcondemn_scroll_bars (frame)
4092 FRAME_PTR frame;
4094 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4095 while (! NILP (FRAME_SCROLL_BARS (frame)))
4097 Lisp_Object bar;
4098 bar = FRAME_SCROLL_BARS (frame);
4099 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4100 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4101 XSCROLL_BAR (bar)->prev = Qnil;
4102 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4103 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4104 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4109 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4110 Note that WINDOW isn't necessarily condemned at all. */
4112 static void
4113 XTredeem_scroll_bar (window)
4114 struct window *window;
4116 struct scroll_bar *bar;
4118 /* We can't redeem this window's scroll bar if it doesn't have one. */
4119 if (NILP (window->vertical_scroll_bar))
4120 abort ();
4122 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4124 /* Unlink it from the condemned list. */
4126 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4128 if (NILP (bar->prev))
4130 /* If the prev pointer is nil, it must be the first in one of
4131 the lists. */
4132 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4133 /* It's not condemned. Everything's fine. */
4134 return;
4135 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4136 window->vertical_scroll_bar))
4137 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4138 else
4139 /* If its prev pointer is nil, it must be at the front of
4140 one or the other! */
4141 abort ();
4143 else
4144 XSCROLL_BAR (bar->prev)->next = bar->next;
4146 if (! NILP (bar->next))
4147 XSCROLL_BAR (bar->next)->prev = bar->prev;
4149 bar->next = FRAME_SCROLL_BARS (f);
4150 bar->prev = Qnil;
4151 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4152 if (! NILP (bar->next))
4153 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4157 /* Remove all scroll bars on FRAME that haven't been saved since the
4158 last call to `*condemn_scroll_bars_hook'. */
4160 static void
4161 XTjudge_scroll_bars (f)
4162 FRAME_PTR f;
4164 Lisp_Object bar, next;
4166 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4168 /* Clear out the condemned list now so we won't try to process any
4169 more events on the hapless scroll bars. */
4170 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4172 for (; ! NILP (bar); bar = next)
4174 struct scroll_bar *b = XSCROLL_BAR (bar);
4176 x_scroll_bar_remove (b);
4178 next = b->next;
4179 b->next = b->prev = Qnil;
4182 /* Now there should be no references to the condemned scroll bars,
4183 and they should get garbage-collected. */
4187 void
4188 activate_scroll_bars (frame)
4189 FRAME_PTR frame;
4191 Lisp_Object bar;
4192 ControlHandle ch;
4194 bar = FRAME_SCROLL_BARS (frame);
4195 while (! NILP (bar))
4197 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4198 #ifdef TARGET_API_MAC_CARBON
4199 ActivateControl (ch);
4200 #else
4201 SetControlMaximum (ch,
4202 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4203 XINT (XSCROLL_BAR (bar)
4204 ->height)) - 1);
4205 #endif
4206 bar = XSCROLL_BAR (bar)->next;
4211 void
4212 deactivate_scroll_bars (frame)
4213 FRAME_PTR frame;
4215 Lisp_Object bar;
4216 ControlHandle ch;
4218 bar = FRAME_SCROLL_BARS (frame);
4219 while (! NILP (bar))
4221 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4222 #ifdef TARGET_API_MAC_CARBON
4223 DeactivateControl (ch);
4224 #else
4225 SetControlMaximum (ch, XINT (-1));
4226 #endif
4227 bar = XSCROLL_BAR (bar)->next;
4231 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4232 is set to something other than NO_EVENT, it is enqueued.
4234 This may be called from a signal handler, so we have to ignore GC
4235 mark bits. */
4237 static void
4238 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4239 struct scroll_bar *bar;
4240 int part_code;
4241 EventRecord *er;
4242 struct input_event *bufp;
4244 if (! GC_WINDOWP (bar->window))
4245 abort ();
4247 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4248 bufp->frame_or_window = bar->window;
4249 bufp->arg = Qnil;
4251 bar->dragging = Qnil;
4253 switch (part_code)
4255 case kControlUpButtonPart:
4256 bufp->part = scroll_bar_up_arrow;
4257 break;
4258 case kControlDownButtonPart:
4259 bufp->part = scroll_bar_down_arrow;
4260 break;
4261 case kControlPageUpPart:
4262 bufp->part = scroll_bar_above_handle;
4263 break;
4264 case kControlPageDownPart:
4265 bufp->part = scroll_bar_below_handle;
4266 break;
4267 #ifdef TARGET_API_MAC_CARBON
4268 default:
4269 #else
4270 case kControlIndicatorPart:
4271 #endif
4272 if (er->what == mouseDown)
4273 bar->dragging = make_number (0);
4274 XSETVECTOR (last_mouse_scroll_bar, bar);
4275 bufp->part = scroll_bar_handle;
4276 break;
4281 /* Handle some mouse motion while someone is dragging the scroll bar.
4283 This may be called from a signal handler, so we have to ignore GC
4284 mark bits. */
4286 static void
4287 x_scroll_bar_note_movement (bar, y_pos, t)
4288 struct scroll_bar *bar;
4289 int y_pos;
4290 Time t;
4292 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4294 last_mouse_movement_time = t;
4296 f->mouse_moved = 1;
4297 XSETVECTOR (last_mouse_scroll_bar, bar);
4299 /* If we're dragging the bar, display it. */
4300 if (! GC_NILP (bar->dragging))
4302 /* Where should the handle be now? */
4303 int new_start = y_pos - 24;
4305 if (new_start != XINT (bar->start))
4307 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4309 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4315 /* Return information to the user about the current position of the
4316 mouse on the scroll bar. */
4318 static void
4319 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4320 FRAME_PTR *fp;
4321 Lisp_Object *bar_window;
4322 enum scroll_bar_part *part;
4323 Lisp_Object *x, *y;
4324 unsigned long *time;
4326 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4327 WindowPtr wp = FrontWindow ();
4328 Point mouse_pos;
4329 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
4330 int win_y, top_range;
4332 #if TARGET_API_MAC_CARBON
4333 SetPort (GetWindowPort (wp));
4334 #else
4335 SetPort (wp);
4336 #endif
4338 GetMouse (&mouse_pos);
4340 win_y = mouse_pos.v - XINT (bar->top);
4341 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4343 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4345 win_y -= 24;
4347 if (! NILP (bar->dragging))
4348 win_y -= XINT (bar->dragging);
4350 if (win_y < 0)
4351 win_y = 0;
4352 if (win_y > top_range)
4353 win_y = top_range;
4355 *fp = f;
4356 *bar_window = bar->window;
4358 if (! NILP (bar->dragging))
4359 *part = scroll_bar_handle;
4360 else if (win_y < XINT (bar->start))
4361 *part = scroll_bar_above_handle;
4362 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4363 *part = scroll_bar_handle;
4364 else
4365 *part = scroll_bar_below_handle;
4367 XSETINT (*x, win_y);
4368 XSETINT (*y, top_range);
4370 f->mouse_moved = 0;
4371 last_mouse_scroll_bar = Qnil;
4373 *time = last_mouse_movement_time;
4376 /***********************************************************************
4377 Text Cursor
4378 ***********************************************************************/
4380 /* Set clipping for output in glyph row ROW. W is the window in which
4381 we operate. GC is the graphics context to set clipping in.
4383 ROW may be a text row or, e.g., a mode line. Text rows must be
4384 clipped to the interior of the window dedicated to text display,
4385 mode lines must be clipped to the whole window. */
4387 static void
4388 x_clip_to_row (w, row, gc)
4389 struct window *w;
4390 struct glyph_row *row;
4391 GC gc;
4393 struct frame *f = XFRAME (WINDOW_FRAME (w));
4394 Rect clip_rect;
4395 int window_y, window_width;
4397 window_box (w, -1, 0, &window_y, &window_width, 0);
4399 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
4400 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4401 clip_rect.top = max (clip_rect.top, window_y);
4402 clip_rect.right = clip_rect.left + window_width;
4403 clip_rect.bottom = clip_rect.top + row->visible_height;
4405 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4409 /* Draw a hollow box cursor on window W in glyph row ROW. */
4411 static void
4412 x_draw_hollow_cursor (w, row)
4413 struct window *w;
4414 struct glyph_row *row;
4416 struct frame *f = XFRAME (WINDOW_FRAME (w));
4417 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4418 Display *dpy = FRAME_MAC_DISPLAY (f);
4419 int x, y, wd, h;
4420 XGCValues xgcv;
4421 struct glyph *cursor_glyph;
4422 GC gc;
4424 /* Compute frame-relative coordinates from window-relative
4425 coordinates. */
4426 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4427 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
4428 + row->ascent - w->phys_cursor_ascent);
4429 h = row->height - 1;
4431 /* Get the glyph the cursor is on. If we can't tell because
4432 the current matrix is invalid or such, give up. */
4433 cursor_glyph = get_phys_cursor_glyph (w);
4434 if (cursor_glyph == NULL)
4435 return;
4437 /* Compute the width of the rectangle to draw. If on a stretch
4438 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4439 rectangle as wide as the glyph, but use a canonical character
4440 width instead. */
4441 wd = cursor_glyph->pixel_width - 1;
4442 if (cursor_glyph->type == STRETCH_GLYPH
4443 && !x_stretch_cursor_p)
4444 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4446 /* The foreground of cursor_gc is typically the same as the normal
4447 background color, which can cause the cursor box to be invisible. */
4448 xgcv.foreground = f->output_data.mac->cursor_pixel;
4449 if (dpyinfo->scratch_cursor_gc)
4450 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4451 else
4452 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4453 GCForeground, &xgcv);
4454 gc = dpyinfo->scratch_cursor_gc;
4456 /* Set clipping, draw the rectangle, and reset clipping again. */
4457 x_clip_to_row (w, row, gc);
4458 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4459 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4463 /* Draw a bar cursor on window W in glyph row ROW.
4465 Implementation note: One would like to draw a bar cursor with an
4466 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4467 Unfortunately, I didn't find a font yet that has this property set.
4468 --gerd. */
4470 static void
4471 x_draw_bar_cursor (w, row, width)
4472 struct window *w;
4473 struct glyph_row *row;
4474 int width;
4476 /* If cursor hpos is out of bounds, don't draw garbage. This can
4477 happen in mini-buffer windows when switching between echo area
4478 glyphs and mini-buffer. */
4479 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
4481 struct frame *f = XFRAME (w->frame);
4482 struct glyph *cursor_glyph;
4483 GC gc;
4484 int x;
4485 unsigned long mask;
4486 XGCValues xgcv;
4487 Display *dpy;
4488 Window window;
4490 cursor_glyph = get_phys_cursor_glyph (w);
4491 if (cursor_glyph == NULL)
4492 return;
4494 xgcv.background = f->output_data.mac->cursor_pixel;
4495 xgcv.foreground = f->output_data.mac->cursor_pixel;
4496 mask = GCForeground | GCBackground;
4497 dpy = FRAME_MAC_DISPLAY (f);
4498 window = FRAME_MAC_WINDOW (f);
4499 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
4501 if (gc)
4502 XChangeGC (dpy, gc, mask, &xgcv);
4503 else
4505 gc = XCreateGC (dpy, window, mask, &xgcv);
4506 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4509 if (width < 0)
4510 width = FRAME_CURSOR_WIDTH (f);
4512 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4513 x_clip_to_row (w, row, gc);
4514 XFillRectangle (dpy, window, gc,
4516 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4517 min (cursor_glyph->pixel_width, width),
4518 row->height);
4519 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4524 /* RIF: Define cursor CURSOR on frame F. */
4526 static void
4527 mac_define_frame_cursor (f, cursor)
4528 struct frame *f;
4529 Cursor cursor;
4531 /* MAC TODO */
4535 /* RIF: Clear area on frame F. */
4537 static void
4538 mac_clear_frame_area (f, x, y, width, height)
4539 struct frame *f;
4540 int x, y, width, height;
4542 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4543 x, y, width, height, 0);
4547 /* RIF: Draw cursor on window W. */
4549 static void
4550 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4551 struct window *w;
4552 struct glyph_row *glyph_row;
4553 int x, y;
4554 int cursor_type, cursor_width;
4555 int on_p, active_p;
4557 if (on_p)
4559 w->phys_cursor_type = cursor_type;
4560 w->phys_cursor_width = cursor_width;
4561 w->phys_cursor_on_p = 1;
4563 if (glyph_row->exact_window_width_line_p
4564 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4566 glyph_row->cursor_in_fringe_p = 1;
4567 draw_fringe_bitmap (w, glyph_row, 0);
4568 return;
4571 switch (cursor_type)
4573 case HOLLOW_BOX_CURSOR:
4574 x_draw_hollow_cursor (w, glyph_row);
4575 break;
4577 case FILLED_BOX_CURSOR:
4578 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4579 break;
4581 case HBAR_CURSOR:
4582 /* TODO. For now, just draw bar cursor. */
4583 case BAR_CURSOR:
4584 x_draw_bar_cursor (w, glyph_row, cursor_width);
4585 break;
4587 case NO_CURSOR:
4588 break;
4590 default:
4591 abort ();
4597 /* Icons. */
4599 #if 0 /* MAC_TODO: no icon support yet. */
4601 x_bitmap_icon (f, icon)
4602 struct frame *f;
4603 Lisp_Object icon;
4605 HANDLE hicon;
4607 if (FRAME_W32_WINDOW (f) == 0)
4608 return 1;
4610 if (NILP (icon))
4611 hicon = LoadIcon (hinst, EMACS_CLASS);
4612 else if (STRINGP (icon))
4613 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4614 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4615 else if (SYMBOLP (icon))
4617 LPCTSTR name;
4619 if (EQ (icon, intern ("application")))
4620 name = (LPCTSTR) IDI_APPLICATION;
4621 else if (EQ (icon, intern ("hand")))
4622 name = (LPCTSTR) IDI_HAND;
4623 else if (EQ (icon, intern ("question")))
4624 name = (LPCTSTR) IDI_QUESTION;
4625 else if (EQ (icon, intern ("exclamation")))
4626 name = (LPCTSTR) IDI_EXCLAMATION;
4627 else if (EQ (icon, intern ("asterisk")))
4628 name = (LPCTSTR) IDI_ASTERISK;
4629 else if (EQ (icon, intern ("winlogo")))
4630 name = (LPCTSTR) IDI_WINLOGO;
4631 else
4632 return 1;
4634 hicon = LoadIcon (NULL, name);
4636 else
4637 return 1;
4639 if (hicon == NULL)
4640 return 1;
4642 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4643 (LPARAM) hicon);
4645 return 0;
4647 #endif /* MAC_TODO */
4649 /************************************************************************
4650 Handling X errors
4651 ************************************************************************/
4653 /* Display Error Handling functions not used on W32. Listing them here
4654 helps diff stay in step when comparing w32term.c with xterm.c.
4656 x_error_catcher (display, error)
4657 x_catch_errors (dpy)
4658 x_catch_errors_unwind (old_val)
4659 x_check_errors (dpy, format)
4660 x_had_errors_p (dpy)
4661 x_clear_errors (dpy)
4662 x_uncatch_errors (dpy, count)
4663 x_trace_wire ()
4664 x_connection_signal (signalnum)
4665 x_connection_closed (dpy, error_message)
4666 x_error_quitter (display, error)
4667 x_error_handler (display, error)
4668 x_io_error_quitter (display)
4673 /* Changing the font of the frame. */
4675 /* Give frame F the font named FONTNAME as its default font, and
4676 return the full name of that font. FONTNAME may be a wildcard
4677 pattern; in that case, we choose some font that fits the pattern.
4678 The return value shows which font we chose. */
4680 Lisp_Object
4681 x_new_font (f, fontname)
4682 struct frame *f;
4683 register char *fontname;
4685 struct font_info *fontp
4686 = FS_LOAD_FONT (f, 0, fontname, -1);
4688 if (!fontp)
4689 return Qnil;
4691 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4692 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4693 FRAME_FONTSET (f) = -1;
4695 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4696 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4698 compute_fringe_widths (f, 1);
4700 /* Compute the scroll bar width in character columns. */
4701 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4703 int wid = FRAME_COLUMN_WIDTH (f);
4704 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4705 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4707 else
4709 int wid = FRAME_COLUMN_WIDTH (f);
4710 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4713 /* Now make the frame display the given font. */
4714 if (FRAME_MAC_WINDOW (f) != 0)
4716 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4717 FRAME_FONT (f));
4718 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4719 FRAME_FONT (f));
4720 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4721 FRAME_FONT (f));
4723 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4724 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4727 return build_string (fontp->full_name);
4730 /* Give frame F the fontset named FONTSETNAME as its default font, and
4731 return the full name of that fontset. FONTSETNAME may be a wildcard
4732 pattern; in that case, we choose some fontset that fits the pattern.
4733 The return value shows which fontset we chose. */
4735 Lisp_Object
4736 x_new_fontset (f, fontsetname)
4737 struct frame *f;
4738 char *fontsetname;
4740 int fontset = fs_query_fontset (build_string (fontsetname), 0);
4741 Lisp_Object result;
4743 if (fontset < 0)
4744 return Qnil;
4746 if (FRAME_FONTSET (f) == fontset)
4747 /* This fontset is already set in frame F. There's nothing more
4748 to do. */
4749 return fontset_name (fontset);
4751 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
4753 if (!STRINGP (result))
4754 /* Can't load ASCII font. */
4755 return Qnil;
4757 /* Since x_new_font doesn't update any fontset information, do it now. */
4758 FRAME_FONTSET(f) = fontset;
4760 return build_string (fontsetname);
4764 /***********************************************************************
4765 TODO: W32 Input Methods
4766 ***********************************************************************/
4767 /* Listing missing functions from xterm.c helps diff stay in step.
4769 xim_destroy_callback (xim, client_data, call_data)
4770 xim_open_dpy (dpyinfo, resource_name)
4771 struct xim_inst_t
4772 xim_instantiate_callback (display, client_data, call_data)
4773 xim_initialize (dpyinfo, resource_name)
4774 xim_close_dpy (dpyinfo)
4779 /* Calculate the absolute position in frame F
4780 from its current recorded position values and gravity. */
4782 void
4783 x_calc_absolute_position (f)
4784 struct frame *f;
4786 Point pt;
4787 int flags = f->size_hint_flags;
4789 pt.h = pt.v = 0;
4791 /* Find the position of the outside upper-left corner of
4792 the inner window, with respect to the outer window. */
4793 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
4795 GrafPtr savePort;
4796 GetPort (&savePort);
4798 #if TARGET_API_MAC_CARBON
4799 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
4800 #else
4801 SetPort (FRAME_MAC_WINDOW (f));
4802 #endif
4804 #if TARGET_API_MAC_CARBON
4806 Rect r;
4808 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
4809 SetPt(&pt, r.left, r.top);
4811 #else /* not TARGET_API_MAC_CARBON */
4812 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
4813 #endif /* not TARGET_API_MAC_CARBON */
4814 LocalToGlobal (&pt);
4815 SetPort (savePort);
4818 /* Treat negative positions as relative to the leftmost bottommost
4819 position that fits on the screen. */
4820 if (flags & XNegative)
4821 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
4822 - 2 * f->border_width - pt.h
4823 - FRAME_PIXEL_WIDTH (f)
4824 + f->left_pos);
4825 /* NTEMACS_TODO: Subtract menubar height? */
4826 if (flags & YNegative)
4827 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
4828 - 2 * f->border_width - pt.v
4829 - FRAME_PIXEL_HEIGHT (f)
4830 + f->top_pos);
4831 /* The left_pos and top_pos
4832 are now relative to the top and left screen edges,
4833 so the flags should correspond. */
4834 f->size_hint_flags &= ~ (XNegative | YNegative);
4837 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4838 to really change the position, and 0 when calling from
4839 x_make_frame_visible (in that case, XOFF and YOFF are the current
4840 position values). It is -1 when calling from x_set_frame_parameters,
4841 which means, do adjust for borders but don't change the gravity. */
4843 void
4844 x_set_offset (f, xoff, yoff, change_gravity)
4845 struct frame *f;
4846 register int xoff, yoff;
4847 int change_gravity;
4849 int modified_top, modified_left;
4851 if (change_gravity > 0)
4853 f->top_pos = yoff;
4854 f->left_pos = xoff;
4855 f->size_hint_flags &= ~ (XNegative | YNegative);
4856 if (xoff < 0)
4857 f->size_hint_flags |= XNegative;
4858 if (yoff < 0)
4859 f->size_hint_flags |= YNegative;
4860 f->win_gravity = NorthWestGravity;
4862 x_calc_absolute_position (f);
4864 BLOCK_INPUT;
4865 x_wm_set_size_hint (f, (long) 0, 0);
4867 modified_left = f->left_pos;
4868 modified_top = f->top_pos;
4870 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
4871 modified_top + 42, false);
4873 UNBLOCK_INPUT;
4876 /* Call this to change the size of frame F's x-window.
4877 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4878 for this size change and subsequent size changes.
4879 Otherwise we leave the window gravity unchanged. */
4881 void
4882 x_set_window_size (f, change_gravity, cols, rows)
4883 struct frame *f;
4884 int change_gravity;
4885 int cols, rows;
4887 int pixelwidth, pixelheight;
4889 BLOCK_INPUT;
4891 check_frame_size (f, &rows, &cols);
4892 f->scroll_bar_actual_width
4893 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
4895 compute_fringe_widths (f, 0);
4897 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
4898 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
4900 f->win_gravity = NorthWestGravity;
4901 x_wm_set_size_hint (f, (long) 0, 0);
4903 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
4905 /* Now, strictly speaking, we can't be sure that this is accurate,
4906 but the window manager will get around to dealing with the size
4907 change request eventually, and we'll hear how it went when the
4908 ConfigureNotify event gets here.
4910 We could just not bother storing any of this information here,
4911 and let the ConfigureNotify event set everything up, but that
4912 might be kind of confusing to the Lisp code, since size changes
4913 wouldn't be reported in the frame parameters until some random
4914 point in the future when the ConfigureNotify event arrives.
4916 We pass 1 for DELAY since we can't run Lisp code inside of
4917 a BLOCK_INPUT. */
4918 change_frame_size (f, rows, cols, 0, 1, 0);
4919 FRAME_PIXEL_WIDTH (f) = pixelwidth;
4920 FRAME_PIXEL_HEIGHT (f) = pixelheight;
4922 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4923 receive in the ConfigureNotify event; if we get what we asked
4924 for, then the event won't cause the screen to become garbaged, so
4925 we have to make sure to do it here. */
4926 SET_FRAME_GARBAGED (f);
4928 XFlush (FRAME_X_DISPLAY (f));
4930 /* If cursor was outside the new size, mark it as off. */
4931 mark_window_cursors_off (XWINDOW (f->root_window));
4933 /* Clear out any recollection of where the mouse highlighting was,
4934 since it might be in a place that's outside the new frame size.
4935 Actually checking whether it is outside is a pain in the neck,
4936 so don't try--just let the highlighting be done afresh with new size. */
4937 cancel_mouse_face (f);
4939 UNBLOCK_INPUT;
4942 /* Mouse warping. */
4944 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
4946 void
4947 x_set_mouse_position (f, x, y)
4948 struct frame *f;
4949 int x, y;
4951 int pix_x, pix_y;
4953 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
4954 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
4956 if (pix_x < 0) pix_x = 0;
4957 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
4959 if (pix_y < 0) pix_y = 0;
4960 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
4962 x_set_mouse_pixel_position (f, pix_x, pix_y);
4965 void
4966 x_set_mouse_pixel_position (f, pix_x, pix_y)
4967 struct frame *f;
4968 int pix_x, pix_y;
4970 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
4971 BLOCK_INPUT;
4973 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
4974 0, 0, 0, 0, pix_x, pix_y);
4975 UNBLOCK_INPUT;
4976 #endif
4980 /* focus shifting, raising and lowering. */
4982 void
4983 x_focus_on_frame (f)
4984 struct frame *f;
4986 #if 0 /* This proves to be unpleasant. */
4987 x_raise_frame (f);
4988 #endif
4989 #if 0
4990 /* I don't think that the ICCCM allows programs to do things like this
4991 without the interaction of the window manager. Whatever you end up
4992 doing with this code, do it to x_unfocus_frame too. */
4993 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4994 RevertToPointerRoot, CurrentTime);
4995 #endif /* ! 0 */
4998 void
4999 x_unfocus_frame (f)
5000 struct frame *f;
5004 /* Raise frame F. */
5005 void
5006 x_raise_frame (f)
5007 struct frame *f;
5009 if (f->async_visible)
5010 SelectWindow (FRAME_MAC_WINDOW (f));
5013 /* Lower frame F. */
5014 void
5015 x_lower_frame (f)
5016 struct frame *f;
5018 if (f->async_visible)
5019 SendBehind (FRAME_MAC_WINDOW (f), nil);
5022 static void
5023 XTframe_raise_lower (f, raise_flag)
5024 FRAME_PTR f;
5025 int raise_flag;
5027 if (raise_flag)
5028 x_raise_frame (f);
5029 else
5030 x_lower_frame (f);
5033 /* Change of visibility. */
5035 /* This tries to wait until the frame is really visible.
5036 However, if the window manager asks the user where to position
5037 the frame, this will return before the user finishes doing that.
5038 The frame will not actually be visible at that time,
5039 but it will become visible later when the window manager
5040 finishes with it. */
5042 void
5043 x_make_frame_visible (f)
5044 struct frame *f;
5046 Lisp_Object type;
5047 int original_top, original_left;
5049 BLOCK_INPUT;
5051 if (! FRAME_VISIBLE_P (f))
5053 /* We test FRAME_GARBAGED_P here to make sure we don't
5054 call x_set_offset a second time
5055 if we get to x_make_frame_visible a second time
5056 before the window gets really visible. */
5057 if (! FRAME_ICONIFIED_P (f)
5058 && ! f->output_data.mac->asked_for_visible)
5059 x_set_offset (f, f->left_pos, f->top_pos, 0);
5061 f->output_data.mac->asked_for_visible = 1;
5063 ShowWindow (FRAME_MAC_WINDOW (f));
5066 XFlush (FRAME_MAC_DISPLAY (f));
5068 #if 0 /* MAC_TODO */
5069 /* Synchronize to ensure Emacs knows the frame is visible
5070 before we do anything else. We do this loop with input not blocked
5071 so that incoming events are handled. */
5073 Lisp_Object frame;
5074 int count;
5076 /* This must come after we set COUNT. */
5077 UNBLOCK_INPUT;
5079 XSETFRAME (frame, f);
5081 /* Wait until the frame is visible. Process X events until a
5082 MapNotify event has been seen, or until we think we won't get a
5083 MapNotify at all.. */
5084 for (count = input_signal_count + 10;
5085 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5087 /* Force processing of queued events. */
5088 x_sync (f);
5090 /* Machines that do polling rather than SIGIO have been
5091 observed to go into a busy-wait here. So we'll fake an
5092 alarm signal to let the handler know that there's something
5093 to be read. We used to raise a real alarm, but it seems
5094 that the handler isn't always enabled here. This is
5095 probably a bug. */
5096 if (input_polling_used ())
5098 /* It could be confusing if a real alarm arrives while
5099 processing the fake one. Turn it off and let the
5100 handler reset it. */
5101 extern void poll_for_input_1 P_ ((void));
5102 int old_poll_suppress_count = poll_suppress_count;
5103 poll_suppress_count = 1;
5104 poll_for_input_1 ();
5105 poll_suppress_count = old_poll_suppress_count;
5108 /* See if a MapNotify event has been processed. */
5109 FRAME_SAMPLE_VISIBILITY (f);
5112 #endif /* MAC_TODO */
5115 /* Change from mapped state to withdrawn state. */
5117 /* Make the frame visible (mapped and not iconified). */
5119 void
5120 x_make_frame_invisible (f)
5121 struct frame *f;
5123 /* Don't keep the highlight on an invisible frame. */
5124 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5125 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5127 BLOCK_INPUT;
5129 HideWindow (FRAME_MAC_WINDOW (f));
5131 /* We can't distinguish this from iconification
5132 just by the event that we get from the server.
5133 So we can't win using the usual strategy of letting
5134 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5135 and synchronize with the server to make sure we agree. */
5136 f->visible = 0;
5137 FRAME_ICONIFIED_P (f) = 0;
5138 f->async_visible = 0;
5139 f->async_iconified = 0;
5141 UNBLOCK_INPUT;
5144 /* Change window state from mapped to iconified. */
5146 void
5147 x_iconify_frame (f)
5148 struct frame *f;
5150 /* Don't keep the highlight on an invisible frame. */
5151 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5152 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5154 #if 0
5155 /* Review: Since window is still visible in dock, still allow updates? */
5156 if (f->async_iconified)
5157 return;
5158 #endif
5160 BLOCK_INPUT;
5162 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5164 UNBLOCK_INPUT;
5168 /* Destroy the X window of frame F. */
5170 void
5171 x_destroy_window (f)
5172 struct frame *f;
5174 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5176 BLOCK_INPUT;
5178 DisposeWindow (FRAME_MAC_WINDOW (f));
5180 free_frame_menubar (f);
5181 free_frame_faces (f);
5183 xfree (f->output_data.mac);
5184 f->output_data.mac = 0;
5185 if (f == dpyinfo->x_focus_frame)
5186 dpyinfo->x_focus_frame = 0;
5187 if (f == dpyinfo->x_focus_event_frame)
5188 dpyinfo->x_focus_event_frame = 0;
5189 if (f == dpyinfo->x_highlight_frame)
5190 dpyinfo->x_highlight_frame = 0;
5192 dpyinfo->reference_count--;
5194 if (f == dpyinfo->mouse_face_mouse_frame)
5196 dpyinfo->mouse_face_beg_row
5197 = dpyinfo->mouse_face_beg_col = -1;
5198 dpyinfo->mouse_face_end_row
5199 = dpyinfo->mouse_face_end_col = -1;
5200 dpyinfo->mouse_face_window = Qnil;
5201 dpyinfo->mouse_face_deferred_gc = 0;
5202 dpyinfo->mouse_face_mouse_frame = 0;
5205 UNBLOCK_INPUT;
5208 /* Setting window manager hints. */
5210 /* Set the normal size hints for the window manager, for frame F.
5211 FLAGS is the flags word to use--or 0 meaning preserve the flags
5212 that the window now has.
5213 If USER_POSITION is nonzero, we set the USPosition
5214 flag (this is useful when FLAGS is 0). */
5215 void
5216 x_wm_set_size_hint (f, flags, user_position)
5217 struct frame *f;
5218 long flags;
5219 int user_position;
5221 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5222 XSizeHints size_hints;
5224 #ifdef USE_X_TOOLKIT
5225 Arg al[2];
5226 int ac = 0;
5227 Dimension widget_width, widget_height;
5228 Window window = XtWindow (f->output_data.x->widget);
5229 #else /* not USE_X_TOOLKIT */
5230 Window window = FRAME_X_WINDOW (f);
5231 #endif /* not USE_X_TOOLKIT */
5233 /* Setting PMaxSize caused various problems. */
5234 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5236 size_hints.x = f->left_pos;
5237 size_hints.y = f->top_pos;
5239 #ifdef USE_X_TOOLKIT
5240 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5241 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5242 XtGetValues (f->output_data.x->widget, al, ac);
5243 size_hints.height = widget_height;
5244 size_hints.width = widget_width;
5245 #else /* not USE_X_TOOLKIT */
5246 size_hints.height = FRAME_PIXEL_HEIGHT (f);
5247 size_hints.width = FRAME_PIXEL_WIDTH (f);
5248 #endif /* not USE_X_TOOLKIT */
5250 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
5251 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
5252 size_hints.max_width
5253 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5254 size_hints.max_height
5255 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5257 /* Calculate the base and minimum sizes.
5259 (When we use the X toolkit, we don't do it here.
5260 Instead we copy the values that the widgets are using, below.) */
5261 #ifndef USE_X_TOOLKIT
5263 int base_width, base_height;
5264 int min_rows = 0, min_cols = 0;
5266 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5267 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5269 check_frame_size (f, &min_rows, &min_cols);
5271 /* The window manager uses the base width hints to calculate the
5272 current number of rows and columns in the frame while
5273 resizing; min_width and min_height aren't useful for this
5274 purpose, since they might not give the dimensions for a
5275 zero-row, zero-column frame.
5277 We use the base_width and base_height members if we have
5278 them; otherwise, we set the min_width and min_height members
5279 to the size for a zero x zero frame. */
5281 #ifdef HAVE_X11R4
5282 size_hints.flags |= PBaseSize;
5283 size_hints.base_width = base_width;
5284 size_hints.base_height = base_height;
5285 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5286 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5287 #else
5288 size_hints.min_width = base_width;
5289 size_hints.min_height = base_height;
5290 #endif
5293 /* If we don't need the old flags, we don't need the old hint at all. */
5294 if (flags)
5296 size_hints.flags |= flags;
5297 goto no_read;
5299 #endif /* not USE_X_TOOLKIT */
5302 XSizeHints hints; /* Sometimes I hate X Windows... */
5303 long supplied_return;
5304 int value;
5306 #ifdef HAVE_X11R4
5307 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5308 &supplied_return);
5309 #else
5310 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5311 #endif
5313 #ifdef USE_X_TOOLKIT
5314 size_hints.base_height = hints.base_height;
5315 size_hints.base_width = hints.base_width;
5316 size_hints.min_height = hints.min_height;
5317 size_hints.min_width = hints.min_width;
5318 #endif
5320 if (flags)
5321 size_hints.flags |= flags;
5322 else
5324 if (value == 0)
5325 hints.flags = 0;
5326 if (hints.flags & PSize)
5327 size_hints.flags |= PSize;
5328 if (hints.flags & PPosition)
5329 size_hints.flags |= PPosition;
5330 if (hints.flags & USPosition)
5331 size_hints.flags |= USPosition;
5332 if (hints.flags & USSize)
5333 size_hints.flags |= USSize;
5337 #ifndef USE_X_TOOLKIT
5338 no_read:
5339 #endif
5341 #ifdef PWinGravity
5342 size_hints.win_gravity = f->win_gravity;
5343 size_hints.flags |= PWinGravity;
5345 if (user_position)
5347 size_hints.flags &= ~ PPosition;
5348 size_hints.flags |= USPosition;
5350 #endif /* PWinGravity */
5352 #ifdef HAVE_X11R4
5353 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5354 #else
5355 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5356 #endif
5357 #endif /* MAC_TODO */
5360 #if 0 /* MAC_TODO: hide application instead of iconify? */
5361 /* Used for IconicState or NormalState */
5363 void
5364 x_wm_set_window_state (f, state)
5365 struct frame *f;
5366 int state;
5368 #ifdef USE_X_TOOLKIT
5369 Arg al[1];
5371 XtSetArg (al[0], XtNinitialState, state);
5372 XtSetValues (f->output_data.x->widget, al, 1);
5373 #else /* not USE_X_TOOLKIT */
5374 Window window = FRAME_X_WINDOW (f);
5376 f->output_data.x->wm_hints.flags |= StateHint;
5377 f->output_data.x->wm_hints.initial_state = state;
5379 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5380 #endif /* not USE_X_TOOLKIT */
5383 void
5384 x_wm_set_icon_pixmap (f, pixmap_id)
5385 struct frame *f;
5386 int pixmap_id;
5388 Pixmap icon_pixmap;
5390 #ifndef USE_X_TOOLKIT
5391 Window window = FRAME_X_WINDOW (f);
5392 #endif
5394 if (pixmap_id > 0)
5396 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5397 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5399 else
5401 /* It seems there is no way to turn off use of an icon pixmap.
5402 The following line does it, only if no icon has yet been created,
5403 for some window managers. But with mwm it crashes.
5404 Some people say it should clear the IconPixmapHint bit in this case,
5405 but that doesn't work, and the X consortium said it isn't the
5406 right thing at all. Since there is no way to win,
5407 best to explicitly give up. */
5408 #if 0
5409 f->output_data.x->wm_hints.icon_pixmap = None;
5410 #else
5411 return;
5412 #endif
5415 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5418 Arg al[1];
5419 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5420 XtSetValues (f->output_data.x->widget, al, 1);
5423 #else /* not USE_X_TOOLKIT */
5425 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5426 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5428 #endif /* not USE_X_TOOLKIT */
5431 #endif /* MAC_TODO */
5433 void
5434 x_wm_set_icon_position (f, icon_x, icon_y)
5435 struct frame *f;
5436 int icon_x, icon_y;
5438 #if 0 /* MAC_TODO: no icons on Mac */
5439 #ifdef USE_X_TOOLKIT
5440 Window window = XtWindow (f->output_data.x->widget);
5441 #else
5442 Window window = FRAME_X_WINDOW (f);
5443 #endif
5445 f->output_data.x->wm_hints.flags |= IconPositionHint;
5446 f->output_data.x->wm_hints.icon_x = icon_x;
5447 f->output_data.x->wm_hints.icon_y = icon_y;
5449 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5450 #endif /* MAC_TODO */
5454 /***********************************************************************
5455 Fonts
5456 ***********************************************************************/
5458 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5460 struct font_info *
5461 x_get_font_info (f, font_idx)
5462 FRAME_PTR f;
5463 int font_idx;
5465 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5468 /* the global font name table */
5469 char **font_name_table = NULL;
5470 int font_name_table_size = 0;
5471 int font_name_count = 0;
5473 /* compare two strings ignoring case */
5474 static int
5475 stricmp (const char *s, const char *t)
5477 for ( ; tolower (*s) == tolower (*t); s++, t++)
5478 if (*s == '\0')
5479 return 0;
5480 return tolower (*s) - tolower (*t);
5483 /* compare two strings ignoring case and handling wildcard */
5484 static int
5485 wildstrieq (char *s1, char *s2)
5487 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5488 return true;
5490 return stricmp (s1, s2) == 0;
5493 /* Assume parameter 1 is fully qualified, no wildcards. */
5494 static int
5495 mac_font_pattern_match (fontname, pattern)
5496 char * fontname;
5497 char * pattern;
5499 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5500 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5501 char *ptr;
5503 /* Copy fontname so we can modify it during comparison. */
5504 strcpy (font_name_copy, fontname);
5506 ptr = regex;
5507 *ptr++ = '^';
5509 /* Turn pattern into a regexp and do a regexp match. */
5510 for (; *pattern; pattern++)
5512 if (*pattern == '?')
5513 *ptr++ = '.';
5514 else if (*pattern == '*')
5516 *ptr++ = '.';
5517 *ptr++ = '*';
5519 else
5520 *ptr++ = *pattern;
5522 *ptr = '$';
5523 *(ptr + 1) = '\0';
5525 return (fast_c_string_match_ignore_case (build_string (regex),
5526 font_name_copy) >= 0);
5529 /* Two font specs are considered to match if their foundry, family,
5530 weight, slant, and charset match. */
5531 static int
5532 mac_font_match (char *mf, char *xf)
5534 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5535 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5537 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5538 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5539 return mac_font_pattern_match (mf, xf);
5541 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5542 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5543 return mac_font_pattern_match (mf, xf);
5545 return (wildstrieq (m_foundry, x_foundry)
5546 && wildstrieq (m_family, x_family)
5547 && wildstrieq (m_weight, x_weight)
5548 && wildstrieq (m_slant, x_slant)
5549 && wildstrieq (m_charset, x_charset))
5550 || mac_font_pattern_match (mf, xf);
5554 static char *
5555 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
5557 char foundry[32], family[32], cs[32];
5558 char xf[255], *result, *p;
5560 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5562 strcpy(foundry, "Apple");
5563 strcpy(family, name);
5565 switch (scriptcode)
5567 case smTradChinese:
5568 strcpy(cs, "big5-0");
5569 break;
5570 case smSimpChinese:
5571 strcpy(cs, "gb2312.1980-0");
5572 break;
5573 case smJapanese:
5574 strcpy(cs, "jisx0208.1983-sjis");
5575 break;
5576 case -smJapanese:
5577 /* Each Apple Japanese font is entered into the font table
5578 twice: once as a jisx0208.1983-sjis font and once as a
5579 jisx0201.1976-0 font. The latter can be used to display
5580 the ascii charset and katakana-jisx0201 charset. A
5581 negative script code signals that the name of this latter
5582 font is being built. */
5583 strcpy(cs, "jisx0201.1976-0");
5584 break;
5585 case smKorean:
5586 strcpy(cs, "ksc5601.1989-0");
5587 break;
5588 default:
5589 strcpy(cs, "mac-roman");
5590 break;
5594 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5595 foundry, family, style & bold ? "bold" : "medium",
5596 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5598 result = (char *) xmalloc (strlen (xf) + 1);
5599 strcpy (result, xf);
5600 for (p = result; *p; p++)
5601 *p = tolower(*p);
5602 return result;
5606 /* Convert an X font spec to the corresponding mac font name, which
5607 can then be passed to GetFNum after conversion to a Pascal string.
5608 For ordinary Mac fonts, this should just be their names, like
5609 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5610 collection contain their charset designation in their names, like
5611 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5612 names are handled accordingly. */
5613 static void
5614 x_font_name_to_mac_font_name (char *xf, char *mf)
5616 char foundry[32], family[32], weight[20], slant[2], cs[32];
5618 strcpy (mf, "");
5620 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5621 foundry, family, weight, slant, cs) != 5 &&
5622 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5623 foundry, family, weight, slant, cs) != 5)
5624 return;
5626 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
5627 || strcmp (cs, "jisx0208.1983-sjis") == 0
5628 || strcmp (cs, "jisx0201.1976-0") == 0
5629 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
5630 strcpy(mf, family);
5631 else
5632 sprintf(mf, "%s-%s-%s", foundry, family, cs);
5636 static void
5637 add_font_name_table_entry (char *font_name)
5639 if (font_name_table_size == 0)
5641 font_name_table_size = 16;
5642 font_name_table = (char **)
5643 xmalloc (font_name_table_size * sizeof (char *));
5645 else if (font_name_count + 1 >= font_name_table_size)
5647 font_name_table_size += 16;
5648 font_name_table = (char **)
5649 xrealloc (font_name_table,
5650 font_name_table_size * sizeof (char *));
5653 font_name_table[font_name_count++] = font_name;
5656 /* Sets up the table font_name_table to contain the list of all fonts
5657 in the system the first time the table is used so that the Resource
5658 Manager need not be accessed every time this information is
5659 needed. */
5661 static void
5662 init_font_name_table ()
5664 #if TARGET_API_MAC_CARBON
5665 SInt32 sv;
5667 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
5669 FMFontFamilyIterator ffi;
5670 FMFontFamilyInstanceIterator ffii;
5671 FMFontFamily ff;
5673 /* Create a dummy instance iterator here to avoid creating and
5674 destroying it in the loop. */
5675 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
5676 return;
5677 /* Create an iterator to enumerate the font families. */
5678 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
5679 != noErr)
5681 FMDisposeFontFamilyInstanceIterator (&ffii);
5682 return;
5685 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
5687 Str255 name;
5688 FMFont font;
5689 FMFontStyle style;
5690 FMFontSize size;
5691 SInt16 sc;
5693 if (FMGetFontFamilyName (ff, name) != noErr)
5694 break;
5695 p2cstr (name);
5697 sc = FontToScript (ff);
5699 /* Point the instance iterator at the current font family. */
5700 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
5701 break;
5703 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
5704 == noErr)
5705 if (size == 0)
5707 add_font_name_table_entry (mac_to_x_fontname (name, size,
5708 style, sc));
5709 add_font_name_table_entry (mac_to_x_fontname (name, size,
5710 italic, sc));
5711 add_font_name_table_entry (mac_to_x_fontname (name, size,
5712 bold, sc));
5713 add_font_name_table_entry (mac_to_x_fontname (name, size,
5714 italic | bold,
5715 sc));
5717 else
5719 add_font_name_table_entry (mac_to_x_fontname (name, size,
5720 style, sc));
5721 if (smJapanese == sc)
5722 add_font_name_table_entry (mac_to_x_fontname (name, size,
5723 style,
5724 -smJapanese));
5728 /* Dispose of the iterators. */
5729 FMDisposeFontFamilyIterator (&ffi);
5730 FMDisposeFontFamilyInstanceIterator (&ffii);
5732 else
5734 #endif /* TARGET_API_MAC_CARBON */
5735 GrafPtr port;
5736 SInt16 fontnum, old_fontnum;
5737 int num_mac_fonts = CountResources('FOND');
5738 int i, j;
5739 Handle font_handle, font_handle_2;
5740 short id, scriptcode;
5741 ResType type;
5742 Str32 name;
5743 struct FontAssoc *fat;
5744 struct AsscEntry *assc_entry;
5746 GetPort (&port); /* save the current font number used */
5747 #if TARGET_API_MAC_CARBON
5748 old_fontnum = GetPortTextFont (port);
5749 #else
5750 old_fontnum = port->txFont;
5751 #endif
5753 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
5755 font_handle = GetIndResource ('FOND', i);
5756 if (!font_handle)
5757 continue;
5759 GetResInfo (font_handle, &id, &type, name);
5760 GetFNum (name, &fontnum);
5761 p2cstr (name);
5762 if (fontnum == 0)
5763 continue;
5765 TextFont (fontnum);
5766 scriptcode = FontToScript (fontnum);
5769 HLock (font_handle);
5771 if (GetResourceSizeOnDisk (font_handle)
5772 >= sizeof (struct FamRec))
5774 fat = (struct FontAssoc *) (*font_handle
5775 + sizeof (struct FamRec));
5776 assc_entry
5777 = (struct AsscEntry *) (*font_handle
5778 + sizeof (struct FamRec)
5779 + sizeof (struct FontAssoc));
5781 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
5783 if (font_name_table_size == 0)
5785 font_name_table_size = 16;
5786 font_name_table = (char **)
5787 xmalloc (font_name_table_size * sizeof (char *));
5789 else if (font_name_count >= font_name_table_size)
5791 font_name_table_size += 16;
5792 font_name_table = (char **)
5793 xrealloc (font_name_table,
5794 font_name_table_size * sizeof (char *));
5796 font_name_table[font_name_count++]
5797 = mac_to_x_fontname (name,
5798 assc_entry->fontSize,
5799 assc_entry->fontStyle,
5800 scriptcode);
5801 /* Both jisx0208.1983-sjis and
5802 jisx0201.1976-sjis parts are contained in
5803 Apple Japanese (SJIS) font. */
5804 if (smJapanese == scriptcode)
5806 font_name_table[font_name_count++]
5807 = mac_to_x_fontname (name,
5808 assc_entry->fontSize,
5809 assc_entry->fontStyle,
5810 -smJapanese);
5815 HUnlock (font_handle);
5816 font_handle_2 = GetNextFOND (font_handle);
5817 ReleaseResource (font_handle);
5818 font_handle = font_handle_2;
5820 while (ResError () == noErr && font_handle);
5823 TextFont (old_fontnum);
5824 #if TARGET_API_MAC_CARBON
5826 #endif /* TARGET_API_MAC_CARBON */
5830 /* Return a list of at most MAXNAMES font specs matching the one in
5831 PATTERN. Cache matching fonts for patterns in
5832 dpyinfo->name_list_element to avoid looking them up again by
5833 calling mac_font_pattern_match (slow). Return as many matching
5834 fonts as possible if MAXNAMES = -1. */
5836 Lisp_Object
5837 x_list_fonts (struct frame *f,
5838 Lisp_Object pattern,
5839 int size,
5840 int maxnames)
5842 char *ptnstr;
5843 Lisp_Object newlist = Qnil, tem, key;
5844 int n_fonts = 0;
5845 int i;
5846 struct gcpro gcpro1, gcpro2;
5847 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
5849 if (font_name_table == NULL) /* Initialize when first used. */
5850 init_font_name_table ();
5852 if (dpyinfo)
5854 tem = XCDR (dpyinfo->name_list_element);
5855 key = Fcons (pattern, make_number (maxnames));
5857 newlist = Fassoc (key, tem);
5858 if (!NILP (newlist))
5860 newlist = Fcdr_safe (newlist);
5861 goto label_cached;
5865 ptnstr = SDATA (pattern);
5867 GCPRO2 (pattern, newlist);
5869 /* Scan and matching bitmap fonts. */
5870 for (i = 0; i < font_name_count; i++)
5872 if (mac_font_pattern_match (font_name_table[i], ptnstr))
5874 newlist = Fcons (build_string (font_name_table[i]), newlist);
5876 n_fonts++;
5877 if (maxnames > 0 && n_fonts >= maxnames)
5878 break;
5882 /* MAC_TODO: add code for matching outline fonts here */
5884 UNGCPRO;
5886 if (dpyinfo)
5888 XSETCDR (dpyinfo->name_list_element,
5889 Fcons (Fcons (key, newlist),
5890 XCDR (dpyinfo->name_list_element)));
5892 label_cached:
5894 return newlist;
5898 #if GLYPH_DEBUG
5900 /* Check that FONT is valid on frame F. It is if it can be found in F's
5901 font table. */
5903 static void
5904 x_check_font (f, font)
5905 struct frame *f;
5906 XFontStruct *font;
5908 int i;
5909 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5911 xassert (font != NULL);
5913 for (i = 0; i < dpyinfo->n_fonts; i++)
5914 if (dpyinfo->font_table[i].name
5915 && font == dpyinfo->font_table[i].font)
5916 break;
5918 xassert (i < dpyinfo->n_fonts);
5921 #endif /* GLYPH_DEBUG != 0 */
5923 /* Set *W to the minimum width, *H to the minimum font height of FONT.
5924 Note: There are (broken) X fonts out there with invalid XFontStruct
5925 min_bounds contents. For example, handa@etl.go.jp reports that
5926 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
5927 have font->min_bounds.width == 0. */
5929 static INLINE void
5930 x_font_min_bounds (font, w, h)
5931 MacFontStruct *font;
5932 int *w, *h;
5935 * TODO: Windows does not appear to offer min bound, only
5936 * average and maximum width, and maximum height.
5938 *h = FONT_HEIGHT (font);
5939 *w = FONT_WIDTH (font);
5943 /* Compute the smallest character width and smallest font height over
5944 all fonts available on frame F. Set the members smallest_char_width
5945 and smallest_font_height in F's x_display_info structure to
5946 the values computed. Value is non-zero if smallest_font_height or
5947 smallest_char_width become smaller than they were before. */
5950 x_compute_min_glyph_bounds (f)
5951 struct frame *f;
5953 int i;
5954 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5955 MacFontStruct *font;
5956 int old_width = dpyinfo->smallest_char_width;
5957 int old_height = dpyinfo->smallest_font_height;
5959 dpyinfo->smallest_font_height = 100000;
5960 dpyinfo->smallest_char_width = 100000;
5962 for (i = 0; i < dpyinfo->n_fonts; ++i)
5963 if (dpyinfo->font_table[i].name)
5965 struct font_info *fontp = dpyinfo->font_table + i;
5966 int w, h;
5968 font = (MacFontStruct *) fontp->font;
5969 xassert (font != (MacFontStruct *) ~0);
5970 x_font_min_bounds (font, &w, &h);
5972 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
5973 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
5976 xassert (dpyinfo->smallest_char_width > 0
5977 && dpyinfo->smallest_font_height > 0);
5979 return (dpyinfo->n_fonts == 1
5980 || dpyinfo->smallest_char_width < old_width
5981 || dpyinfo->smallest_font_height < old_height);
5985 /* Determine whether given string is a fully-specified XLFD: all 14
5986 fields are present, none is '*'. */
5988 static int
5989 is_fully_specified_xlfd (char *p)
5991 int i;
5992 char *q;
5994 if (*p != '-')
5995 return 0;
5997 for (i = 0; i < 13; i++)
5999 q = strchr (p + 1, '-');
6000 if (q == NULL)
6001 return 0;
6002 if (q - p == 2 && *(p + 1) == '*')
6003 return 0;
6004 p = q;
6007 if (strchr (p + 1, '-') != NULL)
6008 return 0;
6010 if (*(p + 1) == '*' && *(p + 2) == '\0')
6011 return 0;
6013 return 1;
6017 const int kDefaultFontSize = 9;
6020 /* XLoadQueryFont creates and returns an internal representation for a
6021 font in a MacFontStruct struct. There is really no concept
6022 corresponding to "loading" a font on the Mac. But we check its
6023 existence and find the font number and all other information for it
6024 and store them in the returned MacFontStruct. */
6026 static MacFontStruct *
6027 XLoadQueryFont (Display *dpy, char *fontname)
6029 int i, size, is_two_byte_font, char_width;
6030 char *name;
6031 GrafPtr port;
6032 SInt16 old_fontnum, old_fontsize;
6033 Style old_fontface;
6034 Str32 mfontname;
6035 SInt16 fontnum;
6036 Style fontface = normal;
6037 MacFontStruct *font;
6038 FontInfo the_fontinfo;
6039 char s_weight[7], c_slant;
6041 if (is_fully_specified_xlfd (fontname))
6042 name = fontname;
6043 else
6045 for (i = 0; i < font_name_count; i++)
6046 if (mac_font_pattern_match (font_name_table[i], fontname))
6047 break;
6049 if (i >= font_name_count)
6050 return NULL;
6052 name = font_name_table[i];
6055 GetPort (&port); /* save the current font number used */
6056 #if TARGET_API_MAC_CARBON
6057 old_fontnum = GetPortTextFont (port);
6058 old_fontsize = GetPortTextSize (port);
6059 old_fontface = GetPortTextFace (port);
6060 #else
6061 old_fontnum = port->txFont;
6062 old_fontsize = port->txSize;
6063 old_fontface = port->txFace;
6064 #endif
6066 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6067 size = kDefaultFontSize;
6069 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6070 if (strcmp (s_weight, "bold") == 0)
6071 fontface |= bold;
6073 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6074 if (c_slant == 'i')
6075 fontface |= italic;
6077 x_font_name_to_mac_font_name (name, mfontname);
6078 c2pstr (mfontname);
6079 GetFNum (mfontname, &fontnum);
6080 if (fontnum == 0)
6081 return NULL;
6083 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6085 font->fontname = (char *) xmalloc (strlen (name) + 1);
6086 bcopy (name, font->fontname, strlen (name) + 1);
6088 font->mac_fontnum = fontnum;
6089 font->mac_fontsize = size;
6090 font->mac_fontface = fontface;
6091 font->mac_scriptcode = FontToScript (fontnum);
6093 /* Apple Japanese (SJIS) font is listed as both
6094 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6095 (Roman script) in init_font_name_table (). The latter should be
6096 treated as a one-byte font. */
6098 char cs[32];
6100 if (sscanf (name,
6101 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6102 cs) == 1
6103 && 0 == strcmp (cs, "jisx0201.1976-0"))
6104 font->mac_scriptcode = smRoman;
6107 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6108 font->mac_scriptcode == smTradChinese ||
6109 font->mac_scriptcode == smSimpChinese ||
6110 font->mac_scriptcode == smKorean;
6112 TextFont (fontnum);
6113 TextSize (size);
6114 TextFace (fontface);
6116 GetFontInfo (&the_fontinfo);
6118 font->ascent = the_fontinfo.ascent;
6119 font->descent = the_fontinfo.descent;
6121 font->min_byte1 = 0;
6122 if (is_two_byte_font)
6123 font->max_byte1 = 1;
6124 else
6125 font->max_byte1 = 0;
6126 font->min_char_or_byte2 = 0x20;
6127 font->max_char_or_byte2 = 0xff;
6129 if (is_two_byte_font)
6131 /* Use the width of an "ideographic space" of that font because
6132 the_fontinfo.widMax returns the wrong width for some fonts. */
6133 switch (font->mac_scriptcode)
6135 case smJapanese:
6136 char_width = StringWidth("\p\x81\x40");
6137 break;
6138 case smTradChinese:
6139 char_width = StringWidth("\p\xa1\x40");
6140 break;
6141 case smSimpChinese:
6142 char_width = StringWidth("\p\xa1\xa1");
6143 break;
6144 case smKorean:
6145 char_width = StringWidth("\p\xa1\xa1");
6146 break;
6149 else
6150 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6151 returns 15 for 12-point Monaco! */
6152 char_width = CharWidth ('m');
6154 font->max_bounds.rbearing = char_width;
6155 font->max_bounds.lbearing = 0;
6156 font->max_bounds.width = char_width;
6157 font->max_bounds.ascent = the_fontinfo.ascent;
6158 font->max_bounds.descent = the_fontinfo.descent;
6160 font->min_bounds = font->max_bounds;
6162 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6163 font->per_char = NULL;
6164 else
6166 font->per_char = (XCharStruct *)
6167 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6169 int c;
6171 for (c = 0x20; c <= 0xff; c++)
6173 font->per_char[c - 0x20] = font->max_bounds;
6174 font->per_char[c - 0x20].width = CharWidth (c);
6179 TextFont (old_fontnum); /* restore previous font number, size and face */
6180 TextSize (old_fontsize);
6181 TextFace (old_fontface);
6183 return font;
6187 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6188 pointer to the structure font_info while allocating it dynamically.
6189 If SIZE is 0, load any size of font.
6190 If loading is failed, return NULL. */
6192 struct font_info *
6193 x_load_font (f, fontname, size)
6194 struct frame *f;
6195 register char *fontname;
6196 int size;
6198 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6199 Lisp_Object font_names;
6201 /* Get a list of all the fonts that match this name. Once we
6202 have a list of matching fonts, we compare them against the fonts
6203 we already have by comparing names. */
6204 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6206 if (!NILP (font_names))
6208 Lisp_Object tail;
6209 int i;
6211 for (i = 0; i < dpyinfo->n_fonts; i++)
6212 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6213 if (dpyinfo->font_table[i].name
6214 && (!strcmp (dpyinfo->font_table[i].name,
6215 SDATA (XCAR (tail)))
6216 || !strcmp (dpyinfo->font_table[i].full_name,
6217 SDATA (XCAR (tail)))))
6218 return (dpyinfo->font_table + i);
6221 /* Load the font and add it to the table. */
6223 char *full_name;
6224 struct MacFontStruct *font;
6225 struct font_info *fontp;
6226 unsigned long value;
6227 int i;
6229 /* If we have found fonts by x_list_font, load one of them. If
6230 not, we still try to load a font by the name given as FONTNAME
6231 because XListFonts (called in x_list_font) of some X server has
6232 a bug of not finding a font even if the font surely exists and
6233 is loadable by XLoadQueryFont. */
6234 if (size > 0 && !NILP (font_names))
6235 fontname = (char *) SDATA (XCAR (font_names));
6237 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6238 if (!font)
6239 return NULL;
6241 /* Find a free slot in the font table. */
6242 for (i = 0; i < dpyinfo->n_fonts; ++i)
6243 if (dpyinfo->font_table[i].name == NULL)
6244 break;
6246 /* If no free slot found, maybe enlarge the font table. */
6247 if (i == dpyinfo->n_fonts
6248 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6250 int sz;
6251 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6252 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6253 dpyinfo->font_table
6254 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6257 fontp = dpyinfo->font_table + i;
6258 if (i == dpyinfo->n_fonts)
6259 ++dpyinfo->n_fonts;
6261 /* Now fill in the slots of *FONTP. */
6262 BLOCK_INPUT;
6263 bzero (fontp, sizeof (*fontp));
6264 fontp->font = font;
6265 fontp->font_idx = i;
6266 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6267 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6269 fontp->full_name = fontp->name;
6271 fontp->size = font->max_bounds.width;
6272 fontp->height = FONT_HEIGHT (font);
6274 /* For some font, ascent and descent in max_bounds field is
6275 larger than the above value. */
6276 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6277 if (max_height > fontp->height)
6278 fontp->height = max_height;
6281 /* The slot `encoding' specifies how to map a character
6282 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6283 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6284 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6285 2:0xA020..0xFF7F). For the moment, we don't know which charset
6286 uses this font. So, we set information in fontp->encoding[1]
6287 which is never used by any charset. If mapping can't be
6288 decided, set FONT_ENCODING_NOT_DECIDED. */
6289 if (font->mac_scriptcode == smJapanese)
6290 fontp->encoding[1] = 4;
6291 else
6293 fontp->encoding[1]
6294 = (font->max_byte1 == 0
6295 /* 1-byte font */
6296 ? (font->min_char_or_byte2 < 0x80
6297 ? (font->max_char_or_byte2 < 0x80
6298 ? 0 /* 0x20..0x7F */
6299 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6300 : 1) /* 0xA0..0xFF */
6301 /* 2-byte font */
6302 : (font->min_byte1 < 0x80
6303 ? (font->max_byte1 < 0x80
6304 ? (font->min_char_or_byte2 < 0x80
6305 ? (font->max_char_or_byte2 < 0x80
6306 ? 0 /* 0x2020..0x7F7F */
6307 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6308 : 3) /* 0x20A0..0x7FFF */
6309 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6310 : (font->min_char_or_byte2 < 0x80
6311 ? (font->max_char_or_byte2 < 0x80
6312 ? 2 /* 0xA020..0xFF7F */
6313 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6314 : 1))); /* 0xA0A0..0xFFFF */
6317 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6318 fontp->baseline_offset
6319 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6320 ? (long) value : 0);
6321 fontp->relative_compose
6322 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6323 ? (long) value : 0);
6324 fontp->default_ascent
6325 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6326 ? (long) value : 0);
6327 #else
6328 fontp->baseline_offset = 0;
6329 fontp->relative_compose = 0;
6330 fontp->default_ascent = 0;
6331 #endif
6333 /* Set global flag fonts_changed_p to non-zero if the font loaded
6334 has a character with a smaller width than any other character
6335 before, or if the font loaded has a smalle>r height than any
6336 other font loaded before. If this happens, it will make a
6337 glyph matrix reallocation necessary. */
6338 fonts_changed_p = x_compute_min_glyph_bounds (f);
6339 UNBLOCK_INPUT;
6340 return fontp;
6345 /* Return a pointer to struct font_info of a font named FONTNAME for
6346 frame F. If no such font is loaded, return NULL. */
6348 struct font_info *
6349 x_query_font (f, fontname)
6350 struct frame *f;
6351 register char *fontname;
6353 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6354 int i;
6356 for (i = 0; i < dpyinfo->n_fonts; i++)
6357 if (dpyinfo->font_table[i].name
6358 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6359 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6360 return (dpyinfo->font_table + i);
6361 return NULL;
6365 /* Find a CCL program for a font specified by FONTP, and set the member
6366 `encoder' of the structure. */
6368 void
6369 x_find_ccl_program (fontp)
6370 struct font_info *fontp;
6372 Lisp_Object list, elt;
6374 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6376 elt = XCAR (list);
6377 if (CONSP (elt)
6378 && STRINGP (XCAR (elt))
6379 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6380 >= 0))
6381 break;
6383 if (! NILP (list))
6385 struct ccl_program *ccl
6386 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6388 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6389 xfree (ccl);
6390 else
6391 fontp->font_encoder = ccl;
6397 /* The Mac Event loop code */
6399 #ifndef MAC_OSX
6400 #include <Events.h>
6401 #include <Quickdraw.h>
6402 #include <Balloons.h>
6403 #include <Devices.h>
6404 #include <Fonts.h>
6405 #include <Gestalt.h>
6406 #include <Menus.h>
6407 #include <Processes.h>
6408 #include <Sound.h>
6409 #include <ToolUtils.h>
6410 #include <TextUtils.h>
6411 #include <Dialogs.h>
6412 #include <Script.h>
6413 #include <Types.h>
6414 #include <TextEncodingConverter.h>
6415 #include <Resources.h>
6417 #if __MWERKS__
6418 #include <unix.h>
6419 #endif
6420 #endif /* ! MAC_OSX */
6422 #define M_APPLE 128
6423 #define I_ABOUT 1
6425 #define WINDOW_RESOURCE 128
6426 #define TERM_WINDOW_RESOURCE 129
6428 #define DEFAULT_NUM_COLS 80
6430 #define MIN_DOC_SIZE 64
6431 #define MAX_DOC_SIZE 32767
6433 /* sleep time for WaitNextEvent */
6434 #define WNE_SLEEP_AT_SUSPEND 10
6435 #define WNE_SLEEP_AT_RESUME 1
6437 /* true when cannot handle any Mac OS events */
6438 static int handling_window_update = 0;
6440 /* the flag appl_is_suspended is used both for determining the sleep
6441 time to be passed to WaitNextEvent and whether the cursor should be
6442 drawn when updating the display. The cursor is turned off when
6443 Emacs is suspended. Redrawing it is unnecessary and what needs to
6444 be done depends on whether the cursor lies inside or outside the
6445 redraw region. So we might as well skip drawing it when Emacs is
6446 suspended. */
6447 static Boolean app_is_suspended = false;
6448 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
6450 #define EXTRA_STACK_ALLOC (256 * 1024)
6452 #define ARGV_STRING_LIST_ID 129
6453 #define ABOUT_ALERT_ID 128
6454 #define RAM_TOO_LARGE_ALERT_ID 129
6456 Boolean terminate_flag = false;
6458 /* True if using command key as meta key. */
6459 Lisp_Object Vmac_command_key_is_meta;
6461 /* True if the ctrl and meta keys should be reversed. */
6462 Lisp_Object Vmac_reverse_ctrl_meta;
6464 #if USE_CARBON_EVENTS
6465 /* True if the mouse wheel button (i.e. button 4) should map to
6466 mouse-2, instead of mouse-3. */
6467 Lisp_Object Vmac_wheel_button_is_mouse_2;
6469 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
6470 for processing before Emacs sees it. */
6471 Lisp_Object Vmac_pass_command_to_system;
6473 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
6474 for processing before Emacs sees it. */
6475 Lisp_Object Vmac_pass_control_to_system;
6476 #endif
6478 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
6479 to this text encoding */
6480 int mac_keyboard_text_encoding;
6481 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
6483 /* Set in term/mac-win.el to indicate that event loop can now generate
6484 drag and drop events. */
6485 Lisp_Object Qmac_ready_for_drag_n_drop;
6487 Lisp_Object drag_and_drop_file_list;
6489 Point saved_menu_event_location;
6491 /* Apple Events */
6492 static void init_required_apple_events (void);
6493 static pascal OSErr
6494 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
6495 static pascal OSErr
6496 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
6497 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
6498 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
6500 /* Drag and Drop */
6501 static OSErr init_mac_drag_n_drop ();
6502 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
6504 #if USE_CARBON_EVENTS
6505 /* Preliminary Support for the OSX Services Menu */
6506 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
6507 static void init_service_handler ();
6508 #endif
6510 extern void init_emacs_passwd_dir ();
6511 extern int emacs_main (int, char **, char **);
6512 extern void check_alarm ();
6514 extern void initialize_applescript();
6515 extern void terminate_applescript();
6517 static unsigned int
6518 #if USE_CARBON_EVENTS
6519 mac_to_emacs_modifiers (UInt32 mods)
6520 #else
6521 mac_to_emacs_modifiers (EventModifiers mods)
6522 #endif
6524 unsigned int result = 0;
6525 if (mods & macShiftKey)
6526 result |= shift_modifier;
6527 if (mods & macCtrlKey)
6528 result |= ctrl_modifier;
6529 if (mods & macMetaKey)
6530 result |= meta_modifier;
6531 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
6532 result |= alt_modifier;
6533 return result;
6536 #if USE_CARBON_EVENTS
6537 /* Obtains the event modifiers from the event ref and then calls
6538 mac_to_emacs_modifiers. */
6539 static int
6540 mac_event_to_emacs_modifiers (EventRef eventRef)
6542 UInt32 mods = 0;
6543 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
6544 sizeof (UInt32), NULL, &mods);
6545 return mac_to_emacs_modifiers (mods);
6548 /* Given an event ref, return the code to use for the mouse button
6549 code in the emacs input_event. */
6550 static int
6551 mac_get_mouse_btn (EventRef ref)
6553 EventMouseButton result = kEventMouseButtonPrimary;
6554 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
6555 sizeof (EventMouseButton), NULL, &result);
6556 switch (result)
6558 case kEventMouseButtonPrimary:
6559 return 0;
6560 case kEventMouseButtonSecondary:
6561 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
6562 case kEventMouseButtonTertiary:
6563 case 4: /* 4 is the number for the mouse wheel button */
6564 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
6565 default:
6566 return 0;
6570 /* Normally, ConvertEventRefToEventRecord will correctly handle all
6571 events. However the click of the mouse wheel is not converted to a
6572 mouseDown or mouseUp event. This calls ConvertEventRef, but then
6573 checks to see if it is a mouse up or down carbon event that has not
6574 been converted, and if so, converts it by hand (to be picked up in
6575 the XTread_socket loop). */
6576 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
6578 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
6579 /* Do special case for mouse wheel button. */
6580 if (!result && GetEventClass (eventRef) == kEventClassMouse)
6582 UInt32 kind = GetEventKind (eventRef);
6583 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
6585 eventRec->what = mouseDown;
6586 result=1;
6588 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
6590 eventRec->what = mouseUp;
6591 result=1;
6593 if (result)
6595 /* Need where and when. */
6596 UInt32 mods;
6597 GetEventParameter (eventRef, kEventParamMouseLocation,
6598 typeQDPoint, NULL, sizeof (Point),
6599 NULL, &eventRec->where);
6600 /* Use two step process because new event modifiers are
6601 32-bit and old are 16-bit. Currently, only loss is
6602 NumLock & Fn. */
6603 GetEventParameter (eventRef, kEventParamKeyModifiers,
6604 typeUInt32, NULL, sizeof (UInt32),
6605 NULL, &mods);
6606 eventRec->modifiers = mods;
6608 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
6611 return result;
6614 #endif
6616 static void
6617 do_get_menus (void)
6619 Handle menubar_handle;
6620 MenuHandle menu_handle;
6622 menubar_handle = GetNewMBar (128);
6623 if(menubar_handle == NULL)
6624 abort ();
6625 SetMenuBar (menubar_handle);
6626 DrawMenuBar ();
6628 menu_handle = GetMenuHandle (M_APPLE);
6629 if(menu_handle != NULL)
6630 AppendResMenu (menu_handle,'DRVR');
6631 else
6632 abort ();
6636 static void
6637 do_init_managers (void)
6639 #if !TARGET_API_MAC_CARBON
6640 InitGraf (&qd.thePort);
6641 InitFonts ();
6642 FlushEvents (everyEvent, 0);
6643 InitWindows ();
6644 InitMenus ();
6645 TEInit ();
6646 InitDialogs (NULL);
6647 #endif /* !TARGET_API_MAC_CARBON */
6648 InitCursor ();
6650 #if !TARGET_API_MAC_CARBON
6651 /* set up some extra stack space for use by emacs */
6652 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
6654 /* MaxApplZone must be called for AppleScript to execute more
6655 complicated scripts */
6656 MaxApplZone ();
6657 MoreMasters ();
6658 #endif /* !TARGET_API_MAC_CARBON */
6661 static void
6662 do_check_ram_size (void)
6664 SInt32 physical_ram_size, logical_ram_size;
6666 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
6667 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
6668 || physical_ram_size > (1 << VALBITS)
6669 || logical_ram_size > (1 << VALBITS))
6671 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
6672 exit (1);
6676 static void
6677 do_window_update (WindowPtr win)
6679 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
6680 struct frame *f = mwp->mFP;
6682 if (f)
6684 if (f->async_visible == 0)
6686 f->async_visible = 1;
6687 f->async_iconified = 0;
6688 SET_FRAME_GARBAGED (f);
6690 /* An update event is equivalent to MapNotify on X, so report
6691 visibility changes properly. */
6692 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
6693 /* Force a redisplay sooner or later to update the
6694 frame titles in case this is the second frame. */
6695 record_asynch_buffer_change ();
6697 else
6699 BeginUpdate (win);
6700 handling_window_update = 1;
6702 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
6704 expose_frame (f, 0, 0, 0, 0);
6706 handling_window_update = 0;
6707 EndUpdate (win);
6712 static int
6713 is_emacs_window (WindowPtr win)
6715 Lisp_Object tail, frame;
6717 if (!win)
6718 return 0;
6720 FOR_EACH_FRAME (tail, frame)
6721 if (FRAME_MAC_P (XFRAME (frame)))
6722 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
6723 return 1;
6725 return 0;
6728 static void
6729 do_window_activate (WindowPtr win)
6731 mac_output *mwp;
6732 struct frame *f;
6734 if (is_emacs_window (win))
6736 mwp = (mac_output *) GetWRefCon (win);
6737 f = mwp->mFP;
6739 if (f)
6741 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
6742 activate_scroll_bars (f);
6747 static void
6748 do_window_deactivate (WindowPtr win)
6750 mac_output *mwp;
6751 struct frame *f;
6753 if (is_emacs_window (win))
6755 mwp = (mac_output *) GetWRefCon (win);
6756 f = mwp->mFP;
6758 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6760 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
6761 deactivate_scroll_bars (f);
6766 static void
6767 do_app_resume ()
6769 WindowPtr wp;
6770 mac_output *mwp;
6771 struct frame *f;
6773 wp = FrontWindow();
6774 if (is_emacs_window (wp))
6776 mwp = (mac_output *) GetWRefCon (wp);
6777 f = mwp->mFP;
6779 if (f)
6781 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
6782 activate_scroll_bars (f);
6786 app_is_suspended = false;
6787 app_sleep_time = WNE_SLEEP_AT_RESUME;
6790 static void
6791 do_app_suspend ()
6793 WindowPtr wp;
6794 mac_output *mwp;
6795 struct frame *f;
6797 wp = FrontWindow();
6798 if (is_emacs_window (wp))
6800 mwp = (mac_output *) GetWRefCon (wp);
6801 f = mwp->mFP;
6803 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6805 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
6806 deactivate_scroll_bars (f);
6810 app_is_suspended = true;
6811 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
6815 static void
6816 do_mouse_moved (Point mouse_pos)
6818 WindowPtr wp = FrontWindow ();
6819 struct frame *f;
6821 if (is_emacs_window (wp))
6823 f = ((mac_output *) GetWRefCon (wp))->mFP;
6825 #if TARGET_API_MAC_CARBON
6826 SetPort (GetWindowPort (wp));
6827 #else
6828 SetPort (wp);
6829 #endif
6831 GlobalToLocal (&mouse_pos);
6833 note_mouse_movement (f, &mouse_pos);
6838 static void
6839 do_os_event (EventRecord *erp)
6841 switch((erp->message >> 24) & 0x000000FF)
6843 case suspendResumeMessage:
6844 if((erp->message & resumeFlag) == 1)
6845 do_app_resume ();
6846 else
6847 do_app_suspend ();
6848 break;
6850 case mouseMovedMessage:
6851 do_mouse_moved (erp->where);
6852 break;
6856 static void
6857 do_events (EventRecord *erp)
6859 switch (erp->what)
6861 case updateEvt:
6862 do_window_update ((WindowPtr) erp->message);
6863 break;
6865 case osEvt:
6866 do_os_event (erp);
6867 break;
6869 case activateEvt:
6870 if ((erp->modifiers & activeFlag) != 0)
6871 do_window_activate ((WindowPtr) erp->message);
6872 else
6873 do_window_deactivate ((WindowPtr) erp->message);
6874 break;
6878 static void
6879 do_apple_menu (SInt16 menu_item)
6881 #if !TARGET_API_MAC_CARBON
6882 Str255 item_name;
6883 SInt16 da_driver_refnum;
6885 if (menu_item == I_ABOUT)
6886 NoteAlert (ABOUT_ALERT_ID, NULL);
6887 else
6889 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
6890 da_driver_refnum = OpenDeskAcc (item_name);
6892 #endif /* !TARGET_API_MAC_CARBON */
6895 void
6896 do_menu_choice (SInt32 menu_choice)
6898 SInt16 menu_id, menu_item;
6900 menu_id = HiWord (menu_choice);
6901 menu_item = LoWord (menu_choice);
6903 if (menu_id == 0)
6904 return;
6906 switch (menu_id)
6908 case M_APPLE:
6909 do_apple_menu (menu_item);
6910 break;
6912 default:
6914 WindowPtr wp = FrontWindow ();
6915 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
6916 MenuHandle menu = GetMenuHandle (menu_id);
6917 if (menu)
6919 UInt32 refcon;
6921 GetMenuItemRefCon (menu, menu_item, &refcon);
6922 menubar_selection_callback (f, refcon);
6927 HiliteMenu (0);
6931 /* Handle drags in size box. Based on code contributed by Ben
6932 Mesander and IM - Window Manager A. */
6934 static void
6935 do_grow_window (WindowPtr w, EventRecord *e)
6937 long grow_size;
6938 Rect limit_rect;
6939 int rows, columns;
6940 mac_output *mwp = (mac_output *) GetWRefCon (w);
6941 struct frame *f = mwp->mFP;
6943 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
6945 grow_size = GrowWindow (w, e->where, &limit_rect);
6947 /* see if it really changed size */
6948 if (grow_size != 0)
6950 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
6951 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
6953 x_set_window_size (f, 0, columns, rows);
6958 /* Handle clicks in zoom box. Calculation of "standard state" based
6959 on code in IM - Window Manager A and code contributed by Ben
6960 Mesander. The standard state of an Emacs window is 80-characters
6961 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
6963 static void
6964 do_zoom_window (WindowPtr w, int zoom_in_or_out)
6966 GrafPtr save_port;
6967 Rect zoom_rect, port_rect;
6968 Point top_left;
6969 int w_title_height, columns, rows, width, height, dummy, x, y;
6970 mac_output *mwp = (mac_output *) GetWRefCon (w);
6971 struct frame *f = mwp->mFP;
6973 GetPort (&save_port);
6975 #if TARGET_API_MAC_CARBON
6976 SetPort (GetWindowPort (w));
6977 #else
6978 SetPort (w);
6979 #endif
6981 /* Clear window to avoid flicker. */
6982 #if TARGET_API_MAC_CARBON
6984 Rect r;
6985 BitMap bm;
6987 GetWindowPortBounds (w, &r);
6988 EraseRect (&r);
6990 if (zoom_in_or_out == inZoomOut)
6992 /* calculate height of window's title bar (hard card it for now). */
6993 w_title_height = 20 + GetMBarHeight ();
6995 /* get maximum height of window into zoom_rect.bottom -
6996 zoom_rect.top */
6997 GetQDGlobalsScreenBits (&bm);
6998 zoom_rect = bm.bounds;
6999 zoom_rect.top += w_title_height;
7000 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7002 zoom_rect.right = zoom_rect.left
7003 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7005 SetWindowStandardState (w, &zoom_rect);
7008 #else /* not TARGET_API_MAC_CARBON */
7009 EraseRect (&(w->portRect));
7010 if (zoom_in_or_out == inZoomOut)
7012 SetPt (&top_left, w->portRect.left, w->portRect.top);
7013 LocalToGlobal (&top_left);
7015 /* calculate height of window's title bar */
7016 w_title_height = top_left.v - 1
7017 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7019 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7020 zoom_rect = qd.screenBits.bounds;
7021 zoom_rect.top += w_title_height;
7022 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7024 zoom_rect.right = zoom_rect.left
7025 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7027 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7028 = zoom_rect;
7030 #endif /* not TARGET_API_MAC_CARBON */
7032 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
7034 /* retrieve window size and update application values */
7035 #if TARGET_API_MAC_CARBON
7036 GetWindowPortBounds (w, &port_rect);
7037 #else
7038 port_rect = w->portRect;
7039 #endif
7040 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
7041 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
7042 x_set_window_size (mwp->mFP, 0, columns, rows);
7044 SetPort (save_port);
7047 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7048 static OSErr
7049 init_mac_drag_n_drop ()
7051 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7052 return result;
7055 /* Intialize AppleEvent dispatcher table for the required events. */
7056 void
7057 init_required_apple_events ()
7059 OSErr err;
7060 long result;
7062 /* Make sure we have apple events before starting. */
7063 err = Gestalt (gestaltAppleEventsAttr, &result);
7064 if (err != noErr)
7065 abort ();
7067 if (!(result & (1 << gestaltAppleEventsPresent)))
7068 abort ();
7070 #if TARGET_API_MAC_CARBON
7071 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7072 NewAEEventHandlerUPP
7073 ((AEEventHandlerProcPtr) do_ae_open_application),
7074 0L, false);
7075 #else
7076 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7077 NewAEEventHandlerProc
7078 ((AEEventHandlerProcPtr) do_ae_open_application),
7079 0L, false);
7080 #endif
7081 if (err != noErr)
7082 abort ();
7084 #if TARGET_API_MAC_CARBON
7085 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7086 NewAEEventHandlerUPP
7087 ((AEEventHandlerProcPtr) do_ae_open_documents),
7088 0L, false);
7089 #else
7090 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7091 NewAEEventHandlerProc
7092 ((AEEventHandlerProcPtr) do_ae_open_documents),
7093 0L, false);
7094 #endif
7095 if (err != noErr)
7096 abort ();
7098 #if TARGET_API_MAC_CARBON
7099 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7100 NewAEEventHandlerUPP
7101 ((AEEventHandlerProcPtr) do_ae_print_documents),
7102 0L, false);
7103 #else
7104 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7105 NewAEEventHandlerProc
7106 ((AEEventHandlerProcPtr) do_ae_print_documents),
7107 0L, false);
7108 #endif
7109 if (err != noErr)
7110 abort ();
7112 #if TARGET_API_MAC_CARBON
7113 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7114 NewAEEventHandlerUPP
7115 ((AEEventHandlerProcPtr) do_ae_quit_application),
7116 0L, false);
7117 #else
7118 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7119 NewAEEventHandlerProc
7120 ((AEEventHandlerProcPtr) do_ae_quit_application),
7121 0L, false);
7122 #endif
7123 if (err != noErr)
7124 abort ();
7127 #if USE_CARBON_EVENTS
7129 void
7130 init_service_handler ()
7132 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7133 {kEventClassService, kEventServiceCopy},
7134 {kEventClassService, kEventServicePaste}};
7135 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7136 3, specs, NULL, NULL);
7140 MAC_TODO: Check to see if this is called by AEProcessDesc...
7142 OSStatus
7143 mac_handle_service_event (EventHandlerCallRef callRef,
7144 EventRef event, void *data)
7146 OSStatus err = noErr;
7147 switch (GetEventKind (event))
7149 case kEventServiceGetTypes:
7151 CFMutableArrayRef copyTypes, pasteTypes;
7152 CFStringRef type;
7153 Boolean selection = true;
7155 GetEventParameter(event, kEventParamServicePasteTypes,
7156 typeCFMutableArrayRef, NULL,
7157 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7159 GetEventParameter(event, kEventParamServiceCopyTypes,
7160 typeCFMutableArrayRef, NULL,
7161 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7162 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7163 if (type) {
7164 CFArrayAppendValue (copyTypes, type);
7165 //CFArrayAppendValue (pasteTypes, type);
7166 CFRelease (type);
7169 case kEventServiceCopy:
7171 ScrapRef currentScrap, specificScrap;
7172 char * buf = "";
7173 Size byteCount = 0;
7175 GetCurrentScrap (&currentScrap);
7177 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7178 if (err == noErr)
7180 void *buffer = xmalloc (byteCount);
7181 if (buffer != NULL)
7183 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7184 sizeof (ScrapRef), NULL, &specificScrap);
7186 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7187 &byteCount, buffer);
7188 if (err == noErr)
7189 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7190 kScrapFlavorMaskNone, byteCount, buffer);
7191 xfree (buffer);
7194 err = noErr;
7196 case kEventServicePaste:
7199 // Get the current location
7200 Size byteCount;
7201 ScrapRef specificScrap;
7202 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7203 sizeof(ScrapRef), NULL, &specificScrap);
7204 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7205 if (err == noErr) {
7206 void * buffer = xmalloc(byteCount);
7207 if (buffer != NULL ) {
7208 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7209 &byteCount, buffer);
7210 if (err == noErr) {
7211 // Actually place in the buffer
7212 BLOCK_INPUT;
7213 // Get the current "selection" string here
7214 UNBLOCK_INPUT;
7217 xfree(buffer);
7222 return err;
7224 #endif
7226 /* Open Application Apple Event */
7227 static pascal OSErr
7228 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7230 return noErr;
7234 /* Defined in mac.c. */
7235 extern int
7236 path_from_vol_dir_name (char *, int, short, long, char *);
7239 /* Called when we receive an AppleEvent with an ID of
7240 "kAEOpenDocuments". This routine gets the direct parameter,
7241 extracts the FSSpecs in it, and puts their names on a list. */
7242 static pascal OSErr
7243 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7245 OSErr err, err2;
7246 AEDesc the_desc;
7247 AEKeyword keyword;
7248 DescType actual_type;
7249 Size actual_size;
7251 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7252 if (err != noErr)
7253 goto descriptor_error_exit;
7255 /* Check to see that we got all of the required parameters from the
7256 event descriptor. For an 'odoc' event this should just be the
7257 file list. */
7258 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
7259 &actual_type, (Ptr) &keyword,
7260 sizeof (keyword), &actual_size);
7261 /* No error means that we found some unused parameters.
7262 errAEDescNotFound means that there are no more parameters. If we
7263 get an error code other than that, flag it. */
7264 if ((err == noErr) || (err != errAEDescNotFound))
7266 err = errAEEventNotHandled;
7267 goto error_exit;
7269 err = noErr;
7271 /* Got all the parameters we need. Now, go through the direct
7272 object list and parse it up. */
7274 long num_files_to_open;
7276 err = AECountItems (&the_desc, &num_files_to_open);
7277 if (err == noErr)
7279 int i;
7281 /* AE file list is one based so just use that for indexing here. */
7282 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7284 FSSpec fs;
7285 Str255 path_name, unix_path_name;
7286 #ifdef MAC_OSX
7287 FSRef fref;
7288 #endif
7290 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7291 (Ptr) &fs, sizeof (fs), &actual_size);
7292 if (err != noErr) break;
7294 #ifdef MAC_OSX
7295 err = FSpMakeFSRef (&fs, &fref);
7296 if (err != noErr) break;
7298 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
7299 #else
7300 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
7301 fs.name) &&
7302 mac_to_posix_pathname (path_name, unix_path_name, 255))
7303 #endif
7304 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7305 drag_and_drop_file_list);
7310 error_exit:
7311 /* Nuke the coerced file list in any case */
7312 err2 = AEDisposeDesc(&the_desc);
7314 descriptor_error_exit:
7315 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7316 return err;
7320 static pascal OSErr
7321 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
7322 DragReference theDrag)
7324 short items;
7325 short index;
7326 FlavorFlags theFlags;
7327 Point mouse;
7328 OSErr result;
7329 ItemReference theItem;
7330 HFSFlavor data;
7331 FSRef fref;
7332 Size size = sizeof (HFSFlavor);
7334 drag_and_drop_file_list = Qnil;
7335 GetDragMouse (theDrag, &mouse, 0L);
7336 CountDragItems (theDrag, &items);
7337 for (index = 1; index <= items; index++)
7339 /* Only handle file references. */
7340 GetDragItemReferenceNumber (theDrag, index, &theItem);
7341 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
7342 if (result == noErr)
7344 #ifdef MAC_OSX
7345 FSRef frref;
7346 #else
7347 Str255 path_name;
7348 #endif
7349 Str255 unix_path_name;
7350 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
7351 #ifdef MAC_OSX
7352 /* Use Carbon routines, otherwise it converts the file name
7353 to /Macintosh HD/..., which is not correct. */
7354 FSpMakeFSRef (&data.fileSpec, &fref);
7355 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
7356 #else
7357 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
7358 data.fileSpec.parID, data.fileSpec.name) &&
7359 mac_to_posix_pathname (path_name, unix_path_name, 255))
7360 #endif
7361 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7362 drag_and_drop_file_list);
7364 else
7365 return;
7367 /* If there are items in the list, construct an event and post it to
7368 the queue like an interrupt using kbd_buffer_store_event. */
7369 if (!NILP (drag_and_drop_file_list))
7371 struct input_event event;
7372 Lisp_Object frame;
7373 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
7374 SetPort (GetWindowPort (window));
7375 GlobalToLocal (&mouse);
7377 event.kind = DRAG_N_DROP_EVENT;
7378 event.code = 0;
7379 event.modifiers = 0;
7380 event.timestamp = TickCount () * (1000 / 60);
7381 XSETINT (event.x, mouse.h);
7382 XSETINT (event.y, mouse.v);
7383 XSETFRAME (frame, f);
7384 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
7385 event.arg = Qnil;
7386 /* Post to the interrupt queue */
7387 kbd_buffer_store_event (&event);
7388 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7390 ProcessSerialNumber psn;
7391 GetCurrentProcess (&psn);
7392 SetFrontProcess (&psn);
7398 /* Print Document Apple Event */
7399 static pascal OSErr
7400 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
7402 return errAEEventNotHandled;
7406 static pascal OSErr
7407 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
7409 /* FixMe: Do we need an unwind-protect or something here? And what
7410 do we do about unsaved files. Currently just forces quit rather
7411 than doing recursive callback to get user input. */
7413 terminate_flag = true;
7415 /* Fkill_emacs doesn't return. We have to return. (TI) */
7416 return noErr;
7420 #if __profile__
7421 void
7422 profiler_exit_proc ()
7424 ProfilerDump ("\pEmacs.prof");
7425 ProfilerTerm ();
7427 #endif
7429 /* These few functions implement Emacs as a normal Mac application
7430 (almost): set up the heap and the Toolbox, handle necessary
7431 system events plus a few simple menu events. They also set up
7432 Emacs's access to functions defined in the rest of this file.
7433 Emacs uses function hooks to perform all its terminal I/O. A
7434 complete list of these functions appear in termhooks.h. For what
7435 they do, read the comments there and see also w32term.c and
7436 xterm.c. What's noticeably missing here is the event loop, which
7437 is normally present in most Mac application. After performing the
7438 necessary Mac initializations, main passes off control to
7439 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7440 mac_read_socket (defined further below) to read input. This is
7441 where WaitNextEvent is called to process Mac events. This is also
7442 where check_alarm in sysdep.c is called to simulate alarm signals.
7443 This makes the cursor jump back to its correct position after
7444 briefly jumping to that of the matching parenthesis, print useful
7445 hints and prompts in the minibuffer after the user stops typing for
7446 a wait, etc. */
7448 #if !TARGET_API_MAC_CARBON
7449 #undef main
7451 main (void)
7453 #if __profile__ /* is the profiler on? */
7454 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
7455 exit(1);
7456 #endif
7458 #if __MWERKS__
7459 /* set creator and type for files created by MSL */
7460 _fcreator = 'EMAx';
7461 _ftype = 'TEXT';
7462 #endif
7464 do_init_managers ();
7466 do_get_menus ();
7468 do_check_ram_size ();
7470 init_emacs_passwd_dir ();
7472 init_environ ();
7474 initialize_applescript ();
7476 init_required_apple_events ();
7479 char **argv;
7480 int argc = 0;
7482 /* set up argv array from STR# resource */
7483 get_string_list (&argv, ARGV_STRING_LIST_ID);
7484 while (argv[argc])
7485 argc++;
7487 /* free up AppleScript resources on exit */
7488 atexit (terminate_applescript);
7490 #if __profile__ /* is the profiler on? */
7491 atexit (profiler_exit_proc);
7492 #endif
7494 /* 3rd param "envp" never used in emacs_main */
7495 (void) emacs_main (argc, argv, 0);
7498 /* Never reached - real exit in Fkill_emacs */
7499 return 0;
7501 #endif
7503 /* Table for translating Mac keycode to X keysym values. Contributed
7504 by Sudhir Shenoy. */
7505 static unsigned char keycode_to_xkeysym_table[] = {
7506 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7507 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7508 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7510 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
7511 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
7512 /*0x38*/ 0, 0, 0, 0,
7513 /*0x3C*/ 0, 0, 0, 0,
7515 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
7516 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
7517 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
7518 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
7520 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
7521 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
7522 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
7523 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
7525 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
7526 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
7527 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
7528 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
7530 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
7531 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
7532 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
7533 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
7536 static int
7537 keycode_to_xkeysym (int keyCode, int *xKeySym)
7539 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
7540 return *xKeySym != 0;
7543 /* Emacs calls this whenever it wants to read an input event from the
7544 user. */
7546 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
7548 int count = 0;
7549 #if USE_CARBON_EVENTS
7550 OSStatus rneResult;
7551 EventRef eventRef;
7552 EventMouseButton mouseBtn;
7553 #endif
7554 EventRecord er;
7555 int the_modifiers;
7556 EventMask event_mask;
7558 #if 0
7559 if (interrupt_input_blocked)
7561 interrupt_input_pending = 1;
7562 return -1;
7564 #endif
7566 interrupt_input_pending = 0;
7567 BLOCK_INPUT;
7569 /* So people can tell when we have read the available input. */
7570 input_signal_count++;
7572 if (numchars <= 0)
7573 abort ();
7575 /* Don't poll for events to process (specifically updateEvt) if
7576 window update currently already in progress. A call to redisplay
7577 (in do_window_update) can be preempted by another call to
7578 redisplay, causing blank regions to be left on the screen and the
7579 cursor to be left at strange places. */
7580 if (handling_window_update)
7582 UNBLOCK_INPUT;
7583 return 0;
7586 if (terminate_flag)
7587 Fkill_emacs (make_number (1));
7589 /* It is necessary to set this (additional) argument slot of an
7590 event to nil because keyboard.c protects incompletely processed
7591 event from being garbage collected by placing them in the
7592 kbd_buffer_gcpro vector. */
7593 bufp->arg = Qnil;
7595 event_mask = everyEvent;
7596 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
7597 event_mask -= highLevelEventMask;
7599 #if USE_CARBON_EVENTS
7600 rneResult = ReceiveNextEvent (0, NULL,
7601 expected
7602 ? TicksToEventTime (app_sleep_time)
7603 : 0,
7604 kEventRemoveFromQueue, &eventRef);
7605 if (!rneResult)
7607 /* Handle new events */
7608 if (!mac_convert_event_ref (eventRef, &er))
7609 switch (GetEventClass (eventRef))
7611 case kEventClassMouse:
7612 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
7614 SInt32 delta;
7615 Point point;
7616 WindowPtr window_ptr = FrontNonFloatingWindow ();
7617 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
7618 if (!IsValidWindowPtr (window_ptr))
7620 SysBeep(1);
7621 UNBLOCK_INPUT;
7622 return 0;
7625 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
7626 typeSInt32, NULL, sizeof (SInt32),
7627 NULL, &delta);
7628 GetEventParameter(eventRef, kEventParamMouseLocation,
7629 typeQDPoint, NULL, sizeof (Point),
7630 NULL, &point);
7631 bufp->kind = WHEEL_EVENT;
7632 bufp->code = 0;
7633 bufp->modifiers = (mac_event_to_emacs_modifiers(eventRef)
7634 | ((delta < 0) ? down_modifier
7635 : up_modifier));
7636 SetPort (GetWindowPort (window_ptr));
7637 GlobalToLocal (&point);
7638 XSETINT (bufp->x, point.h);
7639 XSETINT (bufp->y, point.v);
7640 XSETFRAME (bufp->frame_or_window, mwp->mFP);
7641 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
7642 count++;
7644 else
7645 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
7647 break;
7648 default:
7649 /* Send the event to the appropriate receiver. */
7650 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
7652 else
7653 #else
7654 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
7655 #endif /* USE_CARBON_EVENTS */
7656 switch (er.what)
7658 case mouseDown:
7659 case mouseUp:
7661 WindowPtr window_ptr = FrontWindow ();
7662 SInt16 part_code;
7664 #if USE_CARBON_EVENTS
7665 /* This is needed to send mouse events like aqua window buttons
7666 to the correct handler. */
7667 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
7668 break;
7671 if (!is_emacs_window(window_ptr))
7672 break;
7673 #endif
7675 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
7676 && er.what == mouseUp)
7678 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
7679 Point mouse_loc = er.where;
7681 /* Convert to local coordinates of new window. */
7682 #if TARGET_API_MAC_CARBON
7683 SetPort (GetWindowPort (window_ptr));
7684 #else
7685 SetPort (window_ptr);
7686 #endif
7688 GlobalToLocal (&mouse_loc);
7690 #if USE_CARBON_EVENTS
7691 bufp->code = mac_get_mouse_btn (eventRef);
7692 #else
7693 bufp->code = 0; /* only one mouse button */
7694 #endif
7695 bufp->kind = SCROLL_BAR_CLICK_EVENT;
7696 bufp->frame_or_window = tracked_scroll_bar->window;
7697 bufp->part = scroll_bar_handle;
7698 #if USE_CARBON_EVENTS
7699 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
7700 #else
7701 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
7702 #endif
7703 bufp->modifiers |= up_modifier;
7704 bufp->timestamp = er.when * (1000 / 60);
7705 /* ticks to milliseconds */
7707 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
7708 XSETINT (bufp->y, mouse_loc.v - 24);
7709 tracked_scroll_bar->dragging = Qnil;
7710 mouse_tracking_in_progress = mouse_tracking_none;
7711 tracked_scroll_bar = NULL;
7712 count++;
7713 break;
7716 part_code = FindWindow (er.where, &window_ptr);
7718 switch (part_code)
7720 case inMenuBar:
7721 if (er.what == mouseDown)
7723 struct frame *f = ((mac_output *)
7724 GetWRefCon (FrontWindow ()))->mFP;
7725 saved_menu_event_location = er.where;
7726 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
7727 XSETFRAME (bufp->frame_or_window, f);
7728 count++;
7730 break;
7732 case inContent:
7733 if (window_ptr != FrontWindow ())
7734 SelectWindow (window_ptr);
7735 else
7737 SInt16 control_part_code;
7738 ControlHandle ch;
7739 struct mac_output *mwp = (mac_output *)
7740 GetWRefCon (window_ptr);
7741 Point mouse_loc = er.where;
7743 /* convert to local coordinates of new window */
7744 #if TARGET_API_MAC_CARBON
7745 SetPort (GetWindowPort (window_ptr));
7746 #else
7747 SetPort (window_ptr);
7748 #endif
7750 GlobalToLocal (&mouse_loc);
7751 #if TARGET_API_MAC_CARBON
7752 ch = FindControlUnderMouse (mouse_loc, window_ptr,
7753 &control_part_code);
7754 #else
7755 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
7756 #endif
7758 #if USE_CARBON_EVENTS
7759 bufp->code = mac_get_mouse_btn (eventRef);
7760 #else
7761 bufp->code = 0; /* only one mouse button */
7762 #endif
7763 XSETINT (bufp->x, mouse_loc.h);
7764 XSETINT (bufp->y, mouse_loc.v);
7765 bufp->timestamp = er.when * (1000 / 60);
7766 /* ticks to milliseconds */
7768 #if TARGET_API_MAC_CARBON
7769 if (ch != 0)
7770 #else
7771 if (control_part_code != 0)
7772 #endif
7774 struct scroll_bar *bar = (struct scroll_bar *)
7775 GetControlReference (ch);
7776 x_scroll_bar_handle_click (bar, control_part_code, &er,
7777 bufp);
7778 if (er.what == mouseDown
7779 && control_part_code == kControlIndicatorPart)
7781 mouse_tracking_in_progress
7782 = mouse_tracking_scroll_bar;
7783 tracked_scroll_bar = bar;
7785 else
7787 mouse_tracking_in_progress = mouse_tracking_none;
7788 tracked_scroll_bar = NULL;
7791 else
7793 bufp->kind = MOUSE_CLICK_EVENT;
7794 XSETFRAME (bufp->frame_or_window, mwp->mFP);
7795 if (er.what == mouseDown)
7796 mouse_tracking_in_progress
7797 = mouse_tracking_mouse_movement;
7798 else
7799 mouse_tracking_in_progress = mouse_tracking_none;
7802 #if USE_CARBON_EVENTS
7803 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
7804 #else
7805 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
7806 #endif
7808 switch (er.what)
7810 case mouseDown:
7811 bufp->modifiers |= down_modifier;
7812 break;
7813 case mouseUp:
7814 bufp->modifiers |= up_modifier;
7815 break;
7818 count++;
7820 break;
7822 case inDrag:
7823 #if TARGET_API_MAC_CARBON
7824 if (er.what == mouseDown)
7826 BitMap bm;
7828 GetQDGlobalsScreenBits (&bm);
7829 DragWindow (window_ptr, er.where, &bm.bounds);
7831 #else /* not TARGET_API_MAC_CARBON */
7832 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
7833 #endif /* not TARGET_API_MAC_CARBON */
7834 break;
7836 case inGoAway:
7837 if (TrackGoAway (window_ptr, er.where))
7839 bufp->kind = DELETE_WINDOW_EVENT;
7840 XSETFRAME (bufp->frame_or_window,
7841 ((mac_output *) GetWRefCon (window_ptr))->mFP);
7842 count++;
7844 break;
7846 /* window resize handling added --ben */
7847 case inGrow:
7848 if (er.what == mouseDown)
7850 do_grow_window(window_ptr, &er);
7851 break;
7854 /* window zoom handling added --ben */
7855 case inZoomIn:
7856 case inZoomOut:
7857 if (TrackBox (window_ptr, er.where, part_code))
7858 do_zoom_window (window_ptr, part_code);
7859 break;
7861 default:
7862 break;
7865 break;
7867 case updateEvt:
7868 case osEvt:
7869 case activateEvt:
7870 #if USE_CARBON_EVENTS
7871 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
7872 #endif
7873 do_events (&er);
7874 break;
7876 case keyDown:
7877 case autoKey:
7879 int keycode = (er.message & keyCodeMask) >> 8;
7880 int xkeysym;
7882 #if USE_CARBON_EVENTS
7883 /* When using Carbon Events, we need to pass raw keyboard events
7884 to the TSM ourselves. If TSM handles it, it will pass back
7885 noErr, otherwise it will pass back "eventNotHandledErr" and
7886 we can process it normally. */
7887 if ((!NILP (Vmac_pass_command_to_system)
7888 || !(er.modifiers & cmdKey))
7889 && (!NILP (Vmac_pass_control_to_system)
7890 || !(er.modifiers & controlKey)))
7892 OSStatus err;
7893 err = SendEventToEventTarget (eventRef,
7894 GetEventDispatcherTarget ());
7895 if (err != eventNotHandledErr)
7896 break;
7898 #endif
7900 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
7902 SysBeep (1);
7903 UNBLOCK_INPUT;
7904 return 0;
7907 ObscureCursor ();
7909 if (keycode_to_xkeysym (keycode, &xkeysym))
7911 bufp->code = 0xff00 | xkeysym;
7912 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
7914 else
7916 if (er.modifiers & (controlKey |
7917 (NILP (Vmac_command_key_is_meta) ? optionKey
7918 : cmdKey)))
7920 /* This code comes from Keyboard Resource, Appendix
7921 C of IM - Text. This is necessary since shift is
7922 ignored in KCHR table translation when option or
7923 command is pressed. It also does not translate
7924 correctly control-shift chars like C-% so mask off
7925 shift here also */
7926 int new_modifiers = er.modifiers & 0xe600;
7927 /* mask off option and command */
7928 int new_keycode = keycode | new_modifiers;
7929 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
7930 unsigned long some_state = 0;
7931 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
7932 &some_state) & 0xff;
7934 else
7935 bufp->code = er.message & charCodeMask;
7936 bufp->kind = ASCII_KEYSTROKE_EVENT;
7940 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
7941 convert non-ASCII characters typed at the Mac keyboard
7942 (presumed to be in the Mac Roman encoding) to iso-latin-1
7943 encoding before they are passed to Emacs. This enables the
7944 Mac keyboard to be used to enter non-ASCII iso-latin-1
7945 characters directly. */
7946 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
7947 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
7949 static TECObjectRef converter = NULL;
7950 OSStatus the_err = noErr;
7951 OSStatus convert_status = noErr;
7953 if (converter == NULL)
7955 the_err = TECCreateConverter (&converter,
7956 kTextEncodingMacRoman,
7957 mac_keyboard_text_encoding);
7958 current_mac_keyboard_text_encoding
7959 = mac_keyboard_text_encoding;
7961 else if (mac_keyboard_text_encoding
7962 != current_mac_keyboard_text_encoding)
7964 /* Free the converter for the current encoding before
7965 creating a new one. */
7966 TECDisposeConverter (converter);
7967 the_err = TECCreateConverter (&converter,
7968 kTextEncodingMacRoman,
7969 mac_keyboard_text_encoding);
7970 current_mac_keyboard_text_encoding
7971 = mac_keyboard_text_encoding;
7974 if (the_err == noErr)
7976 unsigned char ch = bufp->code;
7977 ByteCount actual_input_length, actual_output_length;
7978 unsigned char outch;
7980 convert_status = TECConvertText (converter, &ch, 1,
7981 &actual_input_length,
7982 &outch, 1,
7983 &actual_output_length);
7984 if (convert_status == noErr
7985 && actual_input_length == 1
7986 && actual_output_length == 1)
7987 bufp->code = outch;
7991 #if USE_CARBON_EVENTS
7992 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
7993 #else
7994 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
7995 #endif
7998 mac_output *mwp
7999 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
8000 XSETFRAME (bufp->frame_or_window, mwp->mFP);
8003 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8005 count++;
8006 break;
8008 case kHighLevelEvent:
8009 drag_and_drop_file_list = Qnil;
8011 AEProcessAppleEvent(&er);
8013 /* Build a DRAG_N_DROP_EVENT type event as is done in
8014 constuct_drag_n_drop in w32term.c. */
8015 if (!NILP (drag_and_drop_file_list))
8017 struct frame *f = NULL;
8018 WindowPtr wp;
8019 Lisp_Object frame;
8021 wp = FrontNonFloatingWindow ();
8023 if (!wp)
8025 struct frame *f = XFRAME (XCAR (Vframe_list));
8026 CollapseWindow (FRAME_MAC_WINDOW (f), false);
8027 wp = FrontNonFloatingWindow ();
8030 if (wp && is_emacs_window(wp))
8031 f = ((mac_output *) GetWRefCon (wp))->mFP;
8033 bufp->kind = DRAG_N_DROP_EVENT;
8034 bufp->code = 0;
8035 bufp->timestamp = er.when * (1000 / 60);
8036 /* ticks to milliseconds */
8037 #if USE_CARBON_EVENTS
8038 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
8039 #else
8040 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
8041 #endif
8043 XSETINT (bufp->x, 0);
8044 XSETINT (bufp->y, 0);
8046 XSETFRAME (frame, f);
8047 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
8049 /* Regardless of whether Emacs was suspended or in the
8050 foreground, ask it to redraw its entire screen.
8051 Otherwise parts of the screen can be left in an
8052 inconsistent state. */
8053 if (wp)
8054 #if TARGET_API_MAC_CARBON
8056 Rect r;
8058 GetWindowPortBounds (wp, &r);
8059 InvalWindowRect (wp, &r);
8061 #else /* not TARGET_API_MAC_CARBON */
8062 InvalRect (&(wp->portRect));
8063 #endif /* not TARGET_API_MAC_CARBON */
8065 count++;
8067 default:
8068 break;
8070 #if USE_CARBON_EVENTS
8071 ReleaseEvent (eventRef);
8073 #endif
8075 /* If the focus was just given to an autoraising frame,
8076 raise it now. */
8077 /* ??? This ought to be able to handle more than one such frame. */
8078 if (pending_autoraise_frame)
8080 x_raise_frame (pending_autoraise_frame);
8081 pending_autoraise_frame = 0;
8084 #if !TARGET_API_MAC_CARBON
8085 check_alarm (); /* simulate the handling of a SIGALRM */
8086 #endif
8089 static Point old_mouse_pos = { -1, -1 };
8091 if (app_is_suspended)
8093 old_mouse_pos.h = -1;
8094 old_mouse_pos.v = -1;
8096 else
8098 Point mouse_pos;
8099 WindowPtr wp;
8100 struct frame *f;
8101 Lisp_Object bar;
8102 struct scroll_bar *sb;
8104 wp = FrontWindow ();
8105 if (is_emacs_window (wp))
8107 f = ((mac_output *) GetWRefCon (wp))->mFP;
8109 #if TARGET_API_MAC_CARBON
8110 SetPort (GetWindowPort (wp));
8111 #else
8112 SetPort (wp);
8113 #endif
8115 GetMouse (&mouse_pos);
8117 if (!EqualPt (mouse_pos, old_mouse_pos))
8119 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
8120 && tracked_scroll_bar)
8121 x_scroll_bar_note_movement (tracked_scroll_bar,
8122 mouse_pos.v
8123 - XINT (tracked_scroll_bar->top),
8124 TickCount() * (1000 / 60));
8125 else
8126 note_mouse_movement (f, &mouse_pos);
8128 old_mouse_pos = mouse_pos;
8134 UNBLOCK_INPUT;
8136 return count;
8140 /* Need to override CodeWarrior's input function so no conversion is
8141 done on newlines Otherwise compiled functions in .elc files will be
8142 read incorrectly. Defined in ...:MSL C:MSL
8143 Common:Source:buffer_io.c. */
8144 #ifdef __MWERKS__
8145 void
8146 __convert_to_newlines (unsigned char * p, size_t * n)
8148 #pragma unused(p,n)
8151 void
8152 __convert_from_newlines (unsigned char * p, size_t * n)
8154 #pragma unused(p,n)
8156 #endif
8159 /* Initialize the struct pointed to by MW to represent a new COLS x
8160 ROWS Macintosh window, using font with name FONTNAME and size
8161 FONTSIZE. */
8162 void
8163 NewMacWindow (FRAME_PTR fp)
8165 mac_output *mwp;
8166 #if TARGET_API_MAC_CARBON
8167 static int making_terminal_window = 0;
8168 #else
8169 static int making_terminal_window = 1;
8170 #endif
8172 mwp = fp->output_data.mac;
8174 if (making_terminal_window)
8176 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
8177 (WindowPtr) -1)))
8178 abort ();
8179 making_terminal_window = 0;
8181 else
8182 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
8183 abort ();
8185 SetWRefCon (mwp->mWP, (long) mwp);
8186 /* so that update events can find this mac_output struct */
8187 mwp->mFP = fp; /* point back to emacs frame */
8189 #if TARGET_API_MAC_CARBON
8190 SetPort (GetWindowPort (mwp->mWP));
8191 #else
8192 SetPort (mwp->mWP);
8193 #endif
8195 mwp->fontset = -1;
8197 SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
8198 ShowWindow (mwp->mWP);
8203 void
8204 make_mac_frame (struct frame *f)
8206 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8207 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8209 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8211 NewMacWindow(f);
8213 f->output_data.mac->cursor_pixel = 0;
8214 f->output_data.mac->border_pixel = 0x00ff00;
8215 f->output_data.mac->mouse_pixel = 0xff00ff;
8216 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
8218 FRAME_FONTSET (f) = -1;
8219 f->output_data.mac->scroll_bar_foreground_pixel = -1;
8220 f->output_data.mac->scroll_bar_background_pixel = -1;
8221 f->output_data.mac->explicit_parent = 0;
8222 f->left_pos = 4;
8223 f->top_pos = 4;
8224 f->border_width = 0;
8226 f->internal_border_width = 0;
8228 f->output_method = output_mac;
8230 f->auto_raise = 1;
8231 f->auto_lower = 1;
8233 f->new_text_cols = 0;
8234 f->new_text_lines = 0;
8237 void
8238 make_mac_terminal_frame (struct frame *f)
8240 Lisp_Object frame;
8242 XSETFRAME (frame, f);
8244 f->output_method = output_mac;
8245 f->output_data.mac = (struct mac_output *)
8246 xmalloc (sizeof (struct mac_output));
8247 bzero (f->output_data.mac, sizeof (struct mac_output));
8248 FRAME_FONTSET (f) = -1;
8249 f->output_data.mac->scroll_bar_foreground_pixel = -1;
8250 f->output_data.mac->scroll_bar_background_pixel = -1;
8252 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8254 FRAME_COLS (f) = 96;
8255 FRAME_LINES (f) = 4;
8257 make_mac_frame (f);
8259 x_make_gc (f);
8261 /* Need to be initialized for unshow_buffer in window.c. */
8262 selected_window = f->selected_window;
8264 Fmodify_frame_parameters (frame,
8265 Fcons (Fcons (Qfont,
8266 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
8267 Fmodify_frame_parameters (frame,
8268 Fcons (Fcons (Qforeground_color,
8269 build_string ("black")), Qnil));
8270 Fmodify_frame_parameters (frame,
8271 Fcons (Fcons (Qbackground_color,
8272 build_string ("white")), Qnil));
8276 /***********************************************************************
8277 Initialization
8278 ***********************************************************************/
8280 int mac_initialized = 0;
8282 void
8283 mac_initialize_display_info ()
8285 struct mac_display_info *dpyinfo = &one_mac_display_info;
8286 GDHandle main_device_handle;
8288 bzero (dpyinfo, sizeof (*dpyinfo));
8290 /* Put it on x_display_name_list. */
8291 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
8292 x_display_name_list);
8293 dpyinfo->name_list_element = XCAR (x_display_name_list);
8295 #if 0
8296 dpyinfo->mac_id_name
8297 = (char *) xmalloc (SCHARS (Vinvocation_name)
8298 + SCHARS (Vsystem_name)
8299 + 2);
8300 sprintf (dpyinfo->mac_id_name, "%s@%s",
8301 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8302 #else
8303 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
8304 strcpy (dpyinfo->mac_id_name, "Mac Display");
8305 #endif
8307 main_device_handle = LMGetMainDevice();
8309 dpyinfo->reference_count = 0;
8310 dpyinfo->resx = 75.0;
8311 dpyinfo->resy = 75.0;
8312 dpyinfo->n_planes = 1;
8313 dpyinfo->n_cbits = 16;
8314 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8315 dpyinfo->width = (**main_device_handle).gdRect.right;
8316 dpyinfo->grabbed = 0;
8317 dpyinfo->root_window = NULL;
8319 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8320 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8321 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8322 dpyinfo->mouse_face_window = Qnil;
8325 struct mac_display_info *
8326 mac_term_init (display_name, xrm_option, resource_name)
8327 Lisp_Object display_name;
8328 char *xrm_option;
8329 char *resource_name;
8331 struct mac_display_info *dpyinfo;
8332 GDHandle main_device_handle;
8334 if (!mac_initialized)
8336 mac_initialize ();
8337 mac_initialized = 1;
8340 mac_initialize_display_info (display_name);
8342 dpyinfo = &one_mac_display_info;
8344 main_device_handle = LMGetMainDevice();
8346 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8347 dpyinfo->width = (**main_device_handle).gdRect.right;
8349 return dpyinfo;
8352 #ifdef MAC_OSX
8353 void
8354 mac_check_bundle()
8356 extern int inhibit_window_system;
8357 extern int noninteractive;
8358 CFBundleRef appsBundle;
8359 pid_t child;
8361 /* No need to test if already -nw*/
8362 if (inhibit_window_system || noninteractive)
8363 return;
8365 appsBundle = CFBundleGetMainBundle();
8366 if (appsBundle != NULL)
8368 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
8369 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
8370 /* We found the bundle identifier, now we know we are valid. */
8371 if (res != NULL)
8373 CFRelease(res);
8374 return;
8377 /* MAC_TODO: Have this start the bundled executable */
8379 /* For now, prevent the fatal error by bringing it up in the terminal */
8380 inhibit_window_system = 1;
8383 void
8384 MakeMeTheFrontProcess ()
8386 ProcessSerialNumber psn;
8387 OSErr err;
8389 err = GetCurrentProcess (&psn);
8390 if (err == noErr)
8391 (void) SetFrontProcess (&psn);
8394 /***** Code to handle C-g testing *****/
8396 /* Contains the Mac modifier formed from quit_char */
8397 static mac_quit_char_modifiers = 0;
8398 static mac_quit_char_keycode;
8399 extern int quit_char;
8401 static void
8402 mac_determine_quit_char_modifiers()
8404 /* Todo: Determine modifiers from quit_char. */
8405 UInt32 qc_modifiers = ctrl_modifier;
8407 /* Map modifiers */
8408 mac_quit_char_modifiers = 0;
8409 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
8410 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
8411 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
8412 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
8415 static void
8416 init_quit_char_handler ()
8418 /* TODO: Let this support keys other the 'g' */
8419 mac_quit_char_keycode = 5;
8420 /* Look at <architecture/adb_kb_map.h> for details */
8421 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
8423 mac_determine_quit_char_modifiers();
8426 static Boolean
8427 quit_char_comp (EventRef inEvent, void *inCompData)
8429 if (GetEventClass(inEvent) != kEventClassKeyboard)
8430 return false;
8431 if (GetEventKind(inEvent) != kEventRawKeyDown)
8432 return false;
8434 UInt32 keyCode;
8435 UInt32 keyModifiers;
8436 GetEventParameter(inEvent, kEventParamKeyCode,
8437 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
8438 if (keyCode != mac_quit_char_keycode)
8439 return false;
8440 GetEventParameter(inEvent, kEventParamKeyModifiers,
8441 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
8442 if (keyModifiers != mac_quit_char_modifiers)
8443 return false;
8445 return true;
8448 void
8449 mac_check_for_quit_char ()
8451 EventRef event;
8452 static EMACS_TIME last_check_time = { 0, 0 };
8453 static EMACS_TIME one_second = { 1, 0 };
8454 EMACS_TIME now, t;
8456 /* If windows are not initialized, return immediately (keep it bouncin'). */
8457 if (!mac_quit_char_modifiers)
8458 return;
8460 /* Don't check if last check is less than a second ago. */
8461 EMACS_GET_TIME (now);
8462 EMACS_SUB_TIME (t, now, last_check_time);
8463 if (EMACS_TIME_LT (t, one_second))
8464 return;
8465 last_check_time = now;
8467 /* Redetermine modifiers because they are based on lisp variables */
8468 mac_determine_quit_char_modifiers ();
8470 /* Fill the queue with events */
8471 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
8472 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
8473 NULL);
8474 if (event)
8476 struct input_event e;
8477 struct mac_output *mwp =
8478 (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
8479 /* Use an input_event to emulate what the interrupt handler does. */
8480 EVENT_INIT (e);
8481 e.kind = ASCII_KEYSTROKE_EVENT;
8482 e.code = quit_char;
8483 e.arg = NULL;
8484 e.modifiers = NULL;
8485 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
8486 XSETFRAME (e.frame_or_window, mwp->mFP);
8487 /* Remove event from queue to prevent looping. */
8488 RemoveEventFromQueue (GetMainEventQueue (), event);
8489 ReleaseEvent (event);
8490 kbd_buffer_store_event (&e);
8494 #endif /* MAC_OSX */
8496 /* Set up use of X before we make the first connection. */
8498 extern frame_parm_handler mac_frame_parm_handlers[];
8500 static struct redisplay_interface x_redisplay_interface =
8502 mac_frame_parm_handlers,
8503 x_produce_glyphs,
8504 x_write_glyphs,
8505 x_insert_glyphs,
8506 x_clear_end_of_line,
8507 x_scroll_run,
8508 x_after_update_window_line,
8509 x_update_window_begin,
8510 x_update_window_end,
8511 x_cursor_to,
8512 x_flush,
8513 x_flush,
8514 x_clear_window_mouse_face,
8515 x_get_glyph_overhangs,
8516 x_fix_overlapping_area,
8517 x_draw_fringe_bitmap,
8518 mac_per_char_metric,
8519 mac_encode_char,
8520 NULL, /* mac_compute_glyph_string_overhangs */
8521 x_draw_glyph_string,
8522 mac_define_frame_cursor,
8523 mac_clear_frame_area,
8524 mac_draw_window_cursor,
8525 mac_draw_vertical_window_border,
8526 mac_shift_glyphs_for_insert
8529 void
8530 mac_initialize ()
8532 rif = &x_redisplay_interface;
8534 clear_frame_hook = x_clear_frame;
8535 ins_del_lines_hook = x_ins_del_lines;
8536 delete_glyphs_hook = x_delete_glyphs;
8537 ring_bell_hook = XTring_bell;
8538 reset_terminal_modes_hook = XTreset_terminal_modes;
8539 set_terminal_modes_hook = XTset_terminal_modes;
8540 update_begin_hook = x_update_begin;
8541 update_end_hook = x_update_end;
8542 set_terminal_window_hook = XTset_terminal_window;
8543 read_socket_hook = XTread_socket;
8544 frame_up_to_date_hook = XTframe_up_to_date;
8545 mouse_position_hook = XTmouse_position;
8546 frame_rehighlight_hook = XTframe_rehighlight;
8547 frame_raise_lower_hook = XTframe_raise_lower;
8549 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
8550 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
8551 redeem_scroll_bar_hook = XTredeem_scroll_bar;
8552 judge_scroll_bars_hook = XTjudge_scroll_bars;
8554 scroll_region_ok = 1; /* we'll scroll partial frames */
8555 char_ins_del_ok = 1;
8556 line_ins_del_ok = 1; /* we'll just blt 'em */
8557 fast_clear_end_of_line = 1; /* X does this well */
8558 memory_below_frame = 0; /* we don't remember what scrolls
8559 off the bottom */
8560 baud_rate = 19200;
8562 x_noop_count = 0;
8563 last_tool_bar_item = -1;
8564 any_help_event_p = 0;
8566 /* Try to use interrupt input; if we can't, then start polling. */
8567 Fset_input_mode (Qt, Qnil, Qt, Qnil);
8569 #ifdef USE_X_TOOLKIT
8570 XtToolkitInitialize ();
8571 Xt_app_con = XtCreateApplicationContext ();
8572 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
8574 /* Install an asynchronous timer that processes Xt timeout events
8575 every 0.1s. This is necessary because some widget sets use
8576 timeouts internally, for example the LessTif menu bar, or the
8577 Xaw3d scroll bar. When Xt timouts aren't processed, these
8578 widgets don't behave normally. */
8580 EMACS_TIME interval;
8581 EMACS_SET_SECS_USECS (interval, 0, 100000);
8582 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
8584 #endif
8586 #if USE_TOOLKIT_SCROLL_BARS
8587 xaw3d_arrow_scroll = False;
8588 xaw3d_pick_top = True;
8589 #endif
8591 #if 0
8592 /* Note that there is no real way portable across R3/R4 to get the
8593 original error handler. */
8594 XSetErrorHandler (x_error_handler);
8595 XSetIOErrorHandler (x_io_error_quitter);
8597 /* Disable Window Change signals; they are handled by X events. */
8598 #ifdef SIGWINCH
8599 signal (SIGWINCH, SIG_DFL);
8600 #endif /* ! defined (SIGWINCH) */
8602 signal (SIGPIPE, x_connection_signal);
8603 #endif
8605 mac_initialize_display_info ();
8607 #if TARGET_API_MAC_CARBON
8608 init_required_apple_events ();
8610 init_mac_drag_n_drop ();
8612 #if USE_CARBON_EVENTS
8613 init_service_handler ();
8615 init_quit_char_handler ();
8616 #endif
8618 DisableMenuCommand (NULL, kHICommandQuit);
8620 if (!inhibit_window_system)
8621 MakeMeTheFrontProcess ();
8622 #endif
8626 void
8627 syms_of_macterm ()
8629 #if 0
8630 staticpro (&x_error_message_string);
8631 x_error_message_string = Qnil;
8632 #endif
8634 Fprovide (intern ("mac-carbon"), Qnil);
8636 staticpro (&x_display_name_list);
8637 x_display_name_list = Qnil;
8639 staticpro (&last_mouse_scroll_bar);
8640 last_mouse_scroll_bar = Qnil;
8642 staticpro (&Qvendor_specific_keysyms);
8643 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
8645 staticpro (&last_mouse_press_frame);
8646 last_mouse_press_frame = Qnil;
8648 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
8649 staticpro (&Qmac_ready_for_drag_n_drop);
8651 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
8652 doc: /* *Non-nil means autoselect window with mouse pointer. */);
8653 x_autoselect_window_p = 0;
8655 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
8656 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
8657 Vx_toolkit_scroll_bars = Qt;
8659 DEFVAR_BOOL ("x-use-underline-position-properties",
8660 &x_use_underline_position_properties,
8661 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
8662 nil means ignore them. If you encounter fonts with bogus
8663 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
8664 to 4.1, set this to nil. */);
8665 x_use_underline_position_properties = 0;
8667 staticpro (&last_mouse_motion_frame);
8668 last_mouse_motion_frame = Qnil;
8670 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
8671 doc: /* Non-nil means that the command key is used as the Emacs meta key.
8672 Otherwise the option key is used. */);
8673 Vmac_command_key_is_meta = Qt;
8675 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
8676 doc: /* Non-nil means that the control and meta keys are reversed. This is
8677 useful for non-standard keyboard layouts. */);
8678 Vmac_reverse_ctrl_meta = Qnil;
8680 #if USE_CARBON_EVENTS
8681 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
8682 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
8683 the right click will be mouse-3.
8684 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
8685 Vmac_wheel_button_is_mouse_2 = Qt;
8687 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
8688 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
8689 Toolbox for processing before Emacs sees it. */);
8690 Vmac_pass_command_to_system = Qt;
8692 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
8693 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
8694 Toolbox for processing before Emacs sees it. */);
8695 Vmac_pass_control_to_system = Qt;
8696 #endif
8698 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
8699 doc: /* One of the Text Encoding Base constant values defined in the
8700 Basic Text Constants section of Inside Macintosh - Text Encoding
8701 Conversion Manager. Its value determines the encoding characters
8702 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
8703 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
8704 its default value, no conversion takes place. If it is set to
8705 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
8706 characters typed on Mac keyboard are first converted into the
8707 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
8708 passed to Emacs. Together with Emacs's set-keyboard-coding-system
8709 command, this enables the Mac keyboard to be used to enter non-ASCII
8710 characters directly. */);
8711 mac_keyboard_text_encoding = kTextEncodingMacRoman;
8714 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
8715 (do not change this comment) */