Update copyright.
[emacs.git] / src / macterm.c
blob29be6659c357cb42b3b6e2a317de209f152be426
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);
1146 UNBLOCK_INPUT;
1149 /* If a row with mouse-face was overwritten, arrange for
1150 XTframe_up_to_date to redisplay the mouse highlight. */
1151 if (mouse_face_overwritten_p)
1153 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1154 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1155 dpyinfo->mouse_face_window = Qnil;
1158 #if 0
1159 /* Unhide the caret. This won't actually show the cursor, unless it
1160 was visible before the corresponding call to HideCaret in
1161 x_update_window_begin. */
1162 if (w32_use_visible_system_caret)
1163 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1164 #endif
1166 updated_window = NULL;
1170 /* End update of frame F. This function is installed as a hook in
1171 update_end. */
1173 static void
1174 x_update_end (f)
1175 struct frame *f;
1177 /* Reset the background color of Mac OS Window to that of the frame after
1178 update so that it is used by Mac Toolbox to clear the update region before
1179 an update event is generated. */
1180 #if TARGET_API_MAC_CARBON
1181 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
1182 #else
1183 SetPort (FRAME_MAC_WINDOW (f));
1184 #endif
1186 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1188 /* Mouse highlight may be displayed again. */
1189 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1191 BLOCK_INPUT;
1192 XFlush (FRAME_MAC_DISPLAY (f));
1193 UNBLOCK_INPUT;
1197 /* This function is called from various places in xdisp.c whenever a
1198 complete update has been performed. The global variable
1199 updated_window is not available here. */
1201 static void
1202 XTframe_up_to_date (f)
1203 struct frame *f;
1205 if (FRAME_X_P (f))
1207 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1209 if (dpyinfo->mouse_face_deferred_gc
1210 || f == dpyinfo->mouse_face_mouse_frame)
1212 BLOCK_INPUT;
1213 if (dpyinfo->mouse_face_mouse_frame)
1214 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1215 dpyinfo->mouse_face_mouse_x,
1216 dpyinfo->mouse_face_mouse_y);
1217 dpyinfo->mouse_face_deferred_gc = 0;
1218 UNBLOCK_INPUT;
1224 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1225 arrow bitmaps, or clear the fringes if no bitmaps are required
1226 before DESIRED_ROW is made current. The window being updated is
1227 found in updated_window. This function is called from
1228 update_window_line only if it is known that there are differences
1229 between bitmaps to be drawn between current row and DESIRED_ROW. */
1231 static void
1232 x_after_update_window_line (desired_row)
1233 struct glyph_row *desired_row;
1235 struct window *w = updated_window;
1236 struct frame *f;
1237 int width, height;
1239 xassert (w);
1241 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1243 BLOCK_INPUT;
1244 draw_row_fringe_bitmaps (w, desired_row);
1245 UNBLOCK_INPUT;
1248 /* When a window has disappeared, make sure that no rest of
1249 full-width rows stays visible in the internal border. Could
1250 check here if updated_window is the leftmost/rightmost window,
1251 but I guess it's not worth doing since vertically split windows
1252 are almost never used, internal border is rarely set, and the
1253 overhead is very small. */
1254 if (windows_or_buffers_changed
1255 && desired_row->full_width_p
1256 && (f = XFRAME (w->frame),
1257 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1258 width != 0)
1259 && (height = desired_row->visible_height,
1260 height > 0))
1262 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1263 /* Internal border is drawn below the tool bar. */
1264 if (WINDOWP (f->tool_bar_window)
1265 && w == XWINDOW (f->tool_bar_window))
1266 y -= width;
1268 BLOCK_INPUT;
1270 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1271 0, y, width, height, 0);
1272 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1273 FRAME_PIXEL_WIDTH (f) - width, y,
1274 width, height, 0);
1276 UNBLOCK_INPUT;
1281 /* Draw the bitmap WHICH in one of the left or right fringes of
1282 window W. ROW is the glyph row for which to display the bitmap; it
1283 determines the vertical position at which the bitmap has to be
1284 drawn. */
1286 static void
1287 x_draw_fringe_bitmap (w, row, p)
1288 struct window *w;
1289 struct glyph_row *row;
1290 struct draw_fringe_bitmap_params *p;
1292 struct frame *f = XFRAME (WINDOW_FRAME (w));
1293 Display *display = FRAME_MAC_DISPLAY (f);
1294 WindowPtr window = FRAME_MAC_WINDOW (f);
1295 XGCValues gcv;
1296 GC gc = f->output_data.mac->normal_gc;
1297 struct face *face = p->face;
1299 /* Must clip because of partially visible lines. */
1300 x_clip_to_row (w, row, gc);
1302 if (p->bx >= 0)
1304 XGCValues gcv;
1305 gcv.foreground = face->background;
1307 #if 0 /* MAC_TODO: stipple */
1308 /* In case the same realized face is used for fringes and
1309 for something displayed in the text (e.g. face `region' on
1310 mono-displays, the fill style may have been changed to
1311 FillSolid in x_draw_glyph_string_background. */
1312 if (face->stipple)
1313 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1314 else
1315 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1316 #endif
1318 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1319 &gcv,
1320 p->bx, p->by, p->nx, p->ny);
1322 #if 0 /* MAC_TODO: stipple */
1323 if (!face->stipple)
1324 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1325 #endif
1328 if (p->which != NO_FRINGE_BITMAP)
1330 unsigned char *bits = fringe_bitmaps[p->which].bits + p->dh;
1331 BitMap bitmap;
1333 mac_create_bitmap_from_bitmap_data (&bitmap, bits, p->wd, p->h);
1334 gcv.foreground = face->foreground;
1335 gcv.background = face->background;
1337 mac_draw_bitmap (display, window, &gcv, p->x, p->y, &bitmap);
1339 mac_free_bitmap (&bitmap);
1342 mac_reset_clipping (display, window);
1346 /* This is called when starting Emacs and when restarting after
1347 suspend. When starting Emacs, no window is mapped. And nothing
1348 must be done to Emacs's own window if it is suspended (though that
1349 rarely happens). */
1351 static void
1352 XTset_terminal_modes ()
1356 /* This is called when exiting or suspending Emacs. Exiting will make
1357 the windows go away, and suspending requires no action. */
1359 static void
1360 XTreset_terminal_modes ()
1365 /***********************************************************************
1366 Display Iterator
1367 ***********************************************************************/
1369 /* Function prototypes of this page. */
1371 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1372 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1375 /* Return a pointer to per-char metric information in FONT of a
1376 character pointed by B which is a pointer to an XChar2b. */
1378 #define PER_CHAR_METRIC(font, b) \
1379 ((font)->per_char \
1380 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1381 + (((font)->min_byte1 || (font)->max_byte1) \
1382 ? (((b)->byte1 - (font)->min_byte1) \
1383 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1384 : 0)) \
1385 : &((font)->max_bounds))
1388 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1389 is not contained in the font. */
1391 static INLINE XCharStruct *
1392 x_per_char_metric (font, char2b)
1393 XFontStruct *font;
1394 XChar2b *char2b;
1396 /* The result metric information. */
1397 XCharStruct *pcm = NULL;
1399 xassert (font && char2b);
1401 if (font->per_char != NULL)
1403 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1405 /* min_char_or_byte2 specifies the linear character index
1406 corresponding to the first element of the per_char array,
1407 max_char_or_byte2 is the index of the last character. A
1408 character with non-zero CHAR2B->byte1 is not in the font.
1409 A character with byte2 less than min_char_or_byte2 or
1410 greater max_char_or_byte2 is not in the font. */
1411 if (char2b->byte1 == 0
1412 && char2b->byte2 >= font->min_char_or_byte2
1413 && char2b->byte2 <= font->max_char_or_byte2)
1414 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1416 else
1418 /* If either min_byte1 or max_byte1 are nonzero, both
1419 min_char_or_byte2 and max_char_or_byte2 are less than
1420 256, and the 2-byte character index values corresponding
1421 to the per_char array element N (counting from 0) are:
1423 byte1 = N/D + min_byte1
1424 byte2 = N\D + min_char_or_byte2
1426 where:
1428 D = max_char_or_byte2 - min_char_or_byte2 + 1
1429 / = integer division
1430 \ = integer modulus */
1431 if (char2b->byte1 >= font->min_byte1
1432 && char2b->byte1 <= font->max_byte1
1433 && char2b->byte2 >= font->min_char_or_byte2
1434 && char2b->byte2 <= font->max_char_or_byte2)
1436 pcm = (font->per_char
1437 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1438 * (char2b->byte1 - font->min_byte1))
1439 + (char2b->byte2 - font->min_char_or_byte2));
1443 else
1445 /* If the per_char pointer is null, all glyphs between the first
1446 and last character indexes inclusive have the same
1447 information, as given by both min_bounds and max_bounds. */
1448 if (char2b->byte2 >= font->min_char_or_byte2
1449 && char2b->byte2 <= font->max_char_or_byte2)
1450 pcm = &font->max_bounds;
1453 return ((pcm == NULL
1454 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1455 ? NULL : pcm);
1458 /* RIF:
1461 static XCharStruct *
1462 mac_per_char_metric (font, char2b, font_type)
1463 XFontStruct *font;
1464 XChar2b *char2b;
1465 int font_type;
1467 return x_per_char_metric (font, char2b);
1470 /* RIF:
1471 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1472 the two-byte form of C. Encoding is returned in *CHAR2B. */
1474 static int
1475 mac_encode_char (c, char2b, font_info, two_byte_p)
1476 int c;
1477 XChar2b *char2b;
1478 struct font_info *font_info;
1479 int *two_byte_p;
1481 int charset = CHAR_CHARSET (c);
1482 XFontStruct *font = font_info->font;
1484 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1485 This may be either a program in a special encoder language or a
1486 fixed encoding. */
1487 if (font_info->font_encoder)
1489 /* It's a program. */
1490 struct ccl_program *ccl = font_info->font_encoder;
1492 if (CHARSET_DIMENSION (charset) == 1)
1494 ccl->reg[0] = charset;
1495 ccl->reg[1] = char2b->byte2;
1497 else
1499 ccl->reg[0] = charset;
1500 ccl->reg[1] = char2b->byte1;
1501 ccl->reg[2] = char2b->byte2;
1504 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1506 /* We assume that MSBs are appropriately set/reset by CCL
1507 program. */
1508 if (font->max_byte1 == 0) /* 1-byte font */
1509 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1510 else
1511 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1513 else if (font_info->encoding[charset])
1515 /* Fixed encoding scheme. See fontset.h for the meaning of the
1516 encoding numbers. */
1517 int enc = font_info->encoding[charset];
1519 if ((enc == 1 || enc == 2)
1520 && CHARSET_DIMENSION (charset) == 2)
1521 char2b->byte1 |= 0x80;
1523 if (enc == 1 || enc == 3)
1524 char2b->byte2 |= 0x80;
1526 if (enc == 4)
1528 int sjis1, sjis2;
1530 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1531 char2b->byte1 = sjis1;
1532 char2b->byte2 = sjis2;
1536 if (two_byte_p)
1537 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1539 return FONT_TYPE_UNKNOWN;
1544 /***********************************************************************
1545 Glyph display
1546 ***********************************************************************/
1549 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1550 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1551 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1552 int));
1553 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1554 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1555 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1556 static void x_draw_glyph_string P_ ((struct glyph_string *));
1557 static void x_set_cursor_gc P_ ((struct glyph_string *));
1558 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1559 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1560 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1561 unsigned long *, double, int));*/
1562 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1563 double, int, unsigned long));
1564 static void x_setup_relief_colors P_ ((struct glyph_string *));
1565 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1566 static void x_draw_image_relief P_ ((struct glyph_string *));
1567 static void x_draw_image_foreground P_ ((struct glyph_string *));
1568 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1569 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1570 int, int, int));
1571 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1572 int, int, int, int, Rect *));
1573 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1574 int, int, int, Rect *));
1576 #if GLYPH_DEBUG
1577 static void x_check_font P_ ((struct frame *, XFontStruct *));
1578 #endif
1581 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1582 face. */
1584 static void
1585 x_set_cursor_gc (s)
1586 struct glyph_string *s;
1588 if (s->font == FRAME_FONT (s->f)
1589 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1590 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1591 && !s->cmp)
1592 s->gc = s->f->output_data.mac->cursor_gc;
1593 else
1595 /* Cursor on non-default face: must merge. */
1596 XGCValues xgcv;
1597 unsigned long mask;
1599 xgcv.background = s->f->output_data.mac->cursor_pixel;
1600 xgcv.foreground = s->face->background;
1602 /* If the glyph would be invisible, try a different foreground. */
1603 if (xgcv.foreground == xgcv.background)
1604 xgcv.foreground = s->face->foreground;
1605 if (xgcv.foreground == xgcv.background)
1606 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1607 if (xgcv.foreground == xgcv.background)
1608 xgcv.foreground = s->face->foreground;
1610 /* Make sure the cursor is distinct from text in this face. */
1611 if (xgcv.background == s->face->background
1612 && xgcv.foreground == s->face->foreground)
1614 xgcv.background = s->face->foreground;
1615 xgcv.foreground = s->face->background;
1618 IF_DEBUG (x_check_font (s->f, s->font));
1619 xgcv.font = s->font;
1620 mask = GCForeground | GCBackground | GCFont;
1622 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1623 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1624 mask, &xgcv);
1625 else
1626 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1627 = XCreateGC (s->display, s->window, mask, &xgcv);
1629 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1634 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1636 static void
1637 x_set_mouse_face_gc (s)
1638 struct glyph_string *s;
1640 int face_id;
1641 struct face *face;
1643 /* What face has to be used last for the mouse face? */
1644 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1645 face = FACE_FROM_ID (s->f, face_id);
1646 if (face == NULL)
1647 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1649 if (s->first_glyph->type == CHAR_GLYPH)
1650 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1651 else
1652 face_id = FACE_FOR_CHAR (s->f, face, 0);
1653 s->face = FACE_FROM_ID (s->f, face_id);
1654 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1656 /* If font in this face is same as S->font, use it. */
1657 if (s->font == s->face->font)
1658 s->gc = s->face->gc;
1659 else
1661 /* Otherwise construct scratch_cursor_gc with values from FACE
1662 but font FONT. */
1663 XGCValues xgcv;
1664 unsigned long mask;
1666 xgcv.background = s->face->background;
1667 xgcv.foreground = s->face->foreground;
1668 IF_DEBUG (x_check_font (s->f, s->font));
1669 xgcv.font = s->font;
1670 mask = GCForeground | GCBackground | GCFont;
1672 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1673 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1674 mask, &xgcv);
1675 else
1676 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1677 = XCreateGC (s->display, s->window, mask, &xgcv);
1679 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1682 xassert (s->gc != 0);
1686 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1687 Faces to use in the mode line have already been computed when the
1688 matrix was built, so there isn't much to do, here. */
1690 static INLINE void
1691 x_set_mode_line_face_gc (s)
1692 struct glyph_string *s;
1694 s->gc = s->face->gc;
1698 /* Set S->gc of glyph string S for drawing that glyph string. Set
1699 S->stippled_p to a non-zero value if the face of S has a stipple
1700 pattern. */
1702 static INLINE void
1703 x_set_glyph_string_gc (s)
1704 struct glyph_string *s;
1706 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1708 if (s->hl == DRAW_NORMAL_TEXT)
1710 s->gc = s->face->gc;
1711 s->stippled_p = s->face->stipple != 0;
1713 else if (s->hl == DRAW_INVERSE_VIDEO)
1715 x_set_mode_line_face_gc (s);
1716 s->stippled_p = s->face->stipple != 0;
1718 else if (s->hl == DRAW_CURSOR)
1720 x_set_cursor_gc (s);
1721 s->stippled_p = 0;
1723 else if (s->hl == DRAW_MOUSE_FACE)
1725 x_set_mouse_face_gc (s);
1726 s->stippled_p = s->face->stipple != 0;
1728 else if (s->hl == DRAW_IMAGE_RAISED
1729 || s->hl == DRAW_IMAGE_SUNKEN)
1731 s->gc = s->face->gc;
1732 s->stippled_p = s->face->stipple != 0;
1734 else
1736 s->gc = s->face->gc;
1737 s->stippled_p = s->face->stipple != 0;
1740 /* GC must have been set. */
1741 xassert (s->gc != 0);
1745 /* Set clipping for output of glyph string S. S may be part of a mode
1746 line or menu if we don't have X toolkit support. */
1748 static INLINE void
1749 x_set_glyph_string_clipping (s)
1750 struct glyph_string *s;
1752 Rect r;
1753 get_glyph_string_clip_rect (s, &r);
1754 mac_set_clip_rectangle (s->display, s->window, &r);
1758 /* RIF:
1759 Compute left and right overhang of glyph string S. If S is a glyph
1760 string for a composition, assume overhangs don't exist. */
1762 static void
1763 mac_compute_glyph_string_overhangs (s)
1764 struct glyph_string *s;
1766 #if 0
1767 /* MAC_TODO: XTextExtents16 does nothing yet... */
1769 if (s->cmp == NULL
1770 && s->first_glyph->type == CHAR_GLYPH)
1772 XCharStruct cs;
1773 int direction, font_ascent, font_descent;
1774 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
1775 &font_ascent, &font_descent, &cs);
1776 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
1777 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
1779 #endif
1783 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1785 static INLINE void
1786 x_clear_glyph_string_rect (s, x, y, w, h)
1787 struct glyph_string *s;
1788 int x, y, w, h;
1790 XGCValues xgcv;
1792 xgcv.foreground = s->gc->background;
1793 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
1797 /* Draw the background of glyph_string S. If S->background_filled_p
1798 is non-zero don't draw it. FORCE_P non-zero means draw the
1799 background even if it wouldn't be drawn normally. This is used
1800 when a string preceding S draws into the background of S, or S
1801 contains the first component of a composition. */
1803 static void
1804 x_draw_glyph_string_background (s, force_p)
1805 struct glyph_string *s;
1806 int force_p;
1808 /* Nothing to do if background has already been drawn or if it
1809 shouldn't be drawn in the first place. */
1810 if (!s->background_filled_p)
1812 int box_line_width = max (s->face->box_line_width, 0);
1814 #if 0 /* MAC_TODO: stipple */
1815 if (s->stippled_p)
1817 /* Fill background with a stipple pattern. */
1818 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1819 XFillRectangle (s->display, s->window, s->gc, s->x,
1820 s->y + box_line_width,
1821 s->background_width,
1822 s->height - 2 * box_line_width);
1823 XSetFillStyle (s->display, s->gc, FillSolid);
1824 s->background_filled_p = 1;
1826 else
1827 #endif
1828 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
1829 || s->font_not_found_p
1830 || s->extends_to_end_of_line_p
1831 || force_p)
1833 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1834 s->background_width,
1835 s->height - 2 * box_line_width);
1836 s->background_filled_p = 1;
1842 /* Draw the foreground of glyph string S. */
1844 static void
1845 x_draw_glyph_string_foreground (s)
1846 struct glyph_string *s;
1848 int i, x;
1850 /* If first glyph of S has a left box line, start drawing the text
1851 of S to the right of that box line. */
1852 if (s->face->box != FACE_NO_BOX
1853 && s->first_glyph->left_box_line_p)
1854 x = s->x + abs (s->face->box_line_width);
1855 else
1856 x = s->x;
1858 /* Draw characters of S as rectangles if S's font could not be
1859 loaded. */
1860 if (s->font_not_found_p)
1862 for (i = 0; i < s->nchars; ++i)
1864 struct glyph *g = s->first_glyph + i;
1865 mac_draw_rectangle (s->display, s->window,
1866 s->gc, x, s->y, g->pixel_width - 1,
1867 s->height - 1);
1868 x += g->pixel_width;
1871 else
1873 char *char1b = (char *) s->char2b;
1874 int boff = s->font_info->baseline_offset;
1876 if (s->font_info->vertical_centering)
1877 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
1879 /* If we can use 8-bit functions, condense S->char2b. */
1880 if (!s->two_byte_p)
1881 for (i = 0; i < s->nchars; ++i)
1882 char1b[i] = s->char2b[i].byte2;
1884 /* Draw text with XDrawString if background has already been
1885 filled. Otherwise, use XDrawImageString. (Note that
1886 XDrawImageString is usually faster than XDrawString.) Always
1887 use XDrawImageString when drawing the cursor so that there is
1888 no chance that characters under a box cursor are invisible. */
1889 if (s->for_overlaps_p
1890 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1892 /* Draw characters with 16-bit or 8-bit functions. */
1893 if (s->two_byte_p)
1894 XDrawString16 (s->display, s->window, s->gc, x,
1895 s->ybase - boff, s->char2b, s->nchars);
1896 else
1897 XDrawString (s->display, s->window, s->gc, x,
1898 s->ybase - boff, char1b, s->nchars);
1900 else
1902 if (s->two_byte_p)
1903 XDrawImageString16 (s->display, s->window, s->gc, x,
1904 s->ybase - boff, s->char2b, s->nchars);
1905 else
1906 XDrawImageString (s->display, s->window, s->gc, x,
1907 s->ybase - boff, char1b, s->nchars);
1912 /* Draw the foreground of composite glyph string S. */
1914 static void
1915 x_draw_composite_glyph_string_foreground (s)
1916 struct glyph_string *s;
1918 int i, x;
1920 /* If first glyph of S has a left box line, start drawing the text
1921 of S to the right of that box line. */
1922 if (s->face->box != FACE_NO_BOX
1923 && s->first_glyph->left_box_line_p)
1924 x = s->x + abs (s->face->box_line_width);
1925 else
1926 x = s->x;
1928 /* S is a glyph string for a composition. S->gidx is the index of
1929 the first character drawn for glyphs of this composition.
1930 S->gidx == 0 means we are drawing the very first character of
1931 this composition. */
1933 /* Draw a rectangle for the composition if the font for the very
1934 first character of the composition could not be loaded. */
1935 if (s->font_not_found_p)
1937 if (s->gidx == 0)
1938 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
1939 s->width - 1, s->height - 1);
1941 else
1943 for (i = 0; i < s->nchars; i++, ++s->gidx)
1944 XDrawString16 (s->display, s->window, s->gc,
1945 x + s->cmp->offsets[s->gidx * 2],
1946 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
1947 s->char2b + i, 1);
1952 #ifdef USE_X_TOOLKIT
1954 static struct frame *x_frame_of_widget P_ ((Widget));
1957 /* Return the frame on which widget WIDGET is used.. Abort if frame
1958 cannot be determined. */
1960 static struct frame *
1961 x_frame_of_widget (widget)
1962 Widget widget;
1964 struct x_display_info *dpyinfo;
1965 Lisp_Object tail;
1966 struct frame *f;
1968 dpyinfo = x_display_info_for_display (XtDisplay (widget));
1970 /* Find the top-level shell of the widget. Note that this function
1971 can be called when the widget is not yet realized, so XtWindow
1972 (widget) == 0. That's the reason we can't simply use
1973 x_any_window_to_frame. */
1974 while (!XtIsTopLevelShell (widget))
1975 widget = XtParent (widget);
1977 /* Look for a frame with that top-level widget. Allocate the color
1978 on that frame to get the right gamma correction value. */
1979 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
1980 if (GC_FRAMEP (XCAR (tail))
1981 && (f = XFRAME (XCAR (tail)),
1982 (f->output_data.nothing != 1
1983 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
1984 && f->output_data.x->widget == widget)
1985 return f;
1987 abort ();
1991 /* Allocate the color COLOR->pixel on the screen and display of
1992 widget WIDGET in colormap CMAP. If an exact match cannot be
1993 allocated, try the nearest color available. Value is non-zero
1994 if successful. This is called from lwlib. */
1997 x_alloc_nearest_color_for_widget (widget, cmap, color)
1998 Widget widget;
1999 Colormap cmap;
2000 XColor *color;
2002 struct frame *f = x_frame_of_widget (widget);
2003 return x_alloc_nearest_color (f, cmap, color);
2007 #endif /* USE_X_TOOLKIT */
2009 #if 0 /* MAC_TODO */
2011 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2012 CMAP. If an exact match can't be allocated, try the nearest color
2013 available. Value is non-zero if successful. Set *COLOR to the
2014 color allocated. */
2017 x_alloc_nearest_color (f, cmap, color)
2018 struct frame *f;
2019 Colormap cmap;
2020 XColor *color;
2022 Display *display = FRAME_X_DISPLAY (f);
2023 Screen *screen = FRAME_X_SCREEN (f);
2024 int rc;
2026 gamma_correct (f, color);
2027 rc = XAllocColor (display, cmap, color);
2028 if (rc == 0)
2030 /* If we got to this point, the colormap is full, so we're going
2031 to try to get the next closest color. The algorithm used is
2032 a least-squares matching, which is what X uses for closest
2033 color matching with StaticColor visuals. */
2034 int nearest, i;
2035 unsigned long nearest_delta = ~0;
2036 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2037 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2039 for (i = 0; i < ncells; ++i)
2040 cells[i].pixel = i;
2041 XQueryColors (display, cmap, cells, ncells);
2043 for (nearest = i = 0; i < ncells; ++i)
2045 long dred = (color->red >> 8) - (cells[i].red >> 8);
2046 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2047 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2048 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2050 if (delta < nearest_delta)
2052 nearest = i;
2053 nearest_delta = delta;
2057 color->red = cells[nearest].red;
2058 color->green = cells[nearest].green;
2059 color->blue = cells[nearest].blue;
2060 rc = XAllocColor (display, cmap, color);
2063 #ifdef DEBUG_X_COLORS
2064 if (rc)
2065 register_color (color->pixel);
2066 #endif /* DEBUG_X_COLORS */
2068 return rc;
2072 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2073 It's necessary to do this instead of just using PIXEL directly to
2074 get color reference counts right. */
2076 unsigned long
2077 x_copy_color (f, pixel)
2078 struct frame *f;
2079 unsigned long pixel;
2081 XColor color;
2083 color.pixel = pixel;
2084 BLOCK_INPUT;
2085 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2086 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2087 UNBLOCK_INPUT;
2088 #ifdef DEBUG_X_COLORS
2089 register_color (pixel);
2090 #endif
2091 return color.pixel;
2095 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2096 It's necessary to do this instead of just using PIXEL directly to
2097 get color reference counts right. */
2099 unsigned long
2100 x_copy_dpy_color (dpy, cmap, pixel)
2101 Display *dpy;
2102 Colormap cmap;
2103 unsigned long pixel;
2105 XColor color;
2107 color.pixel = pixel;
2108 BLOCK_INPUT;
2109 XQueryColor (dpy, cmap, &color);
2110 XAllocColor (dpy, cmap, &color);
2111 UNBLOCK_INPUT;
2112 #ifdef DEBUG_X_COLORS
2113 register_color (pixel);
2114 #endif
2115 return color.pixel;
2118 #endif /* MAC_TODO */
2120 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2121 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2122 If this produces the same color as COLOR, try a color where all RGB
2123 values have DELTA added. Return the allocated color in *COLOR.
2124 DISPLAY is the X display, CMAP is the colormap to operate on.
2125 Value is non-zero if successful. */
2127 static int
2128 mac_alloc_lighter_color (f, color, factor, delta)
2129 struct frame *f;
2130 unsigned long *color;
2131 double factor;
2132 int delta;
2134 unsigned long new;
2136 /* Change RGB values by specified FACTOR. Avoid overflow! */
2137 xassert (factor >= 0);
2138 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2139 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2140 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2141 if (new == *color)
2142 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2143 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2144 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2146 /* MAC_TODO: Map to palette and retry with delta if same? */
2147 /* MAC_TODO: Free colors (if using palette)? */
2149 if (new == *color)
2150 return 0;
2152 *color = new;
2154 return 1;
2158 /* Set up the foreground color for drawing relief lines of glyph
2159 string S. RELIEF is a pointer to a struct relief containing the GC
2160 with which lines will be drawn. Use a color that is FACTOR or
2161 DELTA lighter or darker than the relief's background which is found
2162 in S->f->output_data.x->relief_background. If such a color cannot
2163 be allocated, use DEFAULT_PIXEL, instead. */
2165 static void
2166 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2167 struct frame *f;
2168 struct relief *relief;
2169 double factor;
2170 int delta;
2171 unsigned long default_pixel;
2173 XGCValues xgcv;
2174 struct mac_output *di = f->output_data.mac;
2175 unsigned long mask = GCForeground;
2176 unsigned long pixel;
2177 unsigned long background = di->relief_background;
2178 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2180 /* MAC_TODO: Free colors (if using palette)? */
2182 /* Allocate new color. */
2183 xgcv.foreground = default_pixel;
2184 pixel = background;
2185 if (mac_alloc_lighter_color (f, &pixel, factor, delta))
2187 relief->allocated_p = 1;
2188 xgcv.foreground = relief->pixel = pixel;
2191 if (relief->gc == 0)
2193 #if 0 /* MAC_TODO: stipple */
2194 xgcv.stipple = dpyinfo->gray;
2195 mask |= GCStipple;
2196 #endif
2197 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2199 else
2200 XChangeGC (NULL, relief->gc, mask, &xgcv);
2204 /* Set up colors for the relief lines around glyph string S. */
2206 static void
2207 x_setup_relief_colors (s)
2208 struct glyph_string *s;
2210 struct mac_output *di = s->f->output_data.mac;
2211 unsigned long color;
2213 if (s->face->use_box_color_for_shadows_p)
2214 color = s->face->box_color;
2215 else
2217 XGCValues xgcv;
2219 /* Get the background color of the face. */
2220 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2221 color = xgcv.background;
2224 if (di->white_relief.gc == 0
2225 || color != di->relief_background)
2227 di->relief_background = color;
2228 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2229 WHITE_PIX_DEFAULT (s->f));
2230 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2231 BLACK_PIX_DEFAULT (s->f));
2236 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2237 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2238 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2239 relief. LEFT_P non-zero means draw a relief on the left side of
2240 the rectangle. RIGHT_P non-zero means draw a relief on the right
2241 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2242 when drawing. */
2244 static void
2245 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2246 raised_p, left_p, right_p, clip_rect)
2247 struct frame *f;
2248 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
2249 Rect *clip_rect;
2251 int i;
2252 GC gc;
2254 if (raised_p)
2255 gc = f->output_data.mac->white_relief.gc;
2256 else
2257 gc = f->output_data.mac->black_relief.gc;
2258 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
2260 /* Top. */
2261 for (i = 0; i < width; ++i)
2262 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2263 left_x + i * left_p, top_y + i,
2264 right_x + 1 - i * right_p, top_y + i);
2266 /* Left. */
2267 if (left_p)
2268 for (i = 0; i < width; ++i)
2269 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2270 left_x + i, top_y + i, left_x + i, bottom_y - i);
2272 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
2273 if (raised_p)
2274 gc = f->output_data.mac->black_relief.gc;
2275 else
2276 gc = f->output_data.mac->white_relief.gc;
2277 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2278 clip_rect);
2280 /* Bottom. */
2281 for (i = 0; i < width; ++i)
2282 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2283 left_x + i * left_p, bottom_y - i,
2284 right_x + 1 - i * right_p, bottom_y - i);
2286 /* Right. */
2287 if (right_p)
2288 for (i = 0; i < width; ++i)
2289 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
2290 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
2292 mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
2296 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2297 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2298 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2299 left side of the rectangle. RIGHT_P non-zero means draw a line
2300 on the right side of the rectangle. CLIP_RECT is the clipping
2301 rectangle to use when drawing. */
2303 static void
2304 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2305 left_p, right_p, clip_rect)
2306 struct glyph_string *s;
2307 int left_x, top_y, right_x, bottom_y, left_p, right_p;
2308 Rect *clip_rect;
2310 XGCValues xgcv;
2312 xgcv.foreground = s->face->box_color;
2313 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2315 /* Top. */
2316 XFillRectangle (s->display, s->window, &xgcv,
2317 left_x, top_y, right_x - left_x, width);
2319 /* Left. */
2320 if (left_p)
2321 XFillRectangle (s->display, s->window, &xgcv,
2322 left_x, top_y, width, bottom_y - top_y);
2324 /* Bottom. */
2325 XFillRectangle (s->display, s->window, &xgcv,
2326 left_x, bottom_y - width, right_x - left_x, width);
2328 /* Right. */
2329 if (right_p)
2330 XFillRectangle (s->display, s->window, &xgcv,
2331 right_x - width, top_y, width, bottom_y - top_y);
2333 mac_reset_clipping (s->display, s->window);
2337 /* Draw a box around glyph string S. */
2339 static void
2340 x_draw_glyph_string_box (s)
2341 struct glyph_string *s;
2343 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2344 int left_p, right_p;
2345 struct glyph *last_glyph;
2346 Rect clip_rect;
2348 last_x = window_box_right (s->w, s->area);
2349 if (s->row->full_width_p
2350 && !s->w->pseudo_window_p)
2352 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2353 if (s->area != RIGHT_MARGIN_AREA
2354 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2355 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2358 /* The glyph that may have a right box line. */
2359 last_glyph = (s->cmp || s->img
2360 ? s->first_glyph
2361 : s->first_glyph + s->nchars - 1);
2363 width = abs (s->face->box_line_width);
2364 raised_p = s->face->box == FACE_RAISED_BOX;
2365 left_x = s->x;
2366 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2367 ? last_x - 1
2368 : min (last_x, s->x + s->background_width) - 1));
2369 top_y = s->y;
2370 bottom_y = top_y + s->height - 1;
2372 left_p = (s->first_glyph->left_box_line_p
2373 || (s->hl == DRAW_MOUSE_FACE
2374 && (s->prev == NULL
2375 || s->prev->hl != s->hl)));
2376 right_p = (last_glyph->right_box_line_p
2377 || (s->hl == DRAW_MOUSE_FACE
2378 && (s->next == NULL
2379 || s->next->hl != s->hl)));
2381 get_glyph_string_clip_rect (s, &clip_rect);
2383 if (s->face->box == FACE_SIMPLE_BOX)
2384 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2385 left_p, right_p, &clip_rect);
2386 else
2388 x_setup_relief_colors (s);
2389 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2390 width, raised_p, left_p, right_p, &clip_rect);
2395 /* Draw foreground of image glyph string S. */
2397 static void
2398 x_draw_image_foreground (s)
2399 struct glyph_string *s;
2401 int x;
2402 int y = s->ybase - image_ascent (s->img, s->face);
2404 /* If first glyph of S has a left box line, start drawing it to the
2405 right of that line. */
2406 if (s->face->box != FACE_NO_BOX
2407 && s->first_glyph->left_box_line_p)
2408 x = s->x + abs (s->face->box_line_width);
2409 else
2410 x = s->x;
2412 /* If there is a margin around the image, adjust x- and y-position
2413 by that margin. */
2414 x += s->img->hmargin;
2415 y += s->img->vmargin;
2417 if (s->img->pixmap)
2419 #if 0 /* MAC_TODO: image mask */
2420 if (s->img->mask)
2422 /* We can't set both a clip mask and use XSetClipRectangles
2423 because the latter also sets a clip mask. We also can't
2424 trust on the shape extension to be available
2425 (XShapeCombineRegion). So, compute the rectangle to draw
2426 manually. */
2427 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2428 | GCFunction);
2429 XGCValues xgcv;
2430 XRectangle clip_rect, image_rect, r;
2432 xgcv.clip_mask = s->img->mask;
2433 xgcv.clip_x_origin = x;
2434 xgcv.clip_y_origin = y;
2435 xgcv.function = GXcopy;
2436 XChangeGC (s->display, s->gc, mask, &xgcv);
2438 get_glyph_string_clip_rect (s, &clip_rect);
2439 image_rect.x = x;
2440 image_rect.y = y;
2441 image_rect.width = s->img->width;
2442 image_rect.height = s->img->height;
2443 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
2444 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
2445 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
2447 else
2448 #endif /* MAC_TODO */
2450 mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
2451 0, 0, s->img->width, s->img->height, x, y);
2453 /* When the image has a mask, we can expect that at
2454 least part of a mouse highlight or a block cursor will
2455 be visible. If the image doesn't have a mask, make
2456 a block cursor visible by drawing a rectangle around
2457 the image. I believe it's looking better if we do
2458 nothing here for mouse-face. */
2459 if (s->hl == DRAW_CURSOR)
2461 int r = s->img->relief;
2462 if (r < 0) r = -r;
2463 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2464 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2468 else
2469 /* Draw a rectangle if image could not be loaded. */
2470 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2471 s->img->width - 1, s->img->height - 1);
2476 /* Draw a relief around the image glyph string S. */
2478 static void
2479 x_draw_image_relief (s)
2480 struct glyph_string *s;
2482 int x0, y0, x1, y1, thick, raised_p;
2483 Rect r;
2484 int x;
2485 int y = s->ybase - image_ascent (s->img, s->face);
2487 /* If first glyph of S has a left box line, start drawing it to the
2488 right of that line. */
2489 if (s->face->box != FACE_NO_BOX
2490 && s->first_glyph->left_box_line_p)
2491 x = s->x + abs (s->face->box_line_width);
2492 else
2493 x = s->x;
2495 /* If there is a margin around the image, adjust x- and y-position
2496 by that margin. */
2497 x += s->img->hmargin;
2498 y += s->img->vmargin;
2500 if (s->hl == DRAW_IMAGE_SUNKEN
2501 || s->hl == DRAW_IMAGE_RAISED)
2503 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2504 raised_p = s->hl == DRAW_IMAGE_RAISED;
2506 else
2508 thick = abs (s->img->relief);
2509 raised_p = s->img->relief > 0;
2512 x0 = x - thick;
2513 y0 = y - thick;
2514 x1 = x + s->img->width + thick - 1;
2515 y1 = y + s->img->height + thick - 1;
2517 x_setup_relief_colors (s);
2518 get_glyph_string_clip_rect (s, &r);
2519 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
2523 /* Draw the foreground of image glyph string S to PIXMAP. */
2525 static void
2526 x_draw_image_foreground_1 (s, pixmap)
2527 struct glyph_string *s;
2528 Pixmap pixmap;
2530 int x;
2531 int y = s->ybase - s->y - image_ascent (s->img, s->face);
2533 /* If first glyph of S has a left box line, start drawing it to the
2534 right of that line. */
2535 if (s->face->box != FACE_NO_BOX
2536 && s->first_glyph->left_box_line_p)
2537 x = abs (s->face->box_line_width);
2538 else
2539 x = 0;
2541 /* If there is a margin around the image, adjust x- and y-position
2542 by that margin. */
2543 x += s->img->hmargin;
2544 y += s->img->vmargin;
2546 if (s->img->pixmap)
2548 #if 0 /* MAC_TODO: image mask */
2549 if (s->img->mask)
2551 /* We can't set both a clip mask and use XSetClipRectangles
2552 because the latter also sets a clip mask. We also can't
2553 trust on the shape extension to be available
2554 (XShapeCombineRegion). So, compute the rectangle to draw
2555 manually. */
2556 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
2557 | GCFunction);
2558 XGCValues xgcv;
2560 xgcv.clip_mask = s->img->mask;
2561 xgcv.clip_x_origin = x;
2562 xgcv.clip_y_origin = y;
2563 xgcv.function = GXcopy;
2564 XChangeGC (s->display, s->gc, mask, &xgcv);
2566 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
2567 0, 0, s->img->width, s->img->height, x, y);
2568 XSetClipMask (s->display, s->gc, None);
2570 else
2571 #endif /* MAC_TODO */
2573 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2574 0, 0, s->img->width, s->img->height, x, y);
2576 /* When the image has a mask, we can expect that at
2577 least part of a mouse highlight or a block cursor will
2578 be visible. If the image doesn't have a mask, make
2579 a block cursor visible by drawing a rectangle around
2580 the image. I believe it's looking better if we do
2581 nothing here for mouse-face. */
2582 if (s->hl == DRAW_CURSOR)
2584 int r = s->img->relief;
2585 if (r < 0) r = -r;
2586 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x - r, y - r,
2587 s->img->width + r*2 - 1, s->img->height + r*2 - 1);
2591 else
2592 /* Draw a rectangle if image could not be loaded. */
2593 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2594 s->img->width - 1, s->img->height - 1);
2598 /* Draw part of the background of glyph string S. X, Y, W, and H
2599 give the rectangle to draw. */
2601 static void
2602 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2603 struct glyph_string *s;
2604 int x, y, w, h;
2606 #if 0 /* MAC_TODO: stipple */
2607 if (s->stippled_p)
2609 /* Fill background with a stipple pattern. */
2610 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2611 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2612 XSetFillStyle (s->display, s->gc, FillSolid);
2614 else
2615 #endif /* MAC_TODO */
2616 x_clear_glyph_string_rect (s, x, y, w, h);
2620 /* Draw image glyph string S.
2622 s->y
2623 s->x +-------------------------
2624 | s->face->box
2626 | +-------------------------
2627 | | s->img->vmargin
2629 | | +-------------------
2630 | | | the image
2634 static void
2635 x_draw_image_glyph_string (s)
2636 struct glyph_string *s;
2638 int x, y;
2639 int box_line_hwidth = abs (s->face->box_line_width);
2640 int box_line_vwidth = max (s->face->box_line_width, 0);
2641 int height;
2642 Pixmap pixmap = 0;
2644 height = s->height - 2 * box_line_vwidth;
2646 /* Fill background with face under the image. Do it only if row is
2647 taller than image or if image has a clip mask to reduce
2648 flickering. */
2649 s->stippled_p = s->face->stipple != 0;
2650 if (height > s->img->height
2651 || s->img->hmargin
2652 || s->img->vmargin
2653 #if 0 /* TODO: image mask */
2654 || s->img->mask
2655 #endif
2656 || s->img->pixmap == 0
2657 || s->width != s->background_width)
2659 if (box_line_hwidth && s->first_glyph->left_box_line_p)
2660 x = s->x + box_line_hwidth;
2661 else
2662 x = s->x;
2664 y = s->y + box_line_vwidth;
2665 #if 0 /* TODO: image mask */
2666 if (s->img->mask)
2668 /* Create a pixmap as large as the glyph string. Fill it
2669 with the background color. Copy the image to it, using
2670 its mask. Copy the temporary pixmap to the display. */
2671 Screen *screen = FRAME_X_SCREEN (s->f);
2672 int depth = DefaultDepthOfScreen (screen);
2674 /* Create a pixmap as large as the glyph string. */
2675 pixmap = XCreatePixmap (s->display, s->window,
2676 s->background_width,
2677 s->height, depth);
2679 /* Don't clip in the following because we're working on the
2680 pixmap. */
2681 XSetClipMask (s->display, s->gc, None);
2683 /* Fill the pixmap with the background color/stipple. */
2684 if (s->stippled_p)
2686 /* Fill background with a stipple pattern. */
2687 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2688 XFillRectangle (s->display, pixmap, s->gc,
2689 0, 0, s->background_width, s->height);
2690 XSetFillStyle (s->display, s->gc, FillSolid);
2692 else
2694 XGCValues xgcv;
2695 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2696 &xgcv);
2697 XSetForeground (s->display, s->gc, xgcv.background);
2698 XFillRectangle (s->display, pixmap, s->gc,
2699 0, 0, s->background_width, s->height);
2700 XSetForeground (s->display, s->gc, xgcv.foreground);
2703 else
2704 #endif
2705 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2707 s->background_filled_p = 1;
2710 /* Draw the foreground. */
2711 if (pixmap != 0)
2713 x_draw_image_foreground_1 (s, pixmap);
2714 x_set_glyph_string_clipping (s);
2715 mac_copy_area (s->display, pixmap, s->window, s->gc,
2716 0, 0, s->background_width, s->height, s->x, s->y);
2717 mac_reset_clipping (s->display, s->window);
2718 XFreePixmap (s->display, pixmap);
2720 else
2721 x_draw_image_foreground (s);
2723 /* If we must draw a relief around the image, do it. */
2724 if (s->img->relief
2725 || s->hl == DRAW_IMAGE_RAISED
2726 || s->hl == DRAW_IMAGE_SUNKEN)
2727 x_draw_image_relief (s);
2731 /* Draw stretch glyph string S. */
2733 static void
2734 x_draw_stretch_glyph_string (s)
2735 struct glyph_string *s;
2737 xassert (s->first_glyph->type == STRETCH_GLYPH);
2738 s->stippled_p = s->face->stipple != 0;
2740 if (s->hl == DRAW_CURSOR
2741 && !x_stretch_cursor_p)
2743 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2744 as wide as the stretch glyph. */
2745 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
2747 /* Draw cursor. */
2748 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
2750 /* Clear rest using the GC of the original non-cursor face. */
2751 if (width < s->background_width)
2753 GC gc = s->face->gc;
2754 int x = s->x + width, y = s->y;
2755 int w = s->background_width - width, h = s->height;
2756 Rect r;
2758 if (s->row->mouse_face_p
2759 && cursor_in_mouse_face_p (s->w))
2761 x_set_mouse_face_gc (s);
2762 gc = s->gc;
2764 else
2765 gc = s->face->gc;
2767 get_glyph_string_clip_rect (s, &r);
2768 mac_set_clip_rectangle (s->display, s->window, &r);
2770 #if 0 /* MAC_TODO: stipple */
2771 if (s->face->stipple)
2773 /* Fill background with a stipple pattern. */
2774 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2775 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2776 XSetFillStyle (s->display, gc, FillSolid);
2778 else
2779 #endif /* MAC_TODO */
2781 XGCValues xgcv;
2782 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2783 XSetForeground (s->display, gc, xgcv.background);
2784 XFillRectangle (s->display, s->window, gc, x, y, w, h);
2785 XSetForeground (s->display, gc, xgcv.foreground);
2788 mac_reset_clipping (s->display, s->window);
2791 else if (!s->background_filled_p)
2792 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
2793 s->height);
2795 s->background_filled_p = 1;
2799 /* Draw glyph string S. */
2801 static void
2802 x_draw_glyph_string (s)
2803 struct glyph_string *s;
2805 int relief_drawn_p = 0;
2807 /* If S draws into the background of its successor, draw the
2808 background of the successor first so that S can draw into it.
2809 This makes S->next use XDrawString instead of XDrawImageString. */
2810 if (s->next && s->right_overhang && !s->for_overlaps_p)
2812 xassert (s->next->img == NULL);
2813 x_set_glyph_string_gc (s->next);
2814 x_set_glyph_string_clipping (s->next);
2815 x_draw_glyph_string_background (s->next, 1);
2819 /* Set up S->gc, set clipping and draw S. */
2820 x_set_glyph_string_gc (s);
2822 /* Draw relief (if any) in advance for char/composition so that the
2823 glyph string can be drawn over it. */
2824 if (!s->for_overlaps_p
2825 && s->face->box != FACE_NO_BOX
2826 && (s->first_glyph->type == CHAR_GLYPH
2827 || s->first_glyph->type == COMPOSITE_GLYPH))
2830 x_set_glyph_string_clipping (s);
2831 x_draw_glyph_string_background (s, 1);
2832 x_draw_glyph_string_box (s);
2833 x_set_glyph_string_clipping (s);
2834 relief_drawn_p = 1;
2836 else
2837 x_set_glyph_string_clipping (s);
2839 switch (s->first_glyph->type)
2841 case IMAGE_GLYPH:
2842 x_draw_image_glyph_string (s);
2843 break;
2845 case STRETCH_GLYPH:
2846 x_draw_stretch_glyph_string (s);
2847 break;
2849 case CHAR_GLYPH:
2850 if (s->for_overlaps_p)
2851 s->background_filled_p = 1;
2852 else
2853 x_draw_glyph_string_background (s, 0);
2854 x_draw_glyph_string_foreground (s);
2855 break;
2857 case COMPOSITE_GLYPH:
2858 if (s->for_overlaps_p || s->gidx > 0)
2859 s->background_filled_p = 1;
2860 else
2861 x_draw_glyph_string_background (s, 1);
2862 x_draw_composite_glyph_string_foreground (s);
2863 break;
2865 default:
2866 abort ();
2869 if (!s->for_overlaps_p)
2871 /* Draw underline. */
2872 if (s->face->underline_p)
2874 unsigned long h = 1;
2875 unsigned long dy = s->height - h;
2877 if (s->face->underline_defaulted_p)
2878 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2879 s->width, h);
2880 else
2882 XGCValues xgcv;
2883 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2884 XSetForeground (s->display, s->gc, s->face->underline_color);
2885 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2886 s->width, h);
2887 XSetForeground (s->display, s->gc, xgcv.foreground);
2891 /* Draw overline. */
2892 if (s->face->overline_p)
2894 unsigned long dy = 0, h = 1;
2896 if (s->face->overline_color_defaulted_p)
2897 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2898 s->width, h);
2899 else
2901 XGCValues xgcv;
2902 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2903 XSetForeground (s->display, s->gc, s->face->overline_color);
2904 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2905 s->width, h);
2906 XSetForeground (s->display, s->gc, xgcv.foreground);
2910 /* Draw strike-through. */
2911 if (s->face->strike_through_p)
2913 unsigned long h = 1;
2914 unsigned long dy = (s->height - h) / 2;
2916 if (s->face->strike_through_color_defaulted_p)
2917 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2918 s->width, h);
2919 else
2921 XGCValues xgcv;
2922 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2923 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2924 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
2925 s->width, h);
2926 XSetForeground (s->display, s->gc, xgcv.foreground);
2930 /* Draw relief. */
2931 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
2932 x_draw_glyph_string_box (s);
2935 /* Reset clipping. */
2936 mac_reset_clipping (s->display, s->window);
2939 /* Shift display to make room for inserted glyphs. */
2941 void
2942 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
2943 struct frame *f;
2944 int x, y, width, height, shift_by;
2946 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
2947 f->output_data.mac->normal_gc,
2948 x, y, width, height,
2949 x + shift_by, y);
2953 /* Delete N glyphs at the nominal cursor position. Not implemented
2954 for X frames. */
2956 static void
2957 x_delete_glyphs (n)
2958 register int n;
2960 abort ();
2964 /* Clear entire frame. If updating_frame is non-null, clear that
2965 frame. Otherwise clear the selected frame. */
2967 static void
2968 x_clear_frame ()
2970 struct frame *f;
2972 if (updating_frame)
2973 f = updating_frame;
2974 else
2975 f = SELECTED_FRAME ();
2977 /* Clearing the frame will erase any cursor, so mark them all as no
2978 longer visible. */
2979 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
2980 output_cursor.hpos = output_cursor.vpos = 0;
2981 output_cursor.x = -1;
2983 /* We don't set the output cursor here because there will always
2984 follow an explicit cursor_to. */
2985 BLOCK_INPUT;
2986 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
2988 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
2989 /* We have to clear the scroll bars, too. If we have changed
2990 colors or something like that, then they should be notified. */
2991 x_scroll_bar_clear (f);
2992 #endif
2994 XFlush (FRAME_MAC_DISPLAY (f));
2995 UNBLOCK_INPUT;
3000 /* Invert the middle quarter of the frame for .15 sec. */
3002 /* We use the select system call to do the waiting, so we have to make
3003 sure it's available. If it isn't, we just won't do visual bells. */
3005 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3007 /* Subtract the `struct timeval' values X and Y, storing the result in
3008 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3010 static int
3011 timeval_subtract (result, x, y)
3012 struct timeval *result, x, y;
3014 /* Perform the carry for the later subtraction by updating y. This
3015 is safer because on some systems the tv_sec member is unsigned. */
3016 if (x.tv_usec < y.tv_usec)
3018 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3019 y.tv_usec -= 1000000 * nsec;
3020 y.tv_sec += nsec;
3023 if (x.tv_usec - y.tv_usec > 1000000)
3025 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3026 y.tv_usec += 1000000 * nsec;
3027 y.tv_sec -= nsec;
3030 /* Compute the time remaining to wait. tv_usec is certainly
3031 positive. */
3032 result->tv_sec = x.tv_sec - y.tv_sec;
3033 result->tv_usec = x.tv_usec - y.tv_usec;
3035 /* Return indication of whether the result should be considered
3036 negative. */
3037 return x.tv_sec < y.tv_sec;
3040 void
3041 XTflash (f)
3042 struct frame *f;
3044 BLOCK_INPUT;
3046 FlashMenuBar (0);
3049 struct timeval wakeup;
3051 EMACS_GET_TIME (wakeup);
3053 /* Compute time to wait until, propagating carry from usecs. */
3054 wakeup.tv_usec += 150000;
3055 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3056 wakeup.tv_usec %= 1000000;
3058 /* Keep waiting until past the time wakeup. */
3059 while (1)
3061 struct timeval timeout;
3063 EMACS_GET_TIME (timeout);
3065 /* In effect, timeout = wakeup - timeout.
3066 Break if result would be negative. */
3067 if (timeval_subtract (&timeout, wakeup, timeout))
3068 break;
3070 /* Try to wait that long--but we might wake up sooner. */
3071 select (0, NULL, NULL, NULL, &timeout);
3075 FlashMenuBar (0);
3077 UNBLOCK_INPUT;
3080 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3083 /* Make audible bell. */
3085 void
3086 XTring_bell ()
3088 struct frame *f = SELECTED_FRAME ();
3090 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3091 if (visible_bell)
3092 XTflash (f);
3093 else
3094 #endif
3096 BLOCK_INPUT;
3097 SysBeep (1);
3098 XFlush (FRAME_MAC_DISPLAY (f));
3099 UNBLOCK_INPUT;
3105 /* Specify how many text lines, from the top of the window,
3106 should be affected by insert-lines and delete-lines operations.
3107 This, and those operations, are used only within an update
3108 that is bounded by calls to x_update_begin and x_update_end. */
3110 void
3111 XTset_terminal_window (n)
3112 register int n;
3114 /* This function intentionally left blank. */
3119 /***********************************************************************
3120 Line Dance
3121 ***********************************************************************/
3123 /* Perform an insert-lines or delete-lines operation, inserting N
3124 lines or deleting -N lines at vertical position VPOS. */
3126 static void
3127 x_ins_del_lines (vpos, n)
3128 int vpos, n;
3130 abort ();
3134 /* Scroll part of the display as described by RUN. */
3136 static void
3137 x_scroll_run (w, run)
3138 struct window *w;
3139 struct run *run;
3141 struct frame *f = XFRAME (w->frame);
3142 int x, y, width, height, from_y, to_y, bottom_y;
3144 /* Get frame-relative bounding box of the text display area of W,
3145 without mode lines. Include in this box the left and right
3146 fringes of W. */
3147 window_box (w, -1, &x, &y, &width, &height);
3149 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3150 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3151 bottom_y = y + height;
3153 if (to_y < from_y)
3155 /* Scrolling up. Make sure we don't copy part of the mode
3156 line at the bottom. */
3157 if (from_y + run->height > bottom_y)
3158 height = bottom_y - from_y;
3159 else
3160 height = run->height;
3162 else
3164 /* Scolling down. Make sure we don't copy over the mode line.
3165 at the bottom. */
3166 if (to_y + run->height > bottom_y)
3167 height = bottom_y - to_y;
3168 else
3169 height = run->height;
3172 BLOCK_INPUT;
3174 /* Cursor off. Will be switched on again in x_update_window_end. */
3175 updated_window = w;
3176 x_clear_cursor (w);
3178 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3179 f->output_data.mac->normal_gc,
3180 x, from_y,
3181 width, height,
3182 x, to_y);
3184 UNBLOCK_INPUT;
3189 /***********************************************************************
3190 Exposure Events
3191 ***********************************************************************/
3194 static void
3195 frame_highlight (f)
3196 struct frame *f;
3198 x_update_cursor (f, 1);
3201 static void
3202 frame_unhighlight (f)
3203 struct frame *f;
3205 x_update_cursor (f, 1);
3208 /* The focus has changed. Update the frames as necessary to reflect
3209 the new situation. Note that we can't change the selected frame
3210 here, because the Lisp code we are interrupting might become confused.
3211 Each event gets marked with the frame in which it occurred, so the
3212 Lisp code can tell when the switch took place by examining the events. */
3214 static void
3215 x_new_focus_frame (dpyinfo, frame)
3216 struct x_display_info *dpyinfo;
3217 struct frame *frame;
3219 struct frame *old_focus = dpyinfo->x_focus_frame;
3221 if (frame != dpyinfo->x_focus_frame)
3223 /* Set this before calling other routines, so that they see
3224 the correct value of x_focus_frame. */
3225 dpyinfo->x_focus_frame = frame;
3227 if (old_focus && old_focus->auto_lower)
3228 x_lower_frame (old_focus);
3230 #if 0
3231 selected_frame = frame;
3232 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3233 selected_frame);
3234 Fselect_window (selected_frame->selected_window, Qnil);
3235 choose_minibuf_frame ();
3236 #endif /* ! 0 */
3238 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3239 pending_autoraise_frame = dpyinfo->x_focus_frame;
3240 else
3241 pending_autoraise_frame = 0;
3244 x_frame_rehighlight (dpyinfo);
3247 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3249 void
3250 x_mouse_leave (dpyinfo)
3251 struct x_display_info *dpyinfo;
3253 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3256 /* The focus has changed, or we have redirected a frame's focus to
3257 another frame (this happens when a frame uses a surrogate
3258 mini-buffer frame). Shift the highlight as appropriate.
3260 The FRAME argument doesn't necessarily have anything to do with which
3261 frame is being highlighted or un-highlighted; we only use it to find
3262 the appropriate X display info. */
3264 static void
3265 XTframe_rehighlight (frame)
3266 struct frame *frame;
3270 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3273 static void
3274 x_frame_rehighlight (dpyinfo)
3275 struct x_display_info *dpyinfo;
3277 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3279 if (dpyinfo->x_focus_frame)
3281 dpyinfo->x_highlight_frame
3282 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3283 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3284 : dpyinfo->x_focus_frame);
3285 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3287 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3288 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3291 else
3292 dpyinfo->x_highlight_frame = 0;
3294 if (dpyinfo->x_highlight_frame != old_highlight)
3296 if (old_highlight)
3297 frame_unhighlight (old_highlight);
3298 if (dpyinfo->x_highlight_frame)
3299 frame_highlight (dpyinfo->x_highlight_frame);
3305 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3307 #if 0 /* MAC_TODO */
3308 /* Initialize mode_switch_bit and modifier_meaning. */
3309 static void
3310 x_find_modifier_meanings (dpyinfo)
3311 struct x_display_info *dpyinfo;
3313 int min_code, max_code;
3314 KeySym *syms;
3315 int syms_per_code;
3316 XModifierKeymap *mods;
3318 dpyinfo->meta_mod_mask = 0;
3319 dpyinfo->shift_lock_mask = 0;
3320 dpyinfo->alt_mod_mask = 0;
3321 dpyinfo->super_mod_mask = 0;
3322 dpyinfo->hyper_mod_mask = 0;
3324 #ifdef HAVE_X11R4
3325 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3326 #else
3327 min_code = dpyinfo->display->min_keycode;
3328 max_code = dpyinfo->display->max_keycode;
3329 #endif
3331 syms = XGetKeyboardMapping (dpyinfo->display,
3332 min_code, max_code - min_code + 1,
3333 &syms_per_code);
3334 mods = XGetModifierMapping (dpyinfo->display);
3336 /* Scan the modifier table to see which modifier bits the Meta and
3337 Alt keysyms are on. */
3339 int row, col; /* The row and column in the modifier table. */
3341 for (row = 3; row < 8; row++)
3342 for (col = 0; col < mods->max_keypermod; col++)
3344 KeyCode code
3345 = mods->modifiermap[(row * mods->max_keypermod) + col];
3347 /* Zeroes are used for filler. Skip them. */
3348 if (code == 0)
3349 continue;
3351 /* Are any of this keycode's keysyms a meta key? */
3353 int code_col;
3355 for (code_col = 0; code_col < syms_per_code; code_col++)
3357 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3359 switch (sym)
3361 case XK_Meta_L:
3362 case XK_Meta_R:
3363 dpyinfo->meta_mod_mask |= (1 << row);
3364 break;
3366 case XK_Alt_L:
3367 case XK_Alt_R:
3368 dpyinfo->alt_mod_mask |= (1 << row);
3369 break;
3371 case XK_Hyper_L:
3372 case XK_Hyper_R:
3373 dpyinfo->hyper_mod_mask |= (1 << row);
3374 break;
3376 case XK_Super_L:
3377 case XK_Super_R:
3378 dpyinfo->super_mod_mask |= (1 << row);
3379 break;
3381 case XK_Shift_Lock:
3382 /* Ignore this if it's not on the lock modifier. */
3383 if ((1 << row) == LockMask)
3384 dpyinfo->shift_lock_mask = LockMask;
3385 break;
3392 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3393 if (! dpyinfo->meta_mod_mask)
3395 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3396 dpyinfo->alt_mod_mask = 0;
3399 /* If some keys are both alt and meta,
3400 make them just meta, not alt. */
3401 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3403 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3406 XFree ((char *) syms);
3407 XFreeModifiermap (mods);
3410 #endif /* MAC_TODO */
3412 /* Convert between the modifier bits X uses and the modifier bits
3413 Emacs uses. */
3415 static unsigned int
3416 x_mac_to_emacs_modifiers (dpyinfo, state)
3417 struct x_display_info *dpyinfo;
3418 unsigned short state;
3420 return (((state & shiftKey) ? shift_modifier : 0)
3421 | ((state & controlKey) ? ctrl_modifier : 0)
3422 | ((state & cmdKey) ? meta_modifier : 0)
3423 | ((state & optionKey) ? alt_modifier : 0));
3426 #if 0 /* MAC_TODO */
3427 static unsigned short
3428 x_emacs_to_x_modifiers (dpyinfo, state)
3429 struct x_display_info *dpyinfo;
3430 unsigned int state;
3432 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3433 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3434 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3435 | ((state & shift_modifier) ? ShiftMask : 0)
3436 | ((state & ctrl_modifier) ? ControlMask : 0)
3437 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3439 #endif /* MAC_TODO */
3441 /* Convert a keysym to its name. */
3443 char *
3444 x_get_keysym_name (keysym)
3445 int keysym;
3447 char *value;
3449 BLOCK_INPUT;
3450 #if 0
3451 value = XKeysymToString (keysym);
3452 #else
3453 value = 0;
3454 #endif
3455 UNBLOCK_INPUT;
3457 return value;
3462 /* Mouse clicks and mouse movement. Rah. */
3464 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3466 If the event is a button press, then note that we have grabbed
3467 the mouse. */
3469 static Lisp_Object
3470 construct_mouse_click (result, event, f)
3471 struct input_event *result;
3472 EventRecord *event;
3473 struct frame *f;
3475 Point mouseLoc;
3477 result->kind = MOUSE_CLICK_EVENT;
3478 result->code = 0; /* only one mouse button */
3479 result->timestamp = event->when;
3480 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3482 mouseLoc = event->where;
3484 #if TARGET_API_MAC_CARBON
3485 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
3486 #else
3487 SetPort (FRAME_MAC_WINDOW (f));
3488 #endif
3490 GlobalToLocal (&mouseLoc);
3491 XSETINT (result->x, mouseLoc.h);
3492 XSETINT (result->y, mouseLoc.v);
3494 XSETFRAME (result->frame_or_window, f);
3496 result->arg = Qnil;
3497 return Qnil;
3501 /* Function to report a mouse movement to the mainstream Emacs code.
3502 The input handler calls this.
3504 We have received a mouse movement event, which is given in *event.
3505 If the mouse is over a different glyph than it was last time, tell
3506 the mainstream emacs code by setting mouse_moved. If not, ask for
3507 another motion event, so we can check again the next time it moves. */
3509 static Point last_mouse_motion_position;
3510 static Lisp_Object last_mouse_motion_frame;
3512 static void
3513 note_mouse_movement (frame, pos)
3514 FRAME_PTR frame;
3515 Point *pos;
3517 #if TARGET_API_MAC_CARBON
3518 Rect r;
3519 #endif
3521 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3522 last_mouse_motion_position = *pos;
3523 XSETFRAME (last_mouse_motion_frame, frame);
3525 #if TARGET_API_MAC_CARBON
3526 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3527 #else
3528 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3529 #endif
3531 frame->mouse_moved = 1;
3532 last_mouse_scroll_bar = Qnil;
3533 note_mouse_highlight (frame, -1, -1);
3535 /* Has the mouse moved off the glyph it was on at the last sighting? */
3536 else if (pos->h < last_mouse_glyph.left
3537 || pos->h >= last_mouse_glyph.right
3538 || pos->v < last_mouse_glyph.top
3539 || pos->v >= last_mouse_glyph.bottom)
3541 frame->mouse_moved = 1;
3542 last_mouse_scroll_bar = Qnil;
3543 note_mouse_highlight (frame, pos->h, pos->v);
3547 /* This is used for debugging, to turn off note_mouse_highlight. */
3549 int disable_mouse_highlight;
3553 /************************************************************************
3554 Mouse Face
3555 ************************************************************************/
3557 static struct scroll_bar *x_window_to_scroll_bar ();
3558 static void x_scroll_bar_report_motion ();
3559 static void x_check_fullscreen P_ ((struct frame *));
3560 static void x_check_fullscreen_move P_ ((struct frame *));
3561 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3564 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3566 static void
3567 redo_mouse_highlight ()
3569 if (!NILP (last_mouse_motion_frame)
3570 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3571 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3572 last_mouse_motion_position.h,
3573 last_mouse_motion_position.v);
3577 /* Try to determine frame pixel position and size of the glyph under
3578 frame pixel coordinates X/Y on frame F . Return the position and
3579 size in *RECT. Value is non-zero if we could compute these
3580 values. */
3582 static int
3583 glyph_rect (f, x, y, rect)
3584 struct frame *f;
3585 int x, y;
3586 Rect *rect;
3588 Lisp_Object window;
3590 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3592 if (!NILP (window))
3594 struct window *w = XWINDOW (window);
3595 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3596 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3598 for (; r < end && r->enabled_p; ++r)
3599 if (r->y <= y && r->y + r->height > y)
3601 /* Found the row at y. */
3602 struct glyph *g = r->glyphs[TEXT_AREA];
3603 struct glyph *end = g + r->used[TEXT_AREA];
3604 int gx;
3606 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3607 rect->bottom = rect->top + r->height;
3609 if (x < r->x)
3611 /* x is to the left of the first glyph in the row. */
3612 /* Shouldn't this be a pixel value?
3613 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3614 ++KFS */
3615 rect->left = WINDOW_LEFT_EDGE_COL (w);
3616 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3617 return 1;
3620 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3621 if (gx <= x && gx + g->pixel_width > x)
3623 /* x is on a glyph. */
3624 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3625 rect->right = rect->left + g->pixel_width;
3626 return 1;
3629 /* x is to the right of the last glyph in the row. */
3630 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3631 /* Shouldn't this be a pixel value?
3632 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3633 ++KFS */
3634 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3635 return 1;
3639 /* The y is not on any row. */
3640 return 0;
3643 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3645 /* Record the position of the mouse in last_mouse_glyph. */
3646 static void
3647 remember_mouse_glyph (f1, gx, gy)
3648 struct frame * f1;
3649 int gx, gy;
3651 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3653 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3654 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3656 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3657 round down even for negative values. */
3658 if (gx < 0)
3659 gx -= width - 1;
3660 if (gy < 0)
3661 gy -= height - 1;
3662 #if 0
3663 /* This was the original code from XTmouse_position, but it seems
3664 to give the position of the glyph diagonally next to the one
3665 the mouse is over. */
3666 gx = (gx + width - 1) / width * width;
3667 gy = (gy + height - 1) / height * height;
3668 #else
3669 gx = gx / width * width;
3670 gy = gy / height * height;
3671 #endif
3673 last_mouse_glyph.left = gx;
3674 last_mouse_glyph.top = gy;
3675 last_mouse_glyph.right = gx + width;
3676 last_mouse_glyph.bottom = gy + height;
3681 /* Return the current position of the mouse.
3682 *fp should be a frame which indicates which display to ask about.
3684 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3685 and *part to the frame, window, and scroll bar part that the mouse
3686 is over. Set *x and *y to the portion and whole of the mouse's
3687 position on the scroll bar.
3689 If the mouse movement started elsewhere, set *fp to the frame the
3690 mouse is on, *bar_window to nil, and *x and *y to the character cell
3691 the mouse is over.
3693 Set *time to the server time-stamp for the time at which the mouse
3694 was at this position.
3696 Don't store anything if we don't have a valid set of values to report.
3698 This clears the mouse_moved flag, so we can wait for the next mouse
3699 movement. */
3701 static void
3702 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3703 FRAME_PTR *fp;
3704 int insist;
3705 Lisp_Object *bar_window;
3706 enum scroll_bar_part *part;
3707 Lisp_Object *x, *y;
3708 unsigned long *time;
3710 Point mouse_pos;
3711 int ignore1, ignore2;
3712 WindowPtr wp = FrontWindow ();
3713 struct frame *f;
3714 Lisp_Object frame, tail;
3716 if (is_emacs_window(wp))
3717 f = ((mac_output *) GetWRefCon (wp))->mFP;
3719 BLOCK_INPUT;
3721 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3722 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3723 else
3725 /* Clear the mouse-moved flag for every frame on this display. */
3726 FOR_EACH_FRAME (tail, frame)
3727 XFRAME (frame)->mouse_moved = 0;
3729 last_mouse_scroll_bar = Qnil;
3731 #if TARGET_API_MAC_CARBON
3732 SetPort (GetWindowPort (wp));
3733 #else
3734 SetPort (wp);
3735 #endif
3737 GetMouse (&mouse_pos);
3739 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3740 &last_mouse_glyph, insist);
3742 *bar_window = Qnil;
3743 *part = scroll_bar_handle;
3744 *fp = f;
3745 XSETINT (*x, mouse_pos.h);
3746 XSETINT (*y, mouse_pos.v);
3747 *time = last_mouse_movement_time;
3750 UNBLOCK_INPUT;
3754 /***********************************************************************
3755 Tool-bars
3756 ***********************************************************************/
3758 /* Handle mouse button event on the tool-bar of frame F, at
3759 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3760 or ButtonRelase. */
3762 static void
3763 mac_handle_tool_bar_click (f, button_event)
3764 struct frame *f;
3765 EventRecord *button_event;
3767 int x = button_event->where.h;
3768 int y = button_event->where.v;
3770 if (button_event->what == mouseDown)
3771 handle_tool_bar_click (f, x, y, 1, 0);
3772 else
3773 handle_tool_bar_click (f, x, y, 0,
3774 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
3775 button_event->modifiers));
3779 /************************************************************************
3780 Scroll bars, general
3781 ************************************************************************/
3783 /* Create a scroll bar and return the scroll bar vector for it. W is
3784 the Emacs window on which to create the scroll bar. TOP, LEFT,
3785 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
3786 scroll bar. */
3788 static struct scroll_bar *
3789 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
3790 struct window *w;
3791 int top, left, width, height, disp_top, disp_height;
3793 struct frame *f = XFRAME (w->frame);
3794 struct scroll_bar *bar
3795 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
3796 Rect r;
3797 ControlHandle ch;
3799 BLOCK_INPUT;
3801 r.left = left;
3802 r.top = disp_top;
3803 r.right = left + width;
3804 r.bottom = disp_top + disp_height;
3806 #ifdef TARGET_API_MAC_CARBON
3807 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
3808 kControlScrollBarProc, 0L);
3809 #else
3810 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
3811 0L);
3812 #endif
3813 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
3814 SetControlReference (ch, (long) bar);
3816 XSETWINDOW (bar->window, w);
3817 XSETINT (bar->top, top);
3818 XSETINT (bar->left, left);
3819 XSETINT (bar->width, width);
3820 XSETINT (bar->height, height);
3821 XSETINT (bar->start, 0);
3822 XSETINT (bar->end, 0);
3823 bar->dragging = Qnil;
3825 /* Add bar to its frame's list of scroll bars. */
3826 bar->next = FRAME_SCROLL_BARS (f);
3827 bar->prev = Qnil;
3828 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
3829 if (!NILP (bar->next))
3830 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
3832 UNBLOCK_INPUT;
3833 return bar;
3837 /* Draw BAR's handle in the proper position.
3839 If the handle is already drawn from START to END, don't bother
3840 redrawing it, unless REBUILD is non-zero; in that case, always
3841 redraw it. (REBUILD is handy for drawing the handle after expose
3842 events.)
3844 Normally, we want to constrain the start and end of the handle to
3845 fit inside its rectangle, but if the user is dragging the scroll
3846 bar handle, we want to let them drag it down all the way, so that
3847 the bar's top is as far down as it goes; otherwise, there's no way
3848 to move to the very end of the buffer. */
3850 static void
3851 x_scroll_bar_set_handle (bar, start, end, rebuild)
3852 struct scroll_bar *bar;
3853 int start, end;
3854 int rebuild;
3856 int dragging = ! NILP (bar->dragging);
3857 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
3858 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3859 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
3860 int length = end - start;
3862 /* If the display is already accurate, do nothing. */
3863 if (! rebuild
3864 && start == XINT (bar->start)
3865 && end == XINT (bar->end))
3866 return;
3868 BLOCK_INPUT;
3870 /* Make sure the values are reasonable, and try to preserve the
3871 distance between start and end. */
3872 if (start < 0)
3873 start = 0;
3874 else if (start > top_range)
3875 start = top_range;
3876 end = start + length;
3878 if (end < start)
3879 end = start;
3880 else if (end > top_range && ! dragging)
3881 end = top_range;
3883 /* Store the adjusted setting in the scroll bar. */
3884 XSETINT (bar->start, start);
3885 XSETINT (bar->end, end);
3887 /* Clip the end position, just for display. */
3888 if (end > top_range)
3889 end = top_range;
3891 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
3892 top positions, to make sure the handle is always at least that
3893 many pixels tall. */
3894 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
3896 SetControlMinimum (ch, 0);
3897 /* Don't inadvertently activate deactivated scroll bars */
3898 if (GetControlMaximum (ch) != -1)
3899 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
3900 - (end - start));
3901 SetControlValue (ch, start);
3902 #if TARGET_API_MAC_CARBON
3903 SetControlViewSize (ch, end - start);
3904 #endif
3906 UNBLOCK_INPUT;
3910 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
3911 nil. */
3913 static void
3914 x_scroll_bar_remove (bar)
3915 struct scroll_bar *bar;
3917 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3919 BLOCK_INPUT;
3921 /* Destroy the Mac scroll bar control */
3922 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
3924 /* Disassociate this scroll bar from its window. */
3925 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
3927 UNBLOCK_INPUT;
3930 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3931 that we are displaying PORTION characters out of a total of WHOLE
3932 characters, starting at POSITION. If WINDOW has no scroll bar,
3933 create one. */
3934 static void
3935 XTset_vertical_scroll_bar (w, portion, whole, position)
3936 struct window *w;
3937 int portion, whole, position;
3939 struct frame *f = XFRAME (w->frame);
3940 struct scroll_bar *bar;
3941 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
3942 int window_y, window_height;
3944 /* Get window dimensions. */
3945 window_box (w, -1, 0, &window_y, 0, &window_height);
3946 top = window_y;
3947 #ifdef MAC_OSX
3948 width = 16;
3949 #else
3950 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
3951 #endif
3952 height = window_height;
3954 /* Compute the left edge of the scroll bar area. */
3955 left = WINDOW_SCROLL_BAR_AREA_X (w);
3957 /* Compute the width of the scroll bar which might be less than
3958 the width of the area reserved for the scroll bar. */
3959 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
3960 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
3961 else
3962 sb_width = width;
3964 /* Compute the left edge of the scroll bar. */
3965 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
3966 sb_left = left + width - sb_width - (width - sb_width) / 2;
3967 else
3968 sb_left = left + (width - sb_width) / 2;
3970 /* Adjustments according to Inside Macintosh to make it look nice */
3971 disp_top = top;
3972 disp_height = height;
3973 if (disp_top == 0)
3975 disp_top = -1;
3976 disp_height++;
3978 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
3980 disp_top++;
3981 disp_height--;
3984 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
3985 sb_left++;
3987 /* Does the scroll bar exist yet? */
3988 if (NILP (w->vertical_scroll_bar))
3990 BLOCK_INPUT;
3991 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3992 left, top, width, height, 0);
3993 UNBLOCK_INPUT;
3994 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
3995 disp_height);
3996 XSETVECTOR (w->vertical_scroll_bar, bar);
3998 else
4000 /* It may just need to be moved and resized. */
4001 ControlHandle ch;
4003 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4004 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4006 BLOCK_INPUT;
4008 /* If already correctly positioned, do nothing. */
4009 if (XINT (bar->left) == sb_left
4010 && XINT (bar->top) == top
4011 && XINT (bar->width) == sb_width
4012 && XINT (bar->height) == height)
4013 Draw1Control (ch);
4014 else
4016 /* Clear areas not covered by the scroll bar because it's not as
4017 wide as the area reserved for it . This makes sure a
4018 previous mode line display is cleared after C-x 2 C-x 1, for
4019 example. */
4020 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4021 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4022 left, top, area_width, height, 0);
4024 #if 0
4025 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4026 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4027 sb_left - 1, top, 1, height, 0);
4028 #endif
4030 HideControl (ch);
4031 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4032 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4033 disp_height);
4034 ShowControl (ch);
4036 /* Remember new settings. */
4037 XSETINT (bar->left, sb_left);
4038 XSETINT (bar->top, top);
4039 XSETINT (bar->width, sb_width);
4040 XSETINT (bar->height, height);
4043 UNBLOCK_INPUT;
4046 /* Set the scroll bar's current state, unless we're currently being
4047 dragged. */
4048 if (NILP (bar->dragging))
4050 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4052 if (whole == 0)
4053 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4054 else
4056 int start = ((double) position * top_range) / whole;
4057 int end = ((double) (position + portion) * top_range) / whole;
4058 x_scroll_bar_set_handle (bar, start, end, 0);
4064 /* The following three hooks are used when we're doing a thorough
4065 redisplay of the frame. We don't explicitly know which scroll bars
4066 are going to be deleted, because keeping track of when windows go
4067 away is a real pain - "Can you say set-window-configuration, boys
4068 and girls?" Instead, we just assert at the beginning of redisplay
4069 that *all* scroll bars are to be removed, and then save a scroll bar
4070 from the fiery pit when we actually redisplay its window. */
4072 /* Arrange for all scroll bars on FRAME to be removed at the next call
4073 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4074 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4076 static void
4077 XTcondemn_scroll_bars (frame)
4078 FRAME_PTR frame;
4080 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4081 while (! NILP (FRAME_SCROLL_BARS (frame)))
4083 Lisp_Object bar;
4084 bar = FRAME_SCROLL_BARS (frame);
4085 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4086 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4087 XSCROLL_BAR (bar)->prev = Qnil;
4088 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4089 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4090 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4095 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4096 Note that WINDOW isn't necessarily condemned at all. */
4098 static void
4099 XTredeem_scroll_bar (window)
4100 struct window *window;
4102 struct scroll_bar *bar;
4104 /* We can't redeem this window's scroll bar if it doesn't have one. */
4105 if (NILP (window->vertical_scroll_bar))
4106 abort ();
4108 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4110 /* Unlink it from the condemned list. */
4112 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4114 if (NILP (bar->prev))
4116 /* If the prev pointer is nil, it must be the first in one of
4117 the lists. */
4118 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4119 /* It's not condemned. Everything's fine. */
4120 return;
4121 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4122 window->vertical_scroll_bar))
4123 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4124 else
4125 /* If its prev pointer is nil, it must be at the front of
4126 one or the other! */
4127 abort ();
4129 else
4130 XSCROLL_BAR (bar->prev)->next = bar->next;
4132 if (! NILP (bar->next))
4133 XSCROLL_BAR (bar->next)->prev = bar->prev;
4135 bar->next = FRAME_SCROLL_BARS (f);
4136 bar->prev = Qnil;
4137 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4138 if (! NILP (bar->next))
4139 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4143 /* Remove all scroll bars on FRAME that haven't been saved since the
4144 last call to `*condemn_scroll_bars_hook'. */
4146 static void
4147 XTjudge_scroll_bars (f)
4148 FRAME_PTR f;
4150 Lisp_Object bar, next;
4152 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4154 /* Clear out the condemned list now so we won't try to process any
4155 more events on the hapless scroll bars. */
4156 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4158 for (; ! NILP (bar); bar = next)
4160 struct scroll_bar *b = XSCROLL_BAR (bar);
4162 x_scroll_bar_remove (b);
4164 next = b->next;
4165 b->next = b->prev = Qnil;
4168 /* Now there should be no references to the condemned scroll bars,
4169 and they should get garbage-collected. */
4173 void
4174 activate_scroll_bars (frame)
4175 FRAME_PTR frame;
4177 Lisp_Object bar;
4178 ControlHandle ch;
4180 bar = FRAME_SCROLL_BARS (frame);
4181 while (! NILP (bar))
4183 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4184 #ifdef TARGET_API_MAC_CARBON
4185 ActivateControl (ch);
4186 #else
4187 SetControlMaximum (ch,
4188 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4189 XINT (XSCROLL_BAR (bar)
4190 ->height)) - 1);
4191 #endif
4192 bar = XSCROLL_BAR (bar)->next;
4197 void
4198 deactivate_scroll_bars (frame)
4199 FRAME_PTR frame;
4201 Lisp_Object bar;
4202 ControlHandle ch;
4204 bar = FRAME_SCROLL_BARS (frame);
4205 while (! NILP (bar))
4207 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4208 #ifdef TARGET_API_MAC_CARBON
4209 DeactivateControl (ch);
4210 #else
4211 SetControlMaximum (ch, XINT (-1));
4212 #endif
4213 bar = XSCROLL_BAR (bar)->next;
4217 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4218 is set to something other than NO_EVENT, it is enqueued.
4220 This may be called from a signal handler, so we have to ignore GC
4221 mark bits. */
4223 static void
4224 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4225 struct scroll_bar *bar;
4226 int part_code;
4227 EventRecord *er;
4228 struct input_event *bufp;
4230 if (! GC_WINDOWP (bar->window))
4231 abort ();
4233 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4234 bufp->frame_or_window = bar->window;
4235 bufp->arg = Qnil;
4237 bar->dragging = Qnil;
4239 switch (part_code)
4241 case kControlUpButtonPart:
4242 bufp->part = scroll_bar_up_arrow;
4243 break;
4244 case kControlDownButtonPart:
4245 bufp->part = scroll_bar_down_arrow;
4246 break;
4247 case kControlPageUpPart:
4248 bufp->part = scroll_bar_above_handle;
4249 break;
4250 case kControlPageDownPart:
4251 bufp->part = scroll_bar_below_handle;
4252 break;
4253 #ifdef TARGET_API_MAC_CARBON
4254 default:
4255 #else
4256 case kControlIndicatorPart:
4257 #endif
4258 if (er->what == mouseDown)
4259 bar->dragging = make_number (0);
4260 XSETVECTOR (last_mouse_scroll_bar, bar);
4261 bufp->part = scroll_bar_handle;
4262 break;
4267 /* Handle some mouse motion while someone is dragging the scroll bar.
4269 This may be called from a signal handler, so we have to ignore GC
4270 mark bits. */
4272 static void
4273 x_scroll_bar_note_movement (bar, y_pos, t)
4274 struct scroll_bar *bar;
4275 int y_pos;
4276 Time t;
4278 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4280 last_mouse_movement_time = t;
4282 f->mouse_moved = 1;
4283 XSETVECTOR (last_mouse_scroll_bar, bar);
4285 /* If we're dragging the bar, display it. */
4286 if (! GC_NILP (bar->dragging))
4288 /* Where should the handle be now? */
4289 int new_start = y_pos - 24;
4291 if (new_start != XINT (bar->start))
4293 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4295 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4301 /* Return information to the user about the current position of the
4302 mouse on the scroll bar. */
4304 static void
4305 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4306 FRAME_PTR *fp;
4307 Lisp_Object *bar_window;
4308 enum scroll_bar_part *part;
4309 Lisp_Object *x, *y;
4310 unsigned long *time;
4312 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4313 WindowPtr wp = FrontWindow ();
4314 Point mouse_pos;
4315 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
4316 int win_y, top_range;
4318 #if TARGET_API_MAC_CARBON
4319 SetPort (GetWindowPort (wp));
4320 #else
4321 SetPort (wp);
4322 #endif
4324 GetMouse (&mouse_pos);
4326 win_y = mouse_pos.v - XINT (bar->top);
4327 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4329 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4331 win_y -= 24;
4333 if (! NILP (bar->dragging))
4334 win_y -= XINT (bar->dragging);
4336 if (win_y < 0)
4337 win_y = 0;
4338 if (win_y > top_range)
4339 win_y = top_range;
4341 *fp = f;
4342 *bar_window = bar->window;
4344 if (! NILP (bar->dragging))
4345 *part = scroll_bar_handle;
4346 else if (win_y < XINT (bar->start))
4347 *part = scroll_bar_above_handle;
4348 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4349 *part = scroll_bar_handle;
4350 else
4351 *part = scroll_bar_below_handle;
4353 XSETINT (*x, win_y);
4354 XSETINT (*y, top_range);
4356 f->mouse_moved = 0;
4357 last_mouse_scroll_bar = Qnil;
4359 *time = last_mouse_movement_time;
4362 /***********************************************************************
4363 Text Cursor
4364 ***********************************************************************/
4366 /* Set clipping for output in glyph row ROW. W is the window in which
4367 we operate. GC is the graphics context to set clipping in.
4369 ROW may be a text row or, e.g., a mode line. Text rows must be
4370 clipped to the interior of the window dedicated to text display,
4371 mode lines must be clipped to the whole window. */
4373 static void
4374 x_clip_to_row (w, row, gc)
4375 struct window *w;
4376 struct glyph_row *row;
4377 GC gc;
4379 struct frame *f = XFRAME (WINDOW_FRAME (w));
4380 Rect clip_rect;
4381 int window_y, window_width;
4383 window_box (w, -1, 0, &window_y, &window_width, 0);
4385 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
4386 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4387 clip_rect.top = max (clip_rect.top, window_y);
4388 clip_rect.right = clip_rect.left + window_width;
4389 clip_rect.bottom = clip_rect.top + row->visible_height;
4391 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4395 /* Draw a hollow box cursor on window W in glyph row ROW. */
4397 static void
4398 x_draw_hollow_cursor (w, row)
4399 struct window *w;
4400 struct glyph_row *row;
4402 struct frame *f = XFRAME (WINDOW_FRAME (w));
4403 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4404 Display *dpy = FRAME_MAC_DISPLAY (f);
4405 int x, y, wd, h;
4406 XGCValues xgcv;
4407 struct glyph *cursor_glyph;
4408 GC gc;
4410 /* Compute frame-relative coordinates from window-relative
4411 coordinates. */
4412 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4413 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
4414 + row->ascent - w->phys_cursor_ascent);
4415 h = row->height - 1;
4417 /* Get the glyph the cursor is on. If we can't tell because
4418 the current matrix is invalid or such, give up. */
4419 cursor_glyph = get_phys_cursor_glyph (w);
4420 if (cursor_glyph == NULL)
4421 return;
4423 /* Compute the width of the rectangle to draw. If on a stretch
4424 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4425 rectangle as wide as the glyph, but use a canonical character
4426 width instead. */
4427 wd = cursor_glyph->pixel_width - 1;
4428 if (cursor_glyph->type == STRETCH_GLYPH
4429 && !x_stretch_cursor_p)
4430 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4432 /* The foreground of cursor_gc is typically the same as the normal
4433 background color, which can cause the cursor box to be invisible. */
4434 xgcv.foreground = f->output_data.mac->cursor_pixel;
4435 if (dpyinfo->scratch_cursor_gc)
4436 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4437 else
4438 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4439 GCForeground, &xgcv);
4440 gc = dpyinfo->scratch_cursor_gc;
4442 /* Set clipping, draw the rectangle, and reset clipping again. */
4443 x_clip_to_row (w, row, gc);
4444 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4445 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4449 /* Draw a bar cursor on window W in glyph row ROW.
4451 Implementation note: One would like to draw a bar cursor with an
4452 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4453 Unfortunately, I didn't find a font yet that has this property set.
4454 --gerd. */
4456 static void
4457 x_draw_bar_cursor (w, row, width)
4458 struct window *w;
4459 struct glyph_row *row;
4460 int width;
4462 /* If cursor hpos is out of bounds, don't draw garbage. This can
4463 happen in mini-buffer windows when switching between echo area
4464 glyphs and mini-buffer. */
4465 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
4467 struct frame *f = XFRAME (w->frame);
4468 struct glyph *cursor_glyph;
4469 GC gc;
4470 int x;
4471 unsigned long mask;
4472 XGCValues xgcv;
4473 Display *dpy;
4474 Window window;
4476 cursor_glyph = get_phys_cursor_glyph (w);
4477 if (cursor_glyph == NULL)
4478 return;
4480 xgcv.background = f->output_data.mac->cursor_pixel;
4481 xgcv.foreground = f->output_data.mac->cursor_pixel;
4482 mask = GCForeground | GCBackground;
4483 dpy = FRAME_MAC_DISPLAY (f);
4484 window = FRAME_MAC_WINDOW (f);
4485 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
4487 if (gc)
4488 XChangeGC (dpy, gc, mask, &xgcv);
4489 else
4491 gc = XCreateGC (dpy, window, mask, &xgcv);
4492 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4495 if (width < 0)
4496 width = FRAME_CURSOR_WIDTH (f);
4498 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4499 x_clip_to_row (w, row, gc);
4500 XFillRectangle (dpy, window, gc,
4502 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4503 min (cursor_glyph->pixel_width, width),
4504 row->height);
4505 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4510 /* RIF: Define cursor CURSOR on frame F. */
4512 static void
4513 mac_define_frame_cursor (f, cursor)
4514 struct frame *f;
4515 Cursor cursor;
4517 /* MAC TODO */
4521 /* RIF: Clear area on frame F. */
4523 static void
4524 mac_clear_frame_area (f, x, y, width, height)
4525 struct frame *f;
4526 int x, y, width, height;
4528 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4529 x, y, width, height, 0);
4533 /* RIF: Draw cursor on window W. */
4535 static void
4536 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4537 struct window *w;
4538 struct glyph_row *glyph_row;
4539 int x, y;
4540 int cursor_type, cursor_width;
4541 int on_p, active_p;
4543 if (on_p)
4545 w->phys_cursor_type = cursor_type;
4546 w->phys_cursor_width = cursor_width;
4547 w->phys_cursor_on_p = 1;
4549 switch (cursor_type)
4551 case HOLLOW_BOX_CURSOR:
4552 x_draw_hollow_cursor (w, glyph_row);
4553 break;
4555 case FILLED_BOX_CURSOR:
4556 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4557 break;
4559 case HBAR_CURSOR:
4560 /* TODO. For now, just draw bar cursor. */
4561 case BAR_CURSOR:
4562 x_draw_bar_cursor (w, glyph_row, cursor_width);
4563 break;
4565 case NO_CURSOR:
4566 break;
4568 default:
4569 abort ();
4575 /* Icons. */
4577 #if 0 /* MAC_TODO: no icon support yet. */
4579 x_bitmap_icon (f, icon)
4580 struct frame *f;
4581 Lisp_Object icon;
4583 HANDLE hicon;
4585 if (FRAME_W32_WINDOW (f) == 0)
4586 return 1;
4588 if (NILP (icon))
4589 hicon = LoadIcon (hinst, EMACS_CLASS);
4590 else if (STRINGP (icon))
4591 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4592 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4593 else if (SYMBOLP (icon))
4595 LPCTSTR name;
4597 if (EQ (icon, intern ("application")))
4598 name = (LPCTSTR) IDI_APPLICATION;
4599 else if (EQ (icon, intern ("hand")))
4600 name = (LPCTSTR) IDI_HAND;
4601 else if (EQ (icon, intern ("question")))
4602 name = (LPCTSTR) IDI_QUESTION;
4603 else if (EQ (icon, intern ("exclamation")))
4604 name = (LPCTSTR) IDI_EXCLAMATION;
4605 else if (EQ (icon, intern ("asterisk")))
4606 name = (LPCTSTR) IDI_ASTERISK;
4607 else if (EQ (icon, intern ("winlogo")))
4608 name = (LPCTSTR) IDI_WINLOGO;
4609 else
4610 return 1;
4612 hicon = LoadIcon (NULL, name);
4614 else
4615 return 1;
4617 if (hicon == NULL)
4618 return 1;
4620 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4621 (LPARAM) hicon);
4623 return 0;
4625 #endif /* MAC_TODO */
4627 /************************************************************************
4628 Handling X errors
4629 ************************************************************************/
4631 /* Display Error Handling functions not used on W32. Listing them here
4632 helps diff stay in step when comparing w32term.c with xterm.c.
4634 x_error_catcher (display, error)
4635 x_catch_errors (dpy)
4636 x_catch_errors_unwind (old_val)
4637 x_check_errors (dpy, format)
4638 x_had_errors_p (dpy)
4639 x_clear_errors (dpy)
4640 x_uncatch_errors (dpy, count)
4641 x_trace_wire ()
4642 x_connection_signal (signalnum)
4643 x_connection_closed (dpy, error_message)
4644 x_error_quitter (display, error)
4645 x_error_handler (display, error)
4646 x_io_error_quitter (display)
4651 /* Changing the font of the frame. */
4653 /* Give frame F the font named FONTNAME as its default font, and
4654 return the full name of that font. FONTNAME may be a wildcard
4655 pattern; in that case, we choose some font that fits the pattern.
4656 The return value shows which font we chose. */
4658 Lisp_Object
4659 x_new_font (f, fontname)
4660 struct frame *f;
4661 register char *fontname;
4663 struct font_info *fontp
4664 = FS_LOAD_FONT (f, 0, fontname, -1);
4666 if (!fontp)
4667 return Qnil;
4669 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4670 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4671 FRAME_FONTSET (f) = -1;
4673 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4674 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4676 compute_fringe_widths (f, 1);
4678 /* Compute the scroll bar width in character columns. */
4679 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4681 int wid = FRAME_COLUMN_WIDTH (f);
4682 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4683 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4685 else
4687 int wid = FRAME_COLUMN_WIDTH (f);
4688 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4691 /* Now make the frame display the given font. */
4692 if (FRAME_MAC_WINDOW (f) != 0)
4694 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4695 FRAME_FONT (f));
4696 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4697 FRAME_FONT (f));
4698 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4699 FRAME_FONT (f));
4701 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4702 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4705 return build_string (fontp->full_name);
4708 /* Give frame F the fontset named FONTSETNAME as its default font, and
4709 return the full name of that fontset. FONTSETNAME may be a wildcard
4710 pattern; in that case, we choose some fontset that fits the pattern.
4711 The return value shows which fontset we chose. */
4713 Lisp_Object
4714 x_new_fontset (f, fontsetname)
4715 struct frame *f;
4716 char *fontsetname;
4718 int fontset = fs_query_fontset (build_string (fontsetname), 0);
4719 Lisp_Object result;
4721 if (fontset < 0)
4722 return Qnil;
4724 if (FRAME_FONTSET (f) == fontset)
4725 /* This fontset is already set in frame F. There's nothing more
4726 to do. */
4727 return fontset_name (fontset);
4729 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
4731 if (!STRINGP (result))
4732 /* Can't load ASCII font. */
4733 return Qnil;
4735 /* Since x_new_font doesn't update any fontset information, do it now. */
4736 FRAME_FONTSET(f) = fontset;
4738 return build_string (fontsetname);
4742 /***********************************************************************
4743 TODO: W32 Input Methods
4744 ***********************************************************************/
4745 /* Listing missing functions from xterm.c helps diff stay in step.
4747 xim_destroy_callback (xim, client_data, call_data)
4748 xim_open_dpy (dpyinfo, resource_name)
4749 struct xim_inst_t
4750 xim_instantiate_callback (display, client_data, call_data)
4751 xim_initialize (dpyinfo, resource_name)
4752 xim_close_dpy (dpyinfo)
4757 /* Calculate the absolute position in frame F
4758 from its current recorded position values and gravity. */
4760 void
4761 x_calc_absolute_position (f)
4762 struct frame *f;
4764 Point pt;
4765 int flags = f->size_hint_flags;
4767 pt.h = pt.v = 0;
4769 /* Find the position of the outside upper-left corner of
4770 the inner window, with respect to the outer window. */
4771 if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
4773 GrafPtr savePort;
4774 GetPort (&savePort);
4776 #if TARGET_API_MAC_CARBON
4777 SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
4778 #else
4779 SetPort (FRAME_MAC_WINDOW (f));
4780 #endif
4782 #if TARGET_API_MAC_CARBON
4784 Rect r;
4786 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
4787 SetPt(&pt, r.left, r.top);
4789 #else /* not TARGET_API_MAC_CARBON */
4790 SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
4791 #endif /* not TARGET_API_MAC_CARBON */
4792 LocalToGlobal (&pt);
4793 SetPort (savePort);
4796 /* Treat negative positions as relative to the leftmost bottommost
4797 position that fits on the screen. */
4798 if (flags & XNegative)
4799 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
4800 - 2 * f->border_width - pt.h
4801 - FRAME_PIXEL_WIDTH (f)
4802 + f->left_pos);
4803 /* NTEMACS_TODO: Subtract menubar height? */
4804 if (flags & YNegative)
4805 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
4806 - 2 * f->border_width - pt.v
4807 - FRAME_PIXEL_HEIGHT (f)
4808 + f->top_pos);
4809 /* The left_pos and top_pos
4810 are now relative to the top and left screen edges,
4811 so the flags should correspond. */
4812 f->size_hint_flags &= ~ (XNegative | YNegative);
4815 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
4816 to really change the position, and 0 when calling from
4817 x_make_frame_visible (in that case, XOFF and YOFF are the current
4818 position values). It is -1 when calling from x_set_frame_parameters,
4819 which means, do adjust for borders but don't change the gravity. */
4821 void
4822 x_set_offset (f, xoff, yoff, change_gravity)
4823 struct frame *f;
4824 register int xoff, yoff;
4825 int change_gravity;
4827 int modified_top, modified_left;
4829 if (change_gravity > 0)
4831 f->top_pos = yoff;
4832 f->left_pos = xoff;
4833 f->size_hint_flags &= ~ (XNegative | YNegative);
4834 if (xoff < 0)
4835 f->size_hint_flags |= XNegative;
4836 if (yoff < 0)
4837 f->size_hint_flags |= YNegative;
4838 f->win_gravity = NorthWestGravity;
4840 x_calc_absolute_position (f);
4842 BLOCK_INPUT;
4843 x_wm_set_size_hint (f, (long) 0, 0);
4845 modified_left = f->left_pos;
4846 modified_top = f->top_pos;
4848 MoveWindow (f->output_data.mac->mWP, modified_left + 6,
4849 modified_top + 42, false);
4851 UNBLOCK_INPUT;
4854 /* Call this to change the size of frame F's x-window.
4855 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
4856 for this size change and subsequent size changes.
4857 Otherwise we leave the window gravity unchanged. */
4859 void
4860 x_set_window_size (f, change_gravity, cols, rows)
4861 struct frame *f;
4862 int change_gravity;
4863 int cols, rows;
4865 int pixelwidth, pixelheight;
4867 BLOCK_INPUT;
4869 check_frame_size (f, &rows, &cols);
4870 f->scroll_bar_actual_width
4871 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
4873 compute_fringe_widths (f, 0);
4875 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
4876 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
4878 f->win_gravity = NorthWestGravity;
4879 x_wm_set_size_hint (f, (long) 0, 0);
4881 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
4883 /* Now, strictly speaking, we can't be sure that this is accurate,
4884 but the window manager will get around to dealing with the size
4885 change request eventually, and we'll hear how it went when the
4886 ConfigureNotify event gets here.
4888 We could just not bother storing any of this information here,
4889 and let the ConfigureNotify event set everything up, but that
4890 might be kind of confusing to the Lisp code, since size changes
4891 wouldn't be reported in the frame parameters until some random
4892 point in the future when the ConfigureNotify event arrives.
4894 We pass 1 for DELAY since we can't run Lisp code inside of
4895 a BLOCK_INPUT. */
4896 change_frame_size (f, rows, cols, 0, 1, 0);
4897 FRAME_PIXEL_WIDTH (f) = pixelwidth;
4898 FRAME_PIXEL_HEIGHT (f) = pixelheight;
4900 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4901 receive in the ConfigureNotify event; if we get what we asked
4902 for, then the event won't cause the screen to become garbaged, so
4903 we have to make sure to do it here. */
4904 SET_FRAME_GARBAGED (f);
4906 XFlush (FRAME_X_DISPLAY (f));
4908 /* If cursor was outside the new size, mark it as off. */
4909 mark_window_cursors_off (XWINDOW (f->root_window));
4911 /* Clear out any recollection of where the mouse highlighting was,
4912 since it might be in a place that's outside the new frame size.
4913 Actually checking whether it is outside is a pain in the neck,
4914 so don't try--just let the highlighting be done afresh with new size. */
4915 cancel_mouse_face (f);
4917 UNBLOCK_INPUT;
4920 /* Mouse warping. */
4922 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
4924 void
4925 x_set_mouse_position (f, x, y)
4926 struct frame *f;
4927 int x, y;
4929 int pix_x, pix_y;
4931 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
4932 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
4934 if (pix_x < 0) pix_x = 0;
4935 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
4937 if (pix_y < 0) pix_y = 0;
4938 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
4940 x_set_mouse_pixel_position (f, pix_x, pix_y);
4943 void
4944 x_set_mouse_pixel_position (f, pix_x, pix_y)
4945 struct frame *f;
4946 int pix_x, pix_y;
4948 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
4949 BLOCK_INPUT;
4951 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
4952 0, 0, 0, 0, pix_x, pix_y);
4953 UNBLOCK_INPUT;
4954 #endif
4958 /* focus shifting, raising and lowering. */
4960 void
4961 x_focus_on_frame (f)
4962 struct frame *f;
4964 #if 0 /* This proves to be unpleasant. */
4965 x_raise_frame (f);
4966 #endif
4967 #if 0
4968 /* I don't think that the ICCCM allows programs to do things like this
4969 without the interaction of the window manager. Whatever you end up
4970 doing with this code, do it to x_unfocus_frame too. */
4971 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4972 RevertToPointerRoot, CurrentTime);
4973 #endif /* ! 0 */
4976 void
4977 x_unfocus_frame (f)
4978 struct frame *f;
4982 /* Raise frame F. */
4983 void
4984 x_raise_frame (f)
4985 struct frame *f;
4987 if (f->async_visible)
4988 SelectWindow (FRAME_MAC_WINDOW (f));
4991 /* Lower frame F. */
4992 void
4993 x_lower_frame (f)
4994 struct frame *f;
4996 if (f->async_visible)
4997 SendBehind (FRAME_MAC_WINDOW (f), nil);
5000 static void
5001 XTframe_raise_lower (f, raise_flag)
5002 FRAME_PTR f;
5003 int raise_flag;
5005 if (raise_flag)
5006 x_raise_frame (f);
5007 else
5008 x_lower_frame (f);
5011 /* Change of visibility. */
5013 /* This tries to wait until the frame is really visible.
5014 However, if the window manager asks the user where to position
5015 the frame, this will return before the user finishes doing that.
5016 The frame will not actually be visible at that time,
5017 but it will become visible later when the window manager
5018 finishes with it. */
5020 void
5021 x_make_frame_visible (f)
5022 struct frame *f;
5024 Lisp_Object type;
5025 int original_top, original_left;
5027 BLOCK_INPUT;
5029 if (! FRAME_VISIBLE_P (f))
5031 /* We test FRAME_GARBAGED_P here to make sure we don't
5032 call x_set_offset a second time
5033 if we get to x_make_frame_visible a second time
5034 before the window gets really visible. */
5035 if (! FRAME_ICONIFIED_P (f)
5036 && ! f->output_data.mac->asked_for_visible)
5037 x_set_offset (f, f->left_pos, f->top_pos, 0);
5039 f->output_data.mac->asked_for_visible = 1;
5041 ShowWindow (FRAME_MAC_WINDOW (f));
5044 XFlush (FRAME_MAC_DISPLAY (f));
5046 #if 0 /* MAC_TODO */
5047 /* Synchronize to ensure Emacs knows the frame is visible
5048 before we do anything else. We do this loop with input not blocked
5049 so that incoming events are handled. */
5051 Lisp_Object frame;
5052 int count;
5054 /* This must come after we set COUNT. */
5055 UNBLOCK_INPUT;
5057 XSETFRAME (frame, f);
5059 /* Wait until the frame is visible. Process X events until a
5060 MapNotify event has been seen, or until we think we won't get a
5061 MapNotify at all.. */
5062 for (count = input_signal_count + 10;
5063 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5065 /* Force processing of queued events. */
5066 x_sync (f);
5068 /* Machines that do polling rather than SIGIO have been
5069 observed to go into a busy-wait here. So we'll fake an
5070 alarm signal to let the handler know that there's something
5071 to be read. We used to raise a real alarm, but it seems
5072 that the handler isn't always enabled here. This is
5073 probably a bug. */
5074 if (input_polling_used ())
5076 /* It could be confusing if a real alarm arrives while
5077 processing the fake one. Turn it off and let the
5078 handler reset it. */
5079 extern void poll_for_input_1 P_ ((void));
5080 int old_poll_suppress_count = poll_suppress_count;
5081 poll_suppress_count = 1;
5082 poll_for_input_1 ();
5083 poll_suppress_count = old_poll_suppress_count;
5086 /* See if a MapNotify event has been processed. */
5087 FRAME_SAMPLE_VISIBILITY (f);
5090 #endif /* MAC_TODO */
5093 /* Change from mapped state to withdrawn state. */
5095 /* Make the frame visible (mapped and not iconified). */
5097 void
5098 x_make_frame_invisible (f)
5099 struct frame *f;
5101 /* Don't keep the highlight on an invisible frame. */
5102 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5103 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5105 BLOCK_INPUT;
5107 HideWindow (FRAME_MAC_WINDOW (f));
5109 /* We can't distinguish this from iconification
5110 just by the event that we get from the server.
5111 So we can't win using the usual strategy of letting
5112 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5113 and synchronize with the server to make sure we agree. */
5114 f->visible = 0;
5115 FRAME_ICONIFIED_P (f) = 0;
5116 f->async_visible = 0;
5117 f->async_iconified = 0;
5119 UNBLOCK_INPUT;
5122 /* Change window state from mapped to iconified. */
5124 void
5125 x_iconify_frame (f)
5126 struct frame *f;
5128 /* Don't keep the highlight on an invisible frame. */
5129 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5130 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5132 #if 0
5133 /* Review: Since window is still visible in dock, still allow updates? */
5134 if (f->async_iconified)
5135 return;
5136 #endif
5138 BLOCK_INPUT;
5140 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5142 UNBLOCK_INPUT;
5146 /* Destroy the X window of frame F. */
5148 void
5149 x_destroy_window (f)
5150 struct frame *f;
5152 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5154 BLOCK_INPUT;
5156 DisposeWindow (FRAME_MAC_WINDOW (f));
5158 free_frame_menubar (f);
5159 free_frame_faces (f);
5161 xfree (f->output_data.mac);
5162 f->output_data.mac = 0;
5163 if (f == dpyinfo->x_focus_frame)
5164 dpyinfo->x_focus_frame = 0;
5165 if (f == dpyinfo->x_focus_event_frame)
5166 dpyinfo->x_focus_event_frame = 0;
5167 if (f == dpyinfo->x_highlight_frame)
5168 dpyinfo->x_highlight_frame = 0;
5170 dpyinfo->reference_count--;
5172 if (f == dpyinfo->mouse_face_mouse_frame)
5174 dpyinfo->mouse_face_beg_row
5175 = dpyinfo->mouse_face_beg_col = -1;
5176 dpyinfo->mouse_face_end_row
5177 = dpyinfo->mouse_face_end_col = -1;
5178 dpyinfo->mouse_face_window = Qnil;
5179 dpyinfo->mouse_face_deferred_gc = 0;
5180 dpyinfo->mouse_face_mouse_frame = 0;
5183 UNBLOCK_INPUT;
5186 /* Setting window manager hints. */
5188 /* Set the normal size hints for the window manager, for frame F.
5189 FLAGS is the flags word to use--or 0 meaning preserve the flags
5190 that the window now has.
5191 If USER_POSITION is nonzero, we set the USPosition
5192 flag (this is useful when FLAGS is 0). */
5193 void
5194 x_wm_set_size_hint (f, flags, user_position)
5195 struct frame *f;
5196 long flags;
5197 int user_position;
5199 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5200 XSizeHints size_hints;
5202 #ifdef USE_X_TOOLKIT
5203 Arg al[2];
5204 int ac = 0;
5205 Dimension widget_width, widget_height;
5206 Window window = XtWindow (f->output_data.x->widget);
5207 #else /* not USE_X_TOOLKIT */
5208 Window window = FRAME_X_WINDOW (f);
5209 #endif /* not USE_X_TOOLKIT */
5211 /* Setting PMaxSize caused various problems. */
5212 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5214 size_hints.x = f->left_pos;
5215 size_hints.y = f->top_pos;
5217 #ifdef USE_X_TOOLKIT
5218 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5219 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5220 XtGetValues (f->output_data.x->widget, al, ac);
5221 size_hints.height = widget_height;
5222 size_hints.width = widget_width;
5223 #else /* not USE_X_TOOLKIT */
5224 size_hints.height = FRAME_PIXEL_HEIGHT (f);
5225 size_hints.width = FRAME_PIXEL_WIDTH (f);
5226 #endif /* not USE_X_TOOLKIT */
5228 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
5229 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
5230 size_hints.max_width
5231 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5232 size_hints.max_height
5233 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5235 /* Calculate the base and minimum sizes.
5237 (When we use the X toolkit, we don't do it here.
5238 Instead we copy the values that the widgets are using, below.) */
5239 #ifndef USE_X_TOOLKIT
5241 int base_width, base_height;
5242 int min_rows = 0, min_cols = 0;
5244 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5245 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5247 check_frame_size (f, &min_rows, &min_cols);
5249 /* The window manager uses the base width hints to calculate the
5250 current number of rows and columns in the frame while
5251 resizing; min_width and min_height aren't useful for this
5252 purpose, since they might not give the dimensions for a
5253 zero-row, zero-column frame.
5255 We use the base_width and base_height members if we have
5256 them; otherwise, we set the min_width and min_height members
5257 to the size for a zero x zero frame. */
5259 #ifdef HAVE_X11R4
5260 size_hints.flags |= PBaseSize;
5261 size_hints.base_width = base_width;
5262 size_hints.base_height = base_height;
5263 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5264 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5265 #else
5266 size_hints.min_width = base_width;
5267 size_hints.min_height = base_height;
5268 #endif
5271 /* If we don't need the old flags, we don't need the old hint at all. */
5272 if (flags)
5274 size_hints.flags |= flags;
5275 goto no_read;
5277 #endif /* not USE_X_TOOLKIT */
5280 XSizeHints hints; /* Sometimes I hate X Windows... */
5281 long supplied_return;
5282 int value;
5284 #ifdef HAVE_X11R4
5285 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5286 &supplied_return);
5287 #else
5288 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5289 #endif
5291 #ifdef USE_X_TOOLKIT
5292 size_hints.base_height = hints.base_height;
5293 size_hints.base_width = hints.base_width;
5294 size_hints.min_height = hints.min_height;
5295 size_hints.min_width = hints.min_width;
5296 #endif
5298 if (flags)
5299 size_hints.flags |= flags;
5300 else
5302 if (value == 0)
5303 hints.flags = 0;
5304 if (hints.flags & PSize)
5305 size_hints.flags |= PSize;
5306 if (hints.flags & PPosition)
5307 size_hints.flags |= PPosition;
5308 if (hints.flags & USPosition)
5309 size_hints.flags |= USPosition;
5310 if (hints.flags & USSize)
5311 size_hints.flags |= USSize;
5315 #ifndef USE_X_TOOLKIT
5316 no_read:
5317 #endif
5319 #ifdef PWinGravity
5320 size_hints.win_gravity = f->win_gravity;
5321 size_hints.flags |= PWinGravity;
5323 if (user_position)
5325 size_hints.flags &= ~ PPosition;
5326 size_hints.flags |= USPosition;
5328 #endif /* PWinGravity */
5330 #ifdef HAVE_X11R4
5331 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5332 #else
5333 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5334 #endif
5335 #endif /* MAC_TODO */
5338 #if 0 /* MAC_TODO: hide application instead of iconify? */
5339 /* Used for IconicState or NormalState */
5341 void
5342 x_wm_set_window_state (f, state)
5343 struct frame *f;
5344 int state;
5346 #ifdef USE_X_TOOLKIT
5347 Arg al[1];
5349 XtSetArg (al[0], XtNinitialState, state);
5350 XtSetValues (f->output_data.x->widget, al, 1);
5351 #else /* not USE_X_TOOLKIT */
5352 Window window = FRAME_X_WINDOW (f);
5354 f->output_data.x->wm_hints.flags |= StateHint;
5355 f->output_data.x->wm_hints.initial_state = state;
5357 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5358 #endif /* not USE_X_TOOLKIT */
5361 void
5362 x_wm_set_icon_pixmap (f, pixmap_id)
5363 struct frame *f;
5364 int pixmap_id;
5366 Pixmap icon_pixmap;
5368 #ifndef USE_X_TOOLKIT
5369 Window window = FRAME_X_WINDOW (f);
5370 #endif
5372 if (pixmap_id > 0)
5374 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5375 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5377 else
5379 /* It seems there is no way to turn off use of an icon pixmap.
5380 The following line does it, only if no icon has yet been created,
5381 for some window managers. But with mwm it crashes.
5382 Some people say it should clear the IconPixmapHint bit in this case,
5383 but that doesn't work, and the X consortium said it isn't the
5384 right thing at all. Since there is no way to win,
5385 best to explicitly give up. */
5386 #if 0
5387 f->output_data.x->wm_hints.icon_pixmap = None;
5388 #else
5389 return;
5390 #endif
5393 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5396 Arg al[1];
5397 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5398 XtSetValues (f->output_data.x->widget, al, 1);
5401 #else /* not USE_X_TOOLKIT */
5403 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5404 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5406 #endif /* not USE_X_TOOLKIT */
5409 #endif /* MAC_TODO */
5411 void
5412 x_wm_set_icon_position (f, icon_x, icon_y)
5413 struct frame *f;
5414 int icon_x, icon_y;
5416 #if 0 /* MAC_TODO: no icons on Mac */
5417 #ifdef USE_X_TOOLKIT
5418 Window window = XtWindow (f->output_data.x->widget);
5419 #else
5420 Window window = FRAME_X_WINDOW (f);
5421 #endif
5423 f->output_data.x->wm_hints.flags |= IconPositionHint;
5424 f->output_data.x->wm_hints.icon_x = icon_x;
5425 f->output_data.x->wm_hints.icon_y = icon_y;
5427 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5428 #endif /* MAC_TODO */
5432 /***********************************************************************
5433 Fonts
5434 ***********************************************************************/
5436 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5438 struct font_info *
5439 x_get_font_info (f, font_idx)
5440 FRAME_PTR f;
5441 int font_idx;
5443 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5446 /* the global font name table */
5447 char **font_name_table = NULL;
5448 int font_name_table_size = 0;
5449 int font_name_count = 0;
5451 /* compare two strings ignoring case */
5452 static int
5453 stricmp (const char *s, const char *t)
5455 for ( ; tolower (*s) == tolower (*t); s++, t++)
5456 if (*s == '\0')
5457 return 0;
5458 return tolower (*s) - tolower (*t);
5461 /* compare two strings ignoring case and handling wildcard */
5462 static int
5463 wildstrieq (char *s1, char *s2)
5465 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5466 return true;
5468 return stricmp (s1, s2) == 0;
5471 /* Assume parameter 1 is fully qualified, no wildcards. */
5472 static int
5473 mac_font_pattern_match (fontname, pattern)
5474 char * fontname;
5475 char * pattern;
5477 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5478 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5479 char *ptr;
5481 /* Copy fontname so we can modify it during comparison. */
5482 strcpy (font_name_copy, fontname);
5484 ptr = regex;
5485 *ptr++ = '^';
5487 /* Turn pattern into a regexp and do a regexp match. */
5488 for (; *pattern; pattern++)
5490 if (*pattern == '?')
5491 *ptr++ = '.';
5492 else if (*pattern == '*')
5494 *ptr++ = '.';
5495 *ptr++ = '*';
5497 else
5498 *ptr++ = *pattern;
5500 *ptr = '$';
5501 *(ptr + 1) = '\0';
5503 return (fast_c_string_match_ignore_case (build_string (regex),
5504 font_name_copy) >= 0);
5507 /* Two font specs are considered to match if their foundry, family,
5508 weight, slant, and charset match. */
5509 static int
5510 mac_font_match (char *mf, char *xf)
5512 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5513 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5515 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5516 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5517 return mac_font_pattern_match (mf, xf);
5519 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5520 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5521 return mac_font_pattern_match (mf, xf);
5523 return (wildstrieq (m_foundry, x_foundry)
5524 && wildstrieq (m_family, x_family)
5525 && wildstrieq (m_weight, x_weight)
5526 && wildstrieq (m_slant, x_slant)
5527 && wildstrieq (m_charset, x_charset))
5528 || mac_font_pattern_match (mf, xf);
5532 static char *
5533 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
5535 char foundry[32], family[32], cs[32];
5536 char xf[255], *result, *p;
5538 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5540 strcpy(foundry, "Apple");
5541 strcpy(family, name);
5543 switch (scriptcode)
5545 case smTradChinese:
5546 strcpy(cs, "big5-0");
5547 break;
5548 case smSimpChinese:
5549 strcpy(cs, "gb2312.1980-0");
5550 break;
5551 case smJapanese:
5552 strcpy(cs, "jisx0208.1983-sjis");
5553 break;
5554 case -smJapanese:
5555 /* Each Apple Japanese font is entered into the font table
5556 twice: once as a jisx0208.1983-sjis font and once as a
5557 jisx0201.1976-0 font. The latter can be used to display
5558 the ascii charset and katakana-jisx0201 charset. A
5559 negative script code signals that the name of this latter
5560 font is being built. */
5561 strcpy(cs, "jisx0201.1976-0");
5562 break;
5563 case smKorean:
5564 strcpy(cs, "ksc5601.1989-0");
5565 break;
5566 default:
5567 strcpy(cs, "mac-roman");
5568 break;
5572 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5573 foundry, family, style & bold ? "bold" : "medium",
5574 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5576 result = (char *) xmalloc (strlen (xf) + 1);
5577 strcpy (result, xf);
5578 for (p = result; *p; p++)
5579 *p = tolower(*p);
5580 return result;
5584 /* Convert an X font spec to the corresponding mac font name, which
5585 can then be passed to GetFNum after conversion to a Pascal string.
5586 For ordinary Mac fonts, this should just be their names, like
5587 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5588 collection contain their charset designation in their names, like
5589 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5590 names are handled accordingly. */
5591 static void
5592 x_font_name_to_mac_font_name (char *xf, char *mf)
5594 char foundry[32], family[32], weight[20], slant[2], cs[32];
5596 strcpy (mf, "");
5598 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5599 foundry, family, weight, slant, cs) != 5 &&
5600 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5601 foundry, family, weight, slant, cs) != 5)
5602 return;
5604 if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
5605 || strcmp (cs, "jisx0208.1983-sjis") == 0
5606 || strcmp (cs, "jisx0201.1976-0") == 0
5607 || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
5608 strcpy(mf, family);
5609 else
5610 sprintf(mf, "%s-%s-%s", foundry, family, cs);
5614 static void
5615 add_font_name_table_entry (char *font_name)
5617 if (font_name_table_size == 0)
5619 font_name_table_size = 16;
5620 font_name_table = (char **)
5621 xmalloc (font_name_table_size * sizeof (char *));
5623 else if (font_name_count + 1 >= font_name_table_size)
5625 font_name_table_size += 16;
5626 font_name_table = (char **)
5627 xrealloc (font_name_table,
5628 font_name_table_size * sizeof (char *));
5631 font_name_table[font_name_count++] = font_name;
5634 /* Sets up the table font_name_table to contain the list of all fonts
5635 in the system the first time the table is used so that the Resource
5636 Manager need not be accessed every time this information is
5637 needed. */
5639 static void
5640 init_font_name_table ()
5642 #if TARGET_API_MAC_CARBON
5643 SInt32 sv;
5645 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
5647 FMFontFamilyIterator ffi;
5648 FMFontFamilyInstanceIterator ffii;
5649 FMFontFamily ff;
5651 /* Create a dummy instance iterator here to avoid creating and
5652 destroying it in the loop. */
5653 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
5654 return;
5655 /* Create an iterator to enumerate the font families. */
5656 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
5657 != noErr)
5659 FMDisposeFontFamilyInstanceIterator (&ffii);
5660 return;
5663 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
5665 Str255 name;
5666 FMFont font;
5667 FMFontStyle style;
5668 FMFontSize size;
5669 SInt16 sc;
5671 if (FMGetFontFamilyName (ff, name) != noErr)
5672 break;
5673 p2cstr (name);
5675 sc = FontToScript (ff);
5677 /* Point the instance iterator at the current font family. */
5678 if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
5679 break;
5681 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
5682 == noErr)
5683 if (size == 0)
5685 add_font_name_table_entry (mac_to_x_fontname (name, size,
5686 style, sc));
5687 add_font_name_table_entry (mac_to_x_fontname (name, size,
5688 italic, sc));
5689 add_font_name_table_entry (mac_to_x_fontname (name, size,
5690 bold, sc));
5691 add_font_name_table_entry (mac_to_x_fontname (name, size,
5692 italic | bold,
5693 sc));
5695 else
5697 add_font_name_table_entry (mac_to_x_fontname (name, size,
5698 style, sc));
5699 if (smJapanese == sc)
5700 add_font_name_table_entry (mac_to_x_fontname (name, size,
5701 style,
5702 -smJapanese));
5706 /* Dispose of the iterators. */
5707 FMDisposeFontFamilyIterator (&ffi);
5708 FMDisposeFontFamilyInstanceIterator (&ffii);
5710 else
5712 #endif /* TARGET_API_MAC_CARBON */
5713 GrafPtr port;
5714 SInt16 fontnum, old_fontnum;
5715 int num_mac_fonts = CountResources('FOND');
5716 int i, j;
5717 Handle font_handle, font_handle_2;
5718 short id, scriptcode;
5719 ResType type;
5720 Str32 name;
5721 struct FontAssoc *fat;
5722 struct AsscEntry *assc_entry;
5724 GetPort (&port); /* save the current font number used */
5725 #if TARGET_API_MAC_CARBON
5726 old_fontnum = GetPortTextFont (port);
5727 #else
5728 old_fontnum = port->txFont;
5729 #endif
5731 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
5733 font_handle = GetIndResource ('FOND', i);
5734 if (!font_handle)
5735 continue;
5737 GetResInfo (font_handle, &id, &type, name);
5738 GetFNum (name, &fontnum);
5739 p2cstr (name);
5740 if (fontnum == 0)
5741 continue;
5743 TextFont (fontnum);
5744 scriptcode = FontToScript (fontnum);
5747 HLock (font_handle);
5749 if (GetResourceSizeOnDisk (font_handle)
5750 >= sizeof (struct FamRec))
5752 fat = (struct FontAssoc *) (*font_handle
5753 + sizeof (struct FamRec));
5754 assc_entry
5755 = (struct AsscEntry *) (*font_handle
5756 + sizeof (struct FamRec)
5757 + sizeof (struct FontAssoc));
5759 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
5761 if (font_name_table_size == 0)
5763 font_name_table_size = 16;
5764 font_name_table = (char **)
5765 xmalloc (font_name_table_size * sizeof (char *));
5767 else if (font_name_count >= font_name_table_size)
5769 font_name_table_size += 16;
5770 font_name_table = (char **)
5771 xrealloc (font_name_table,
5772 font_name_table_size * sizeof (char *));
5774 font_name_table[font_name_count++]
5775 = mac_to_x_fontname (name,
5776 assc_entry->fontSize,
5777 assc_entry->fontStyle,
5778 scriptcode);
5779 /* Both jisx0208.1983-sjis and
5780 jisx0201.1976-sjis parts are contained in
5781 Apple Japanese (SJIS) font. */
5782 if (smJapanese == scriptcode)
5784 font_name_table[font_name_count++]
5785 = mac_to_x_fontname (name,
5786 assc_entry->fontSize,
5787 assc_entry->fontStyle,
5788 -smJapanese);
5793 HUnlock (font_handle);
5794 font_handle_2 = GetNextFOND (font_handle);
5795 ReleaseResource (font_handle);
5796 font_handle = font_handle_2;
5798 while (ResError () == noErr && font_handle);
5801 TextFont (old_fontnum);
5802 #if TARGET_API_MAC_CARBON
5804 #endif /* TARGET_API_MAC_CARBON */
5808 /* Return a list of at most MAXNAMES font specs matching the one in
5809 PATTERN. Cache matching fonts for patterns in
5810 dpyinfo->name_list_element to avoid looking them up again by
5811 calling mac_font_pattern_match (slow). Return as many matching
5812 fonts as possible if MAXNAMES = -1. */
5814 Lisp_Object
5815 x_list_fonts (struct frame *f,
5816 Lisp_Object pattern,
5817 int size,
5818 int maxnames)
5820 char *ptnstr;
5821 Lisp_Object newlist = Qnil, tem, key;
5822 int n_fonts = 0;
5823 int i;
5824 struct gcpro gcpro1, gcpro2;
5825 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
5827 if (font_name_table == NULL) /* Initialize when first used. */
5828 init_font_name_table ();
5830 if (dpyinfo)
5832 tem = XCDR (dpyinfo->name_list_element);
5833 key = Fcons (pattern, make_number (maxnames));
5835 newlist = Fassoc (key, tem);
5836 if (!NILP (newlist))
5838 newlist = Fcdr_safe (newlist);
5839 goto label_cached;
5843 ptnstr = SDATA (pattern);
5845 GCPRO2 (pattern, newlist);
5847 /* Scan and matching bitmap fonts. */
5848 for (i = 0; i < font_name_count; i++)
5850 if (mac_font_pattern_match (font_name_table[i], ptnstr))
5852 newlist = Fcons (build_string (font_name_table[i]), newlist);
5854 n_fonts++;
5855 if (maxnames > 0 && n_fonts >= maxnames)
5856 break;
5860 /* MAC_TODO: add code for matching outline fonts here */
5862 UNGCPRO;
5864 if (dpyinfo)
5866 XSETCDR (dpyinfo->name_list_element,
5867 Fcons (Fcons (key, newlist),
5868 XCDR (dpyinfo->name_list_element)));
5870 label_cached:
5872 return newlist;
5876 #if GLYPH_DEBUG
5878 /* Check that FONT is valid on frame F. It is if it can be found in F's
5879 font table. */
5881 static void
5882 x_check_font (f, font)
5883 struct frame *f;
5884 XFontStruct *font;
5886 int i;
5887 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5889 xassert (font != NULL);
5891 for (i = 0; i < dpyinfo->n_fonts; i++)
5892 if (dpyinfo->font_table[i].name
5893 && font == dpyinfo->font_table[i].font)
5894 break;
5896 xassert (i < dpyinfo->n_fonts);
5899 #endif /* GLYPH_DEBUG != 0 */
5901 /* Set *W to the minimum width, *H to the minimum font height of FONT.
5902 Note: There are (broken) X fonts out there with invalid XFontStruct
5903 min_bounds contents. For example, handa@etl.go.jp reports that
5904 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
5905 have font->min_bounds.width == 0. */
5907 static INLINE void
5908 x_font_min_bounds (font, w, h)
5909 MacFontStruct *font;
5910 int *w, *h;
5913 * TODO: Windows does not appear to offer min bound, only
5914 * average and maximum width, and maximum height.
5916 *h = FONT_HEIGHT (font);
5917 *w = FONT_WIDTH (font);
5921 /* Compute the smallest character width and smallest font height over
5922 all fonts available on frame F. Set the members smallest_char_width
5923 and smallest_font_height in F's x_display_info structure to
5924 the values computed. Value is non-zero if smallest_font_height or
5925 smallest_char_width become smaller than they were before. */
5928 x_compute_min_glyph_bounds (f)
5929 struct frame *f;
5931 int i;
5932 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5933 MacFontStruct *font;
5934 int old_width = dpyinfo->smallest_char_width;
5935 int old_height = dpyinfo->smallest_font_height;
5937 dpyinfo->smallest_font_height = 100000;
5938 dpyinfo->smallest_char_width = 100000;
5940 for (i = 0; i < dpyinfo->n_fonts; ++i)
5941 if (dpyinfo->font_table[i].name)
5943 struct font_info *fontp = dpyinfo->font_table + i;
5944 int w, h;
5946 font = (MacFontStruct *) fontp->font;
5947 xassert (font != (MacFontStruct *) ~0);
5948 x_font_min_bounds (font, &w, &h);
5950 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
5951 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
5954 xassert (dpyinfo->smallest_char_width > 0
5955 && dpyinfo->smallest_font_height > 0);
5957 return (dpyinfo->n_fonts == 1
5958 || dpyinfo->smallest_char_width < old_width
5959 || dpyinfo->smallest_font_height < old_height);
5963 /* Determine whether given string is a fully-specified XLFD: all 14
5964 fields are present, none is '*'. */
5966 static int
5967 is_fully_specified_xlfd (char *p)
5969 int i;
5970 char *q;
5972 if (*p != '-')
5973 return 0;
5975 for (i = 0; i < 13; i++)
5977 q = strchr (p + 1, '-');
5978 if (q == NULL)
5979 return 0;
5980 if (q - p == 2 && *(p + 1) == '*')
5981 return 0;
5982 p = q;
5985 if (strchr (p + 1, '-') != NULL)
5986 return 0;
5988 if (*(p + 1) == '*' && *(p + 2) == '\0')
5989 return 0;
5991 return 1;
5995 const int kDefaultFontSize = 9;
5998 /* XLoadQueryFont creates and returns an internal representation for a
5999 font in a MacFontStruct struct. There is really no concept
6000 corresponding to "loading" a font on the Mac. But we check its
6001 existence and find the font number and all other information for it
6002 and store them in the returned MacFontStruct. */
6004 static MacFontStruct *
6005 XLoadQueryFont (Display *dpy, char *fontname)
6007 int i, size, is_two_byte_font, char_width;
6008 char *name;
6009 GrafPtr port;
6010 SInt16 old_fontnum, old_fontsize;
6011 Style old_fontface;
6012 Str32 mfontname;
6013 SInt16 fontnum;
6014 Style fontface = normal;
6015 MacFontStruct *font;
6016 FontInfo the_fontinfo;
6017 char s_weight[7], c_slant;
6019 if (is_fully_specified_xlfd (fontname))
6020 name = fontname;
6021 else
6023 for (i = 0; i < font_name_count; i++)
6024 if (mac_font_pattern_match (font_name_table[i], fontname))
6025 break;
6027 if (i >= font_name_count)
6028 return NULL;
6030 name = font_name_table[i];
6033 GetPort (&port); /* save the current font number used */
6034 #if TARGET_API_MAC_CARBON
6035 old_fontnum = GetPortTextFont (port);
6036 old_fontsize = GetPortTextSize (port);
6037 old_fontface = GetPortTextFace (port);
6038 #else
6039 old_fontnum = port->txFont;
6040 old_fontsize = port->txSize;
6041 old_fontface = port->txFace;
6042 #endif
6044 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6045 size = kDefaultFontSize;
6047 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6048 if (strcmp (s_weight, "bold") == 0)
6049 fontface |= bold;
6051 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6052 if (c_slant == 'i')
6053 fontface |= italic;
6055 x_font_name_to_mac_font_name (name, mfontname);
6056 c2pstr (mfontname);
6057 GetFNum (mfontname, &fontnum);
6058 if (fontnum == 0)
6059 return NULL;
6061 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6063 font->fontname = (char *) xmalloc (strlen (name) + 1);
6064 bcopy (name, font->fontname, strlen (name) + 1);
6066 font->mac_fontnum = fontnum;
6067 font->mac_fontsize = size;
6068 font->mac_fontface = fontface;
6069 font->mac_scriptcode = FontToScript (fontnum);
6071 /* Apple Japanese (SJIS) font is listed as both
6072 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6073 (Roman script) in init_font_name_table (). The latter should be
6074 treated as a one-byte font. */
6076 char cs[32];
6078 if (sscanf (name,
6079 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6080 cs) == 1
6081 && 0 == strcmp (cs, "jisx0201.1976-0"))
6082 font->mac_scriptcode = smRoman;
6085 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6086 font->mac_scriptcode == smTradChinese ||
6087 font->mac_scriptcode == smSimpChinese ||
6088 font->mac_scriptcode == smKorean;
6090 TextFont (fontnum);
6091 TextSize (size);
6092 TextFace (fontface);
6094 GetFontInfo (&the_fontinfo);
6096 font->ascent = the_fontinfo.ascent;
6097 font->descent = the_fontinfo.descent;
6099 font->min_byte1 = 0;
6100 if (is_two_byte_font)
6101 font->max_byte1 = 1;
6102 else
6103 font->max_byte1 = 0;
6104 font->min_char_or_byte2 = 0x20;
6105 font->max_char_or_byte2 = 0xff;
6107 if (is_two_byte_font)
6109 /* Use the width of an "ideographic space" of that font because
6110 the_fontinfo.widMax returns the wrong width for some fonts. */
6111 switch (font->mac_scriptcode)
6113 case smJapanese:
6114 char_width = StringWidth("\p\x81\x40");
6115 break;
6116 case smTradChinese:
6117 char_width = StringWidth("\p\xa1\x40");
6118 break;
6119 case smSimpChinese:
6120 char_width = StringWidth("\p\xa1\xa1");
6121 break;
6122 case smKorean:
6123 char_width = StringWidth("\p\xa1\xa1");
6124 break;
6127 else
6128 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6129 returns 15 for 12-point Monaco! */
6130 char_width = CharWidth ('m');
6132 font->max_bounds.rbearing = char_width;
6133 font->max_bounds.lbearing = 0;
6134 font->max_bounds.width = char_width;
6135 font->max_bounds.ascent = the_fontinfo.ascent;
6136 font->max_bounds.descent = the_fontinfo.descent;
6138 font->min_bounds = font->max_bounds;
6140 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6141 font->per_char = NULL;
6142 else
6144 font->per_char = (XCharStruct *)
6145 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6147 int c;
6149 for (c = 0x20; c <= 0xff; c++)
6151 font->per_char[c - 0x20] = font->max_bounds;
6152 font->per_char[c - 0x20].width = CharWidth (c);
6157 TextFont (old_fontnum); /* restore previous font number, size and face */
6158 TextSize (old_fontsize);
6159 TextFace (old_fontface);
6161 return font;
6165 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6166 pointer to the structure font_info while allocating it dynamically.
6167 If SIZE is 0, load any size of font.
6168 If loading is failed, return NULL. */
6170 struct font_info *
6171 x_load_font (f, fontname, size)
6172 struct frame *f;
6173 register char *fontname;
6174 int size;
6176 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6177 Lisp_Object font_names;
6179 /* Get a list of all the fonts that match this name. Once we
6180 have a list of matching fonts, we compare them against the fonts
6181 we already have by comparing names. */
6182 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6184 if (!NILP (font_names))
6186 Lisp_Object tail;
6187 int i;
6189 for (i = 0; i < dpyinfo->n_fonts; i++)
6190 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6191 if (dpyinfo->font_table[i].name
6192 && (!strcmp (dpyinfo->font_table[i].name,
6193 SDATA (XCAR (tail)))
6194 || !strcmp (dpyinfo->font_table[i].full_name,
6195 SDATA (XCAR (tail)))))
6196 return (dpyinfo->font_table + i);
6199 /* Load the font and add it to the table. */
6201 char *full_name;
6202 struct MacFontStruct *font;
6203 struct font_info *fontp;
6204 unsigned long value;
6205 int i;
6207 /* If we have found fonts by x_list_font, load one of them. If
6208 not, we still try to load a font by the name given as FONTNAME
6209 because XListFonts (called in x_list_font) of some X server has
6210 a bug of not finding a font even if the font surely exists and
6211 is loadable by XLoadQueryFont. */
6212 if (size > 0 && !NILP (font_names))
6213 fontname = (char *) SDATA (XCAR (font_names));
6215 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6216 if (!font)
6217 return NULL;
6219 /* Find a free slot in the font table. */
6220 for (i = 0; i < dpyinfo->n_fonts; ++i)
6221 if (dpyinfo->font_table[i].name == NULL)
6222 break;
6224 /* If no free slot found, maybe enlarge the font table. */
6225 if (i == dpyinfo->n_fonts
6226 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6228 int sz;
6229 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6230 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6231 dpyinfo->font_table
6232 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6235 fontp = dpyinfo->font_table + i;
6236 if (i == dpyinfo->n_fonts)
6237 ++dpyinfo->n_fonts;
6239 /* Now fill in the slots of *FONTP. */
6240 BLOCK_INPUT;
6241 bzero (fontp, sizeof (*fontp));
6242 fontp->font = font;
6243 fontp->font_idx = i;
6244 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6245 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6247 fontp->full_name = fontp->name;
6249 fontp->size = font->max_bounds.width;
6250 fontp->height = FONT_HEIGHT (font);
6252 /* For some font, ascent and descent in max_bounds field is
6253 larger than the above value. */
6254 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6255 if (max_height > fontp->height)
6256 fontp->height = max_height;
6259 /* The slot `encoding' specifies how to map a character
6260 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6261 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6262 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6263 2:0xA020..0xFF7F). For the moment, we don't know which charset
6264 uses this font. So, we set information in fontp->encoding[1]
6265 which is never used by any charset. If mapping can't be
6266 decided, set FONT_ENCODING_NOT_DECIDED. */
6267 if (font->mac_scriptcode == smJapanese)
6268 fontp->encoding[1] = 4;
6269 else
6271 fontp->encoding[1]
6272 = (font->max_byte1 == 0
6273 /* 1-byte font */
6274 ? (font->min_char_or_byte2 < 0x80
6275 ? (font->max_char_or_byte2 < 0x80
6276 ? 0 /* 0x20..0x7F */
6277 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6278 : 1) /* 0xA0..0xFF */
6279 /* 2-byte font */
6280 : (font->min_byte1 < 0x80
6281 ? (font->max_byte1 < 0x80
6282 ? (font->min_char_or_byte2 < 0x80
6283 ? (font->max_char_or_byte2 < 0x80
6284 ? 0 /* 0x2020..0x7F7F */
6285 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6286 : 3) /* 0x20A0..0x7FFF */
6287 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6288 : (font->min_char_or_byte2 < 0x80
6289 ? (font->max_char_or_byte2 < 0x80
6290 ? 2 /* 0xA020..0xFF7F */
6291 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6292 : 1))); /* 0xA0A0..0xFFFF */
6295 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6296 fontp->baseline_offset
6297 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6298 ? (long) value : 0);
6299 fontp->relative_compose
6300 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6301 ? (long) value : 0);
6302 fontp->default_ascent
6303 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6304 ? (long) value : 0);
6305 #else
6306 fontp->baseline_offset = 0;
6307 fontp->relative_compose = 0;
6308 fontp->default_ascent = 0;
6309 #endif
6311 /* Set global flag fonts_changed_p to non-zero if the font loaded
6312 has a character with a smaller width than any other character
6313 before, or if the font loaded has a smalle>r height than any
6314 other font loaded before. If this happens, it will make a
6315 glyph matrix reallocation necessary. */
6316 fonts_changed_p = x_compute_min_glyph_bounds (f);
6317 UNBLOCK_INPUT;
6318 return fontp;
6323 /* Return a pointer to struct font_info of a font named FONTNAME for
6324 frame F. If no such font is loaded, return NULL. */
6326 struct font_info *
6327 x_query_font (f, fontname)
6328 struct frame *f;
6329 register char *fontname;
6331 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6332 int i;
6334 for (i = 0; i < dpyinfo->n_fonts; i++)
6335 if (dpyinfo->font_table[i].name
6336 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6337 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6338 return (dpyinfo->font_table + i);
6339 return NULL;
6343 /* Find a CCL program for a font specified by FONTP, and set the member
6344 `encoder' of the structure. */
6346 void
6347 x_find_ccl_program (fontp)
6348 struct font_info *fontp;
6350 Lisp_Object list, elt;
6352 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6354 elt = XCAR (list);
6355 if (CONSP (elt)
6356 && STRINGP (XCAR (elt))
6357 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6358 >= 0))
6359 break;
6361 if (! NILP (list))
6363 struct ccl_program *ccl
6364 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6366 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6367 xfree (ccl);
6368 else
6369 fontp->font_encoder = ccl;
6375 /* The Mac Event loop code */
6377 #ifndef MAC_OSX
6378 #include <Events.h>
6379 #include <Quickdraw.h>
6380 #include <Balloons.h>
6381 #include <Devices.h>
6382 #include <Fonts.h>
6383 #include <Gestalt.h>
6384 #include <Menus.h>
6385 #include <Processes.h>
6386 #include <Sound.h>
6387 #include <ToolUtils.h>
6388 #include <TextUtils.h>
6389 #include <Dialogs.h>
6390 #include <Script.h>
6391 #include <Types.h>
6392 #include <TextEncodingConverter.h>
6393 #include <Resources.h>
6395 #if __MWERKS__
6396 #include <unix.h>
6397 #endif
6398 #endif /* ! MAC_OSX */
6400 #define M_APPLE 128
6401 #define I_ABOUT 1
6403 #define WINDOW_RESOURCE 128
6404 #define TERM_WINDOW_RESOURCE 129
6406 #define DEFAULT_NUM_COLS 80
6408 #define MIN_DOC_SIZE 64
6409 #define MAX_DOC_SIZE 32767
6411 /* sleep time for WaitNextEvent */
6412 #define WNE_SLEEP_AT_SUSPEND 10
6413 #define WNE_SLEEP_AT_RESUME 1
6415 /* true when cannot handle any Mac OS events */
6416 static int handling_window_update = 0;
6418 /* the flag appl_is_suspended is used both for determining the sleep
6419 time to be passed to WaitNextEvent and whether the cursor should be
6420 drawn when updating the display. The cursor is turned off when
6421 Emacs is suspended. Redrawing it is unnecessary and what needs to
6422 be done depends on whether the cursor lies inside or outside the
6423 redraw region. So we might as well skip drawing it when Emacs is
6424 suspended. */
6425 static Boolean app_is_suspended = false;
6426 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
6428 #define EXTRA_STACK_ALLOC (256 * 1024)
6430 #define ARGV_STRING_LIST_ID 129
6431 #define ABOUT_ALERT_ID 128
6432 #define RAM_TOO_LARGE_ALERT_ID 129
6434 Boolean terminate_flag = false;
6436 /* True if using command key as meta key. */
6437 Lisp_Object Vmac_command_key_is_meta;
6439 /* True if the ctrl and meta keys should be reversed. */
6440 Lisp_Object Vmac_reverse_ctrl_meta;
6442 #if USE_CARBON_EVENTS
6443 /* True if the mouse wheel button (i.e. button 4) should map to
6444 mouse-2, instead of mouse-3. */
6445 Lisp_Object Vmac_wheel_button_is_mouse_2;
6447 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
6448 for processing before Emacs sees it. */
6449 Lisp_Object Vmac_pass_command_to_system;
6451 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
6452 for processing before Emacs sees it. */
6453 Lisp_Object Vmac_pass_control_to_system;
6454 #endif
6456 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
6457 to this text encoding */
6458 int mac_keyboard_text_encoding;
6459 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
6461 /* Set in term/mac-win.el to indicate that event loop can now generate
6462 drag and drop events. */
6463 Lisp_Object Qmac_ready_for_drag_n_drop;
6465 Lisp_Object drag_and_drop_file_list;
6467 Point saved_menu_event_location;
6469 /* Apple Events */
6470 static void init_required_apple_events (void);
6471 static pascal OSErr
6472 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
6473 static pascal OSErr
6474 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
6475 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
6476 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
6478 /* Drag and Drop */
6479 static OSErr init_mac_drag_n_drop ();
6480 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
6482 #if USE_CARBON_EVENTS
6483 /* Preliminary Support for the OSX Services Menu */
6484 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
6485 static void init_service_handler ();
6486 #endif
6488 extern void init_emacs_passwd_dir ();
6489 extern int emacs_main (int, char **, char **);
6490 extern void check_alarm ();
6492 extern void initialize_applescript();
6493 extern void terminate_applescript();
6495 static unsigned int
6496 #if USE_CARBON_EVENTS
6497 mac_to_emacs_modifiers (UInt32 mods)
6498 #else
6499 mac_to_emacs_modifiers (EventModifiers mods)
6500 #endif
6502 unsigned int result = 0;
6503 if (mods & macShiftKey)
6504 result |= shift_modifier;
6505 if (mods & macCtrlKey)
6506 result |= ctrl_modifier;
6507 if (mods & macMetaKey)
6508 result |= meta_modifier;
6509 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
6510 result |= alt_modifier;
6511 return result;
6514 #if USE_CARBON_EVENTS
6515 /* Obtains the event modifiers from the event ref and then calls
6516 mac_to_emacs_modifiers. */
6517 static int
6518 mac_event_to_emacs_modifiers (EventRef eventRef)
6520 UInt32 mods = 0;
6521 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
6522 sizeof (UInt32), NULL, &mods);
6523 return mac_to_emacs_modifiers (mods);
6526 /* Given an event ref, return the code to use for the mouse button
6527 code in the emacs input_event. */
6528 static int
6529 mac_get_mouse_btn (EventRef ref)
6531 EventMouseButton result = kEventMouseButtonPrimary;
6532 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
6533 sizeof (EventMouseButton), NULL, &result);
6534 switch (result)
6536 case kEventMouseButtonPrimary:
6537 return 0;
6538 case kEventMouseButtonSecondary:
6539 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
6540 case kEventMouseButtonTertiary:
6541 case 4: /* 4 is the number for the mouse wheel button */
6542 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
6543 default:
6544 return 0;
6548 /* Normally, ConvertEventRefToEventRecord will correctly handle all
6549 events. However the click of the mouse wheel is not converted to a
6550 mouseDown or mouseUp event. This calls ConvertEventRef, but then
6551 checks to see if it is a mouse up or down carbon event that has not
6552 been converted, and if so, converts it by hand (to be picked up in
6553 the XTread_socket loop). */
6554 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
6556 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
6557 /* Do special case for mouse wheel button. */
6558 if (!result && GetEventClass (eventRef) == kEventClassMouse)
6560 UInt32 kind = GetEventKind (eventRef);
6561 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
6563 eventRec->what = mouseDown;
6564 result=1;
6566 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
6568 eventRec->what = mouseUp;
6569 result=1;
6571 if (result)
6573 /* Need where and when. */
6574 UInt32 mods;
6575 GetEventParameter (eventRef, kEventParamMouseLocation,
6576 typeQDPoint, NULL, sizeof (Point),
6577 NULL, &eventRec->where);
6578 /* Use two step process because new event modifiers are
6579 32-bit and old are 16-bit. Currently, only loss is
6580 NumLock & Fn. */
6581 GetEventParameter (eventRef, kEventParamKeyModifiers,
6582 typeUInt32, NULL, sizeof (UInt32),
6583 NULL, &mods);
6584 eventRec->modifiers = mods;
6586 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
6589 return result;
6592 #endif
6594 static void
6595 do_get_menus (void)
6597 Handle menubar_handle;
6598 MenuHandle menu_handle;
6600 menubar_handle = GetNewMBar (128);
6601 if(menubar_handle == NULL)
6602 abort ();
6603 SetMenuBar (menubar_handle);
6604 DrawMenuBar ();
6606 menu_handle = GetMenuHandle (M_APPLE);
6607 if(menu_handle != NULL)
6608 AppendResMenu (menu_handle,'DRVR');
6609 else
6610 abort ();
6614 static void
6615 do_init_managers (void)
6617 #if !TARGET_API_MAC_CARBON
6618 InitGraf (&qd.thePort);
6619 InitFonts ();
6620 FlushEvents (everyEvent, 0);
6621 InitWindows ();
6622 InitMenus ();
6623 TEInit ();
6624 InitDialogs (NULL);
6625 #endif /* !TARGET_API_MAC_CARBON */
6626 InitCursor ();
6628 #if !TARGET_API_MAC_CARBON
6629 /* set up some extra stack space for use by emacs */
6630 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
6632 /* MaxApplZone must be called for AppleScript to execute more
6633 complicated scripts */
6634 MaxApplZone ();
6635 MoreMasters ();
6636 #endif /* !TARGET_API_MAC_CARBON */
6639 static void
6640 do_check_ram_size (void)
6642 SInt32 physical_ram_size, logical_ram_size;
6644 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
6645 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
6646 || physical_ram_size > 256 * 1024 * 1024
6647 || logical_ram_size > 256 * 1024 * 1024)
6649 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
6650 exit (1);
6654 static void
6655 do_window_update (WindowPtr win)
6657 struct mac_output *mwp = (mac_output *) GetWRefCon (win);
6658 struct frame *f = mwp->mFP;
6660 if (f)
6662 if (f->async_visible == 0)
6664 f->async_visible = 1;
6665 f->async_iconified = 0;
6666 SET_FRAME_GARBAGED (f);
6668 /* An update event is equivalent to MapNotify on X, so report
6669 visibility changes properly. */
6670 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
6671 /* Force a redisplay sooner or later to update the
6672 frame titles in case this is the second frame. */
6673 record_asynch_buffer_change ();
6675 else
6677 BeginUpdate (win);
6678 handling_window_update = 1;
6680 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
6682 expose_frame (f, 0, 0, 0, 0);
6684 handling_window_update = 0;
6685 EndUpdate (win);
6690 static int
6691 is_emacs_window (WindowPtr win)
6693 Lisp_Object tail, frame;
6695 if (!win)
6696 return 0;
6698 FOR_EACH_FRAME (tail, frame)
6699 if (FRAME_MAC_P (XFRAME (frame)))
6700 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
6701 return 1;
6703 return 0;
6706 static void
6707 do_window_activate (WindowPtr win)
6709 mac_output *mwp;
6710 struct frame *f;
6712 if (is_emacs_window (win))
6714 mwp = (mac_output *) GetWRefCon (win);
6715 f = mwp->mFP;
6717 if (f)
6719 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
6720 activate_scroll_bars (f);
6725 static void
6726 do_window_deactivate (WindowPtr win)
6728 mac_output *mwp;
6729 struct frame *f;
6731 if (is_emacs_window (win))
6733 mwp = (mac_output *) GetWRefCon (win);
6734 f = mwp->mFP;
6736 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6738 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
6739 deactivate_scroll_bars (f);
6744 static void
6745 do_app_resume ()
6747 WindowPtr wp;
6748 mac_output *mwp;
6749 struct frame *f;
6751 wp = FrontWindow();
6752 if (is_emacs_window (wp))
6754 mwp = (mac_output *) GetWRefCon (wp);
6755 f = mwp->mFP;
6757 if (f)
6759 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
6760 activate_scroll_bars (f);
6764 app_is_suspended = false;
6765 app_sleep_time = WNE_SLEEP_AT_RESUME;
6768 static void
6769 do_app_suspend ()
6771 WindowPtr wp;
6772 mac_output *mwp;
6773 struct frame *f;
6775 wp = FrontWindow();
6776 if (is_emacs_window (wp))
6778 mwp = (mac_output *) GetWRefCon (wp);
6779 f = mwp->mFP;
6781 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
6783 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
6784 deactivate_scroll_bars (f);
6788 app_is_suspended = true;
6789 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
6793 static void
6794 do_mouse_moved (Point mouse_pos)
6796 WindowPtr wp = FrontWindow ();
6797 struct frame *f;
6799 if (is_emacs_window (wp))
6801 f = ((mac_output *) GetWRefCon (wp))->mFP;
6803 #if TARGET_API_MAC_CARBON
6804 SetPort (GetWindowPort (wp));
6805 #else
6806 SetPort (wp);
6807 #endif
6809 GlobalToLocal (&mouse_pos);
6811 note_mouse_movement (f, &mouse_pos);
6816 static void
6817 do_os_event (EventRecord *erp)
6819 switch((erp->message >> 24) & 0x000000FF)
6821 case suspendResumeMessage:
6822 if((erp->message & resumeFlag) == 1)
6823 do_app_resume ();
6824 else
6825 do_app_suspend ();
6826 break;
6828 case mouseMovedMessage:
6829 do_mouse_moved (erp->where);
6830 break;
6834 static void
6835 do_events (EventRecord *erp)
6837 switch (erp->what)
6839 case updateEvt:
6840 do_window_update ((WindowPtr) erp->message);
6841 break;
6843 case osEvt:
6844 do_os_event (erp);
6845 break;
6847 case activateEvt:
6848 if ((erp->modifiers & activeFlag) != 0)
6849 do_window_activate ((WindowPtr) erp->message);
6850 else
6851 do_window_deactivate ((WindowPtr) erp->message);
6852 break;
6856 static void
6857 do_apple_menu (SInt16 menu_item)
6859 #if !TARGET_API_MAC_CARBON
6860 Str255 item_name;
6861 SInt16 da_driver_refnum;
6863 if (menu_item == I_ABOUT)
6864 NoteAlert (ABOUT_ALERT_ID, NULL);
6865 else
6867 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
6868 da_driver_refnum = OpenDeskAcc (item_name);
6870 #endif /* !TARGET_API_MAC_CARBON */
6873 void
6874 do_menu_choice (SInt32 menu_choice)
6876 SInt16 menu_id, menu_item;
6878 menu_id = HiWord (menu_choice);
6879 menu_item = LoWord (menu_choice);
6881 if (menu_id == 0)
6882 return;
6884 switch (menu_id)
6886 case M_APPLE:
6887 do_apple_menu (menu_item);
6888 break;
6890 default:
6892 WindowPtr wp = FrontWindow ();
6893 struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
6894 MenuHandle menu = GetMenuHandle (menu_id);
6895 if (menu)
6897 UInt32 refcon;
6899 GetMenuItemRefCon (menu, menu_item, &refcon);
6900 menubar_selection_callback (f, refcon);
6905 HiliteMenu (0);
6909 /* Handle drags in size box. Based on code contributed by Ben
6910 Mesander and IM - Window Manager A. */
6912 static void
6913 do_grow_window (WindowPtr w, EventRecord *e)
6915 long grow_size;
6916 Rect limit_rect;
6917 int rows, columns;
6918 mac_output *mwp = (mac_output *) GetWRefCon (w);
6919 struct frame *f = mwp->mFP;
6921 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
6923 grow_size = GrowWindow (w, e->where, &limit_rect);
6925 /* see if it really changed size */
6926 if (grow_size != 0)
6928 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
6929 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
6931 x_set_window_size (f, 0, columns, rows);
6936 /* Handle clicks in zoom box. Calculation of "standard state" based
6937 on code in IM - Window Manager A and code contributed by Ben
6938 Mesander. The standard state of an Emacs window is 80-characters
6939 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
6941 static void
6942 do_zoom_window (WindowPtr w, int zoom_in_or_out)
6944 GrafPtr save_port;
6945 Rect zoom_rect, port_rect;
6946 Point top_left;
6947 int w_title_height, columns, rows, width, height, dummy, x, y;
6948 mac_output *mwp = (mac_output *) GetWRefCon (w);
6949 struct frame *f = mwp->mFP;
6951 GetPort (&save_port);
6953 #if TARGET_API_MAC_CARBON
6954 SetPort (GetWindowPort (w));
6955 #else
6956 SetPort (w);
6957 #endif
6959 /* Clear window to avoid flicker. */
6960 #if TARGET_API_MAC_CARBON
6962 Rect r;
6963 BitMap bm;
6965 GetWindowPortBounds (w, &r);
6966 EraseRect (&r);
6968 if (zoom_in_or_out == inZoomOut)
6970 /* calculate height of window's title bar (hard card it for now). */
6971 w_title_height = 20 + GetMBarHeight ();
6973 /* get maximum height of window into zoom_rect.bottom -
6974 zoom_rect.top */
6975 GetQDGlobalsScreenBits (&bm);
6976 zoom_rect = bm.bounds;
6977 zoom_rect.top += w_title_height;
6978 InsetRect (&zoom_rect, 8, 4); /* not too tight */
6980 zoom_rect.right = zoom_rect.left
6981 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
6983 SetWindowStandardState (w, &zoom_rect);
6986 #else /* not TARGET_API_MAC_CARBON */
6987 EraseRect (&(w->portRect));
6988 if (zoom_in_or_out == inZoomOut)
6990 SetPt (&top_left, w->portRect.left, w->portRect.top);
6991 LocalToGlobal (&top_left);
6993 /* calculate height of window's title bar */
6994 w_title_height = top_left.v - 1
6995 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
6997 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
6998 zoom_rect = qd.screenBits.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 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7006 = zoom_rect;
7008 #endif /* not TARGET_API_MAC_CARBON */
7010 ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
7012 /* retrieve window size and update application values */
7013 #if TARGET_API_MAC_CARBON
7014 GetWindowPortBounds (w, &port_rect);
7015 #else
7016 port_rect = w->portRect;
7017 #endif
7018 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
7019 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
7020 x_set_window_size (mwp->mFP, 0, columns, rows);
7022 SetPort (save_port);
7025 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7026 static OSErr
7027 init_mac_drag_n_drop ()
7029 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7030 return result;
7033 /* Intialize AppleEvent dispatcher table for the required events. */
7034 void
7035 init_required_apple_events ()
7037 OSErr err;
7038 long result;
7040 /* Make sure we have apple events before starting. */
7041 err = Gestalt (gestaltAppleEventsAttr, &result);
7042 if (err != noErr)
7043 abort ();
7045 if (!(result & (1 << gestaltAppleEventsPresent)))
7046 abort ();
7048 #if TARGET_API_MAC_CARBON
7049 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7050 NewAEEventHandlerUPP
7051 ((AEEventHandlerProcPtr) do_ae_open_application),
7052 0L, false);
7053 #else
7054 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7055 NewAEEventHandlerProc
7056 ((AEEventHandlerProcPtr) do_ae_open_application),
7057 0L, false);
7058 #endif
7059 if (err != noErr)
7060 abort ();
7062 #if TARGET_API_MAC_CARBON
7063 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7064 NewAEEventHandlerUPP
7065 ((AEEventHandlerProcPtr) do_ae_open_documents),
7066 0L, false);
7067 #else
7068 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7069 NewAEEventHandlerProc
7070 ((AEEventHandlerProcPtr) do_ae_open_documents),
7071 0L, false);
7072 #endif
7073 if (err != noErr)
7074 abort ();
7076 #if TARGET_API_MAC_CARBON
7077 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7078 NewAEEventHandlerUPP
7079 ((AEEventHandlerProcPtr) do_ae_print_documents),
7080 0L, false);
7081 #else
7082 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7083 NewAEEventHandlerProc
7084 ((AEEventHandlerProcPtr) do_ae_print_documents),
7085 0L, false);
7086 #endif
7087 if (err != noErr)
7088 abort ();
7090 #if TARGET_API_MAC_CARBON
7091 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7092 NewAEEventHandlerUPP
7093 ((AEEventHandlerProcPtr) do_ae_quit_application),
7094 0L, false);
7095 #else
7096 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7097 NewAEEventHandlerProc
7098 ((AEEventHandlerProcPtr) do_ae_quit_application),
7099 0L, false);
7100 #endif
7101 if (err != noErr)
7102 abort ();
7105 #if USE_CARBON_EVENTS
7107 void
7108 init_service_handler ()
7110 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7111 {kEventClassService, kEventServiceCopy},
7112 {kEventClassService, kEventServicePaste}};
7113 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7114 3, specs, NULL, NULL);
7118 MAC_TODO: Check to see if this is called by AEProcessDesc...
7120 OSStatus
7121 mac_handle_service_event (EventHandlerCallRef callRef,
7122 EventRef event, void *data)
7124 OSStatus err = noErr;
7125 switch (GetEventKind (event))
7127 case kEventServiceGetTypes:
7129 CFMutableArrayRef copyTypes, pasteTypes;
7130 CFStringRef type;
7131 Boolean selection = true;
7133 GetEventParameter(event, kEventParamServicePasteTypes,
7134 typeCFMutableArrayRef, NULL,
7135 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7137 GetEventParameter(event, kEventParamServiceCopyTypes,
7138 typeCFMutableArrayRef, NULL,
7139 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7140 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7141 if (type) {
7142 CFArrayAppendValue (copyTypes, type);
7143 //CFArrayAppendValue (pasteTypes, type);
7144 CFRelease (type);
7147 case kEventServiceCopy:
7149 ScrapRef currentScrap, specificScrap;
7150 char * buf = "";
7151 Size byteCount = 0;
7153 GetCurrentScrap (&currentScrap);
7155 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7156 if (err == noErr)
7158 void *buffer = xmalloc (byteCount);
7159 if (buffer != NULL)
7161 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7162 sizeof (ScrapRef), NULL, &specificScrap);
7164 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7165 &byteCount, buffer);
7166 if (err == noErr)
7167 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7168 kScrapFlavorMaskNone, byteCount, buffer);
7169 xfree (buffer);
7172 err = noErr;
7174 case kEventServicePaste:
7177 // Get the current location
7178 Size byteCount;
7179 ScrapRef specificScrap;
7180 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7181 sizeof(ScrapRef), NULL, &specificScrap);
7182 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7183 if (err == noErr) {
7184 void * buffer = xmalloc(byteCount);
7185 if (buffer != NULL ) {
7186 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7187 &byteCount, buffer);
7188 if (err == noErr) {
7189 // Actually place in the buffer
7190 BLOCK_INPUT;
7191 // Get the current "selection" string here
7192 UNBLOCK_INPUT;
7195 xfree(buffer);
7200 return err;
7202 #endif
7204 /* Open Application Apple Event */
7205 static pascal OSErr
7206 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7208 return noErr;
7212 /* Defined in mac.c. */
7213 extern int
7214 path_from_vol_dir_name (char *, int, short, long, char *);
7217 /* Called when we receive an AppleEvent with an ID of
7218 "kAEOpenDocuments". This routine gets the direct parameter,
7219 extracts the FSSpecs in it, and puts their names on a list. */
7220 static pascal OSErr
7221 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7223 OSErr err, err2;
7224 AEDesc the_desc;
7225 AEKeyword keyword;
7226 DescType actual_type;
7227 Size actual_size;
7229 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7230 if (err != noErr)
7231 goto descriptor_error_exit;
7233 /* Check to see that we got all of the required parameters from the
7234 event descriptor. For an 'odoc' event this should just be the
7235 file list. */
7236 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
7237 &actual_type, (Ptr) &keyword,
7238 sizeof (keyword), &actual_size);
7239 /* No error means that we found some unused parameters.
7240 errAEDescNotFound means that there are no more parameters. If we
7241 get an error code other than that, flag it. */
7242 if ((err == noErr) || (err != errAEDescNotFound))
7244 err = errAEEventNotHandled;
7245 goto error_exit;
7247 err = noErr;
7249 /* Got all the parameters we need. Now, go through the direct
7250 object list and parse it up. */
7252 long num_files_to_open;
7254 err = AECountItems (&the_desc, &num_files_to_open);
7255 if (err == noErr)
7257 int i;
7259 /* AE file list is one based so just use that for indexing here. */
7260 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7262 FSSpec fs;
7263 Str255 path_name, unix_path_name;
7264 #ifdef MAC_OSX
7265 FSRef fref;
7266 #endif
7268 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7269 (Ptr) &fs, sizeof (fs), &actual_size);
7270 if (err != noErr) break;
7272 #ifdef MAC_OSX
7273 err = FSpMakeFSRef (&fs, &fref);
7274 if (err != noErr) break;
7276 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
7277 #else
7278 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
7279 fs.name) &&
7280 mac_to_posix_pathname (path_name, unix_path_name, 255))
7281 #endif
7282 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7283 drag_and_drop_file_list);
7288 error_exit:
7289 /* Nuke the coerced file list in any case */
7290 err2 = AEDisposeDesc(&the_desc);
7292 descriptor_error_exit:
7293 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7294 return err;
7298 static pascal OSErr
7299 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
7300 DragReference theDrag)
7302 short items;
7303 short index;
7304 FlavorFlags theFlags;
7305 Point mouse;
7306 OSErr result;
7307 ItemReference theItem;
7308 HFSFlavor data;
7309 FSRef fref;
7310 Size size = sizeof (HFSFlavor);
7312 drag_and_drop_file_list = Qnil;
7313 GetDragMouse (theDrag, &mouse, 0L);
7314 CountDragItems (theDrag, &items);
7315 for (index = 1; index <= items; index++)
7317 /* Only handle file references. */
7318 GetDragItemReferenceNumber (theDrag, index, &theItem);
7319 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
7320 if (result == noErr)
7322 #ifdef MAC_OSX
7323 FSRef frref;
7324 #else
7325 Str255 path_name;
7326 #endif
7327 Str255 unix_path_name;
7328 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
7329 #ifdef MAC_OSX
7330 /* Use Carbon routines, otherwise it converts the file name
7331 to /Macintosh HD/..., which is not correct. */
7332 FSpMakeFSRef (&data.fileSpec, &fref);
7333 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
7334 #else
7335 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
7336 data.fileSpec.parID, data.fileSpec.name) &&
7337 mac_to_posix_pathname (path_name, unix_path_name, 255))
7338 #endif
7339 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7340 drag_and_drop_file_list);
7342 else
7343 return;
7345 /* If there are items in the list, construct an event and post it to
7346 the queue like an interrupt using kbd_buffer_store_event. */
7347 if (!NILP (drag_and_drop_file_list))
7349 struct input_event event;
7350 Lisp_Object frame;
7351 struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
7352 SetPort (GetWindowPort (window));
7353 GlobalToLocal (&mouse);
7355 event.kind = DRAG_N_DROP_EVENT;
7356 event.code = 0;
7357 event.modifiers = 0;
7358 event.timestamp = TickCount () * (1000 / 60);
7359 XSETINT (event.x, mouse.h);
7360 XSETINT (event.y, mouse.v);
7361 XSETFRAME (frame, f);
7362 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
7363 event.arg = Qnil;
7364 /* Post to the interrupt queue */
7365 kbd_buffer_store_event (&event);
7366 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7368 ProcessSerialNumber psn;
7369 GetCurrentProcess (&psn);
7370 SetFrontProcess (&psn);
7376 /* Print Document Apple Event */
7377 static pascal OSErr
7378 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
7380 return errAEEventNotHandled;
7384 static pascal OSErr
7385 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
7387 /* FixMe: Do we need an unwind-protect or something here? And what
7388 do we do about unsaved files. Currently just forces quit rather
7389 than doing recursive callback to get user input. */
7391 terminate_flag = true;
7393 /* Fkill_emacs doesn't return. We have to return. (TI) */
7394 return noErr;
7398 #if __profile__
7399 void
7400 profiler_exit_proc ()
7402 ProfilerDump ("\pEmacs.prof");
7403 ProfilerTerm ();
7405 #endif
7407 /* These few functions implement Emacs as a normal Mac application
7408 (almost): set up the heap and the Toolbox, handle necessary
7409 system events plus a few simple menu events. They also set up
7410 Emacs's access to functions defined in the rest of this file.
7411 Emacs uses function hooks to perform all its terminal I/O. A
7412 complete list of these functions appear in termhooks.h. For what
7413 they do, read the comments there and see also w32term.c and
7414 xterm.c. What's noticeably missing here is the event loop, which
7415 is normally present in most Mac application. After performing the
7416 necessary Mac initializations, main passes off control to
7417 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7418 mac_read_socket (defined further below) to read input. This is
7419 where WaitNextEvent is called to process Mac events. This is also
7420 where check_alarm in sysdep.c is called to simulate alarm signals.
7421 This makes the cursor jump back to its correct position after
7422 briefly jumping to that of the matching parenthesis, print useful
7423 hints and prompts in the minibuffer after the user stops typing for
7424 a wait, etc. */
7426 #if !TARGET_API_MAC_CARBON
7427 #undef main
7429 main (void)
7431 #if __profile__ /* is the profiler on? */
7432 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
7433 exit(1);
7434 #endif
7436 #if __MWERKS__
7437 /* set creator and type for files created by MSL */
7438 _fcreator = 'EMAx';
7439 _ftype = 'TEXT';
7440 #endif
7442 do_init_managers ();
7444 do_get_menus ();
7446 do_check_ram_size ();
7448 init_emacs_passwd_dir ();
7450 init_environ ();
7452 initialize_applescript ();
7454 init_required_apple_events ();
7457 char **argv;
7458 int argc = 0;
7460 /* set up argv array from STR# resource */
7461 get_string_list (&argv, ARGV_STRING_LIST_ID);
7462 while (argv[argc])
7463 argc++;
7465 /* free up AppleScript resources on exit */
7466 atexit (terminate_applescript);
7468 #if __profile__ /* is the profiler on? */
7469 atexit (profiler_exit_proc);
7470 #endif
7472 /* 3rd param "envp" never used in emacs_main */
7473 (void) emacs_main (argc, argv, 0);
7476 /* Never reached - real exit in Fkill_emacs */
7477 return 0;
7479 #endif
7481 /* Table for translating Mac keycode to X keysym values. Contributed
7482 by Sudhir Shenoy. */
7483 static unsigned char keycode_to_xkeysym_table[] = {
7484 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7485 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7486 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7488 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
7489 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
7490 /*0x38*/ 0, 0, 0, 0,
7491 /*0x3C*/ 0, 0, 0, 0,
7493 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
7494 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
7495 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
7496 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
7498 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
7499 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
7500 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
7501 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
7503 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
7504 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
7505 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
7506 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
7508 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
7509 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
7510 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
7511 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
7514 static int
7515 keycode_to_xkeysym (int keyCode, int *xKeySym)
7517 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
7518 return *xKeySym != 0;
7521 /* Emacs calls this whenever it wants to read an input event from the
7522 user. */
7524 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
7526 int count = 0;
7527 #if USE_CARBON_EVENTS
7528 OSStatus rneResult;
7529 EventRef eventRef;
7530 EventMouseButton mouseBtn;
7531 #endif
7532 EventRecord er;
7533 int the_modifiers;
7534 EventMask event_mask;
7536 #if 0
7537 if (interrupt_input_blocked)
7539 interrupt_input_pending = 1;
7540 return -1;
7542 #endif
7544 interrupt_input_pending = 0;
7545 BLOCK_INPUT;
7547 /* So people can tell when we have read the available input. */
7548 input_signal_count++;
7550 if (numchars <= 0)
7551 abort ();
7553 /* Don't poll for events to process (specifically updateEvt) if
7554 window update currently already in progress. A call to redisplay
7555 (in do_window_update) can be preempted by another call to
7556 redisplay, causing blank regions to be left on the screen and the
7557 cursor to be left at strange places. */
7558 if (handling_window_update)
7560 UNBLOCK_INPUT;
7561 return 0;
7564 if (terminate_flag)
7565 Fkill_emacs (make_number (1));
7567 /* It is necessary to set this (additional) argument slot of an
7568 event to nil because keyboard.c protects incompletely processed
7569 event from being garbage collected by placing them in the
7570 kbd_buffer_gcpro vector. */
7571 bufp->arg = Qnil;
7573 event_mask = everyEvent;
7574 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
7575 event_mask -= highLevelEventMask;
7577 #if USE_CARBON_EVENTS
7578 rneResult = ReceiveNextEvent (0, NULL,
7579 expected
7580 ? TicksToEventTime (app_sleep_time)
7581 : 0,
7582 kEventRemoveFromQueue, &eventRef);
7583 if (!rneResult)
7585 /* Handle new events */
7586 if (!mac_convert_event_ref (eventRef, &er))
7587 switch (GetEventClass (eventRef))
7589 case kEventClassMouse:
7590 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
7592 SInt32 delta;
7593 Point point;
7594 WindowPtr window_ptr = FrontNonFloatingWindow ();
7595 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
7596 if (!IsValidWindowPtr (window_ptr))
7598 SysBeep(1);
7599 UNBLOCK_INPUT;
7600 return 0;
7603 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
7604 typeSInt32, NULL, sizeof (SInt32),
7605 NULL, &delta);
7606 GetEventParameter(eventRef, kEventParamMouseLocation,
7607 typeQDPoint, NULL, sizeof (Point),
7608 NULL, &point);
7609 bufp->kind = WHEEL_EVENT;
7610 bufp->code = 0;
7611 bufp->modifiers = (mac_event_to_emacs_modifiers(eventRef)
7612 | ((delta < 0) ? down_modifier
7613 : up_modifier));
7614 SetPort (GetWindowPort (window_ptr));
7615 GlobalToLocal (&point);
7616 XSETINT (bufp->x, point.h);
7617 XSETINT (bufp->y, point.v);
7618 XSETFRAME (bufp->frame_or_window, mwp->mFP);
7619 bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
7620 count++;
7622 else
7623 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
7625 break;
7626 default:
7627 /* Send the event to the appropriate receiver. */
7628 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
7630 else
7631 #else
7632 if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
7633 #endif /* USE_CARBON_EVENTS */
7634 switch (er.what)
7636 case mouseDown:
7637 case mouseUp:
7639 WindowPtr window_ptr = FrontWindow ();
7640 SInt16 part_code;
7642 #if USE_CARBON_EVENTS
7643 /* This is needed to send mouse events like aqua window buttons
7644 to the correct handler. */
7645 if (eventNotHandledErr != SendEventToEventTarget (eventRef, GetEventDispatcherTarget ())) {
7646 break;
7649 if (!is_emacs_window(window_ptr))
7650 break;
7651 #endif
7653 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
7654 && er.what == mouseUp)
7656 struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
7657 Point mouse_loc = er.where;
7659 /* Convert to local coordinates of new window. */
7660 #if TARGET_API_MAC_CARBON
7661 SetPort (GetWindowPort (window_ptr));
7662 #else
7663 SetPort (window_ptr);
7664 #endif
7666 GlobalToLocal (&mouse_loc);
7668 #if USE_CARBON_EVENTS
7669 bufp->code = mac_get_mouse_btn (eventRef);
7670 #else
7671 bufp->code = 0; /* only one mouse button */
7672 #endif
7673 bufp->kind = SCROLL_BAR_CLICK_EVENT;
7674 bufp->frame_or_window = tracked_scroll_bar->window;
7675 bufp->part = scroll_bar_handle;
7676 #if USE_CARBON_EVENTS
7677 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
7678 #else
7679 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
7680 #endif
7681 bufp->modifiers |= up_modifier;
7682 bufp->timestamp = er.when * (1000 / 60);
7683 /* ticks to milliseconds */
7685 XSETINT (bufp->x, tracked_scroll_bar->left + 2);
7686 XSETINT (bufp->y, mouse_loc.v - 24);
7687 tracked_scroll_bar->dragging = Qnil;
7688 mouse_tracking_in_progress = mouse_tracking_none;
7689 tracked_scroll_bar = NULL;
7690 count++;
7691 break;
7694 part_code = FindWindow (er.where, &window_ptr);
7696 switch (part_code)
7698 case inMenuBar:
7699 if (er.what == mouseDown)
7701 struct frame *f = ((mac_output *)
7702 GetWRefCon (FrontWindow ()))->mFP;
7703 saved_menu_event_location = er.where;
7704 bufp->kind = MENU_BAR_ACTIVATE_EVENT;
7705 XSETFRAME (bufp->frame_or_window, f);
7706 count++;
7708 break;
7710 case inContent:
7711 if (window_ptr != FrontWindow ())
7712 SelectWindow (window_ptr);
7713 else
7715 SInt16 control_part_code;
7716 ControlHandle ch;
7717 struct mac_output *mwp = (mac_output *)
7718 GetWRefCon (window_ptr);
7719 Point mouse_loc = er.where;
7721 /* convert to local coordinates of new window */
7722 #if TARGET_API_MAC_CARBON
7723 SetPort (GetWindowPort (window_ptr));
7724 #else
7725 SetPort (window_ptr);
7726 #endif
7728 GlobalToLocal (&mouse_loc);
7729 #if TARGET_API_MAC_CARBON
7730 ch = FindControlUnderMouse (mouse_loc, window_ptr,
7731 &control_part_code);
7732 #else
7733 control_part_code = FindControl (mouse_loc, window_ptr, &ch);
7734 #endif
7736 #if USE_CARBON_EVENTS
7737 bufp->code = mac_get_mouse_btn (eventRef);
7738 #else
7739 bufp->code = 0; /* only one mouse button */
7740 #endif
7741 XSETINT (bufp->x, mouse_loc.h);
7742 XSETINT (bufp->y, mouse_loc.v);
7743 bufp->timestamp = er.when * (1000 / 60);
7744 /* ticks to milliseconds */
7746 #if TARGET_API_MAC_CARBON
7747 if (ch != 0)
7748 #else
7749 if (control_part_code != 0)
7750 #endif
7752 struct scroll_bar *bar = (struct scroll_bar *)
7753 GetControlReference (ch);
7754 x_scroll_bar_handle_click (bar, control_part_code, &er,
7755 bufp);
7756 if (er.what == mouseDown
7757 && control_part_code == kControlIndicatorPart)
7759 mouse_tracking_in_progress
7760 = mouse_tracking_scroll_bar;
7761 tracked_scroll_bar = bar;
7763 else
7765 mouse_tracking_in_progress = mouse_tracking_none;
7766 tracked_scroll_bar = NULL;
7769 else
7771 bufp->kind = MOUSE_CLICK_EVENT;
7772 XSETFRAME (bufp->frame_or_window, mwp->mFP);
7773 if (er.what == mouseDown)
7774 mouse_tracking_in_progress
7775 = mouse_tracking_mouse_movement;
7776 else
7777 mouse_tracking_in_progress = mouse_tracking_none;
7780 #if USE_CARBON_EVENTS
7781 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
7782 #else
7783 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
7784 #endif
7786 switch (er.what)
7788 case mouseDown:
7789 bufp->modifiers |= down_modifier;
7790 break;
7791 case mouseUp:
7792 bufp->modifiers |= up_modifier;
7793 break;
7796 count++;
7798 break;
7800 case inDrag:
7801 #if TARGET_API_MAC_CARBON
7802 if (er.what == mouseDown)
7804 BitMap bm;
7806 GetQDGlobalsScreenBits (&bm);
7807 DragWindow (window_ptr, er.where, &bm.bounds);
7809 #else /* not TARGET_API_MAC_CARBON */
7810 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
7811 #endif /* not TARGET_API_MAC_CARBON */
7812 break;
7814 case inGoAway:
7815 if (TrackGoAway (window_ptr, er.where))
7817 bufp->kind = DELETE_WINDOW_EVENT;
7818 XSETFRAME (bufp->frame_or_window,
7819 ((mac_output *) GetWRefCon (window_ptr))->mFP);
7820 count++;
7822 break;
7824 /* window resize handling added --ben */
7825 case inGrow:
7826 if (er.what == mouseDown)
7828 do_grow_window(window_ptr, &er);
7829 break;
7832 /* window zoom handling added --ben */
7833 case inZoomIn:
7834 case inZoomOut:
7835 if (TrackBox (window_ptr, er.where, part_code))
7836 do_zoom_window (window_ptr, part_code);
7837 break;
7839 default:
7840 break;
7843 break;
7845 case updateEvt:
7846 case osEvt:
7847 case activateEvt:
7848 #if USE_CARBON_EVENTS
7849 if (eventNotHandledErr == SendEventToEventTarget (eventRef, GetEventDispatcherTarget ()))
7850 #endif
7851 do_events (&er);
7852 break;
7854 case keyDown:
7855 case autoKey:
7857 int keycode = (er.message & keyCodeMask) >> 8;
7858 int xkeysym;
7860 #if USE_CARBON_EVENTS
7861 /* When using Carbon Events, we need to pass raw keyboard events
7862 to the TSM ourselves. If TSM handles it, it will pass back
7863 noErr, otherwise it will pass back "eventNotHandledErr" and
7864 we can process it normally. */
7865 if ((!NILP (Vmac_pass_command_to_system)
7866 || !(er.modifiers & cmdKey))
7867 && (!NILP (Vmac_pass_control_to_system)
7868 || !(er.modifiers & controlKey)))
7870 OSStatus err;
7871 err = SendEventToEventTarget (eventRef,
7872 GetEventDispatcherTarget ());
7873 if (err != eventNotHandledErr)
7874 break;
7876 #endif
7878 if (!IsValidWindowPtr (FrontNonFloatingWindow ()))
7880 SysBeep (1);
7881 UNBLOCK_INPUT;
7882 return 0;
7885 ObscureCursor ();
7887 if (keycode_to_xkeysym (keycode, &xkeysym))
7889 bufp->code = 0xff00 | xkeysym;
7890 bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
7892 else
7894 if (er.modifiers & (controlKey |
7895 (NILP (Vmac_command_key_is_meta) ? optionKey
7896 : cmdKey)))
7898 /* This code comes from Keyboard Resource, Appendix
7899 C of IM - Text. This is necessary since shift is
7900 ignored in KCHR table translation when option or
7901 command is pressed. It also does not translate
7902 correctly control-shift chars like C-% so mask off
7903 shift here also */
7904 int new_modifiers = er.modifiers & 0xe600;
7905 /* mask off option and command */
7906 int new_keycode = keycode | new_modifiers;
7907 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
7908 unsigned long some_state = 0;
7909 bufp->code = KeyTranslate (kchr_ptr, new_keycode,
7910 &some_state) & 0xff;
7912 else
7913 bufp->code = er.message & charCodeMask;
7914 bufp->kind = ASCII_KEYSTROKE_EVENT;
7918 /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
7919 convert non-ASCII characters typed at the Mac keyboard
7920 (presumed to be in the Mac Roman encoding) to iso-latin-1
7921 encoding before they are passed to Emacs. This enables the
7922 Mac keyboard to be used to enter non-ASCII iso-latin-1
7923 characters directly. */
7924 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
7925 && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
7927 static TECObjectRef converter = NULL;
7928 OSStatus the_err = noErr;
7929 OSStatus convert_status = noErr;
7931 if (converter == NULL)
7933 the_err = TECCreateConverter (&converter,
7934 kTextEncodingMacRoman,
7935 mac_keyboard_text_encoding);
7936 current_mac_keyboard_text_encoding
7937 = mac_keyboard_text_encoding;
7939 else if (mac_keyboard_text_encoding
7940 != current_mac_keyboard_text_encoding)
7942 /* Free the converter for the current encoding before
7943 creating a new one. */
7944 TECDisposeConverter (converter);
7945 the_err = TECCreateConverter (&converter,
7946 kTextEncodingMacRoman,
7947 mac_keyboard_text_encoding);
7948 current_mac_keyboard_text_encoding
7949 = mac_keyboard_text_encoding;
7952 if (the_err == noErr)
7954 unsigned char ch = bufp->code;
7955 ByteCount actual_input_length, actual_output_length;
7956 unsigned char outch;
7958 convert_status = TECConvertText (converter, &ch, 1,
7959 &actual_input_length,
7960 &outch, 1,
7961 &actual_output_length);
7962 if (convert_status == noErr
7963 && actual_input_length == 1
7964 && actual_output_length == 1)
7965 bufp->code = outch;
7969 #if USE_CARBON_EVENTS
7970 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
7971 #else
7972 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
7973 #endif
7976 mac_output *mwp
7977 = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
7978 XSETFRAME (bufp->frame_or_window, mwp->mFP);
7981 bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
7983 count++;
7984 break;
7986 case kHighLevelEvent:
7987 drag_and_drop_file_list = Qnil;
7989 AEProcessAppleEvent(&er);
7991 /* Build a DRAG_N_DROP_EVENT type event as is done in
7992 constuct_drag_n_drop in w32term.c. */
7993 if (!NILP (drag_and_drop_file_list))
7995 struct frame *f = NULL;
7996 WindowPtr wp;
7997 Lisp_Object frame;
7999 wp = FrontNonFloatingWindow ();
8001 if (!wp)
8003 struct frame *f = XFRAME (XCAR (Vframe_list));
8004 CollapseWindow (FRAME_MAC_WINDOW (f), false);
8005 wp = FrontNonFloatingWindow ();
8008 if (wp && is_emacs_window(wp))
8009 f = ((mac_output *) GetWRefCon (wp))->mFP;
8011 bufp->kind = DRAG_N_DROP_EVENT;
8012 bufp->code = 0;
8013 bufp->timestamp = er.when * (1000 / 60);
8014 /* ticks to milliseconds */
8015 #if USE_CARBON_EVENTS
8016 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
8017 #else
8018 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
8019 #endif
8021 XSETINT (bufp->x, 0);
8022 XSETINT (bufp->y, 0);
8024 XSETFRAME (frame, f);
8025 bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
8027 /* Regardless of whether Emacs was suspended or in the
8028 foreground, ask it to redraw its entire screen.
8029 Otherwise parts of the screen can be left in an
8030 inconsistent state. */
8031 if (wp)
8032 #if TARGET_API_MAC_CARBON
8034 Rect r;
8036 GetWindowPortBounds (wp, &r);
8037 InvalWindowRect (wp, &r);
8039 #else /* not TARGET_API_MAC_CARBON */
8040 InvalRect (&(wp->portRect));
8041 #endif /* not TARGET_API_MAC_CARBON */
8043 count++;
8045 default:
8046 break;
8048 #if USE_CARBON_EVENTS
8049 ReleaseEvent (eventRef);
8051 #endif
8053 /* If the focus was just given to an autoraising frame,
8054 raise it now. */
8055 /* ??? This ought to be able to handle more than one such frame. */
8056 if (pending_autoraise_frame)
8058 x_raise_frame (pending_autoraise_frame);
8059 pending_autoraise_frame = 0;
8062 #if !TARGET_API_MAC_CARBON
8063 check_alarm (); /* simulate the handling of a SIGALRM */
8064 #endif
8067 static Point old_mouse_pos = { -1, -1 };
8069 if (app_is_suspended)
8071 old_mouse_pos.h = -1;
8072 old_mouse_pos.v = -1;
8074 else
8076 Point mouse_pos;
8077 WindowPtr wp;
8078 struct frame *f;
8079 Lisp_Object bar;
8080 struct scroll_bar *sb;
8082 wp = FrontWindow ();
8083 if (is_emacs_window (wp))
8085 f = ((mac_output *) GetWRefCon (wp))->mFP;
8087 #if TARGET_API_MAC_CARBON
8088 SetPort (GetWindowPort (wp));
8089 #else
8090 SetPort (wp);
8091 #endif
8093 GetMouse (&mouse_pos);
8095 if (!EqualPt (mouse_pos, old_mouse_pos))
8097 if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
8098 && tracked_scroll_bar)
8099 x_scroll_bar_note_movement (tracked_scroll_bar,
8100 mouse_pos.v
8101 - XINT (tracked_scroll_bar->top),
8102 TickCount() * (1000 / 60));
8103 else
8104 note_mouse_movement (f, &mouse_pos);
8106 old_mouse_pos = mouse_pos;
8112 UNBLOCK_INPUT;
8114 return count;
8118 /* Need to override CodeWarrior's input function so no conversion is
8119 done on newlines Otherwise compiled functions in .elc files will be
8120 read incorrectly. Defined in ...:MSL C:MSL
8121 Common:Source:buffer_io.c. */
8122 #ifdef __MWERKS__
8123 void
8124 __convert_to_newlines (unsigned char * p, size_t * n)
8126 #pragma unused(p,n)
8129 void
8130 __convert_from_newlines (unsigned char * p, size_t * n)
8132 #pragma unused(p,n)
8134 #endif
8137 /* Initialize the struct pointed to by MW to represent a new COLS x
8138 ROWS Macintosh window, using font with name FONTNAME and size
8139 FONTSIZE. */
8140 void
8141 NewMacWindow (FRAME_PTR fp)
8143 mac_output *mwp;
8144 #if TARGET_API_MAC_CARBON
8145 static int making_terminal_window = 0;
8146 #else
8147 static int making_terminal_window = 1;
8148 #endif
8150 mwp = fp->output_data.mac;
8152 if (making_terminal_window)
8154 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
8155 (WindowPtr) -1)))
8156 abort ();
8157 making_terminal_window = 0;
8159 else
8160 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
8161 abort ();
8163 SetWRefCon (mwp->mWP, (long) mwp);
8164 /* so that update events can find this mac_output struct */
8165 mwp->mFP = fp; /* point back to emacs frame */
8167 #if TARGET_API_MAC_CARBON
8168 SetPort (GetWindowPort (mwp->mWP));
8169 #else
8170 SetPort (mwp->mWP);
8171 #endif
8173 mwp->fontset = -1;
8175 SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
8176 ShowWindow (mwp->mWP);
8181 void
8182 make_mac_frame (struct frame *f)
8184 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8185 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8187 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8189 NewMacWindow(f);
8191 f->output_data.mac->cursor_pixel = 0;
8192 f->output_data.mac->border_pixel = 0x00ff00;
8193 f->output_data.mac->mouse_pixel = 0xff00ff;
8194 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
8196 FRAME_FONTSET (f) = -1;
8197 f->output_data.mac->scroll_bar_foreground_pixel = -1;
8198 f->output_data.mac->scroll_bar_background_pixel = -1;
8199 f->output_data.mac->explicit_parent = 0;
8200 f->left_pos = 4;
8201 f->top_pos = 4;
8202 f->border_width = 0;
8204 f->internal_border_width = 0;
8206 f->output_method = output_mac;
8208 f->auto_raise = 1;
8209 f->auto_lower = 1;
8211 f->new_text_cols = 0;
8212 f->new_text_lines = 0;
8215 void
8216 make_mac_terminal_frame (struct frame *f)
8218 Lisp_Object frame;
8220 XSETFRAME (frame, f);
8222 f->output_method = output_mac;
8223 f->output_data.mac = (struct mac_output *)
8224 xmalloc (sizeof (struct mac_output));
8225 bzero (f->output_data.mac, sizeof (struct mac_output));
8226 FRAME_FONTSET (f) = -1;
8227 f->output_data.mac->scroll_bar_foreground_pixel = -1;
8228 f->output_data.mac->scroll_bar_background_pixel = -1;
8230 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8232 FRAME_COLS (f) = 96;
8233 FRAME_LINES (f) = 4;
8235 make_mac_frame (f);
8237 x_make_gc (f);
8239 /* Need to be initialized for unshow_buffer in window.c. */
8240 selected_window = f->selected_window;
8242 Fmodify_frame_parameters (frame,
8243 Fcons (Fcons (Qfont,
8244 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
8245 Fmodify_frame_parameters (frame,
8246 Fcons (Fcons (Qforeground_color,
8247 build_string ("black")), Qnil));
8248 Fmodify_frame_parameters (frame,
8249 Fcons (Fcons (Qbackground_color,
8250 build_string ("white")), Qnil));
8254 /***********************************************************************
8255 Initialization
8256 ***********************************************************************/
8258 int mac_initialized = 0;
8260 void
8261 mac_initialize_display_info ()
8263 struct mac_display_info *dpyinfo = &one_mac_display_info;
8264 GDHandle main_device_handle;
8266 bzero (dpyinfo, sizeof (*dpyinfo));
8268 /* Put it on x_display_name_list. */
8269 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
8270 x_display_name_list);
8271 dpyinfo->name_list_element = XCAR (x_display_name_list);
8273 #if 0
8274 dpyinfo->mac_id_name
8275 = (char *) xmalloc (SCHARS (Vinvocation_name)
8276 + SCHARS (Vsystem_name)
8277 + 2);
8278 sprintf (dpyinfo->mac_id_name, "%s@%s",
8279 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8280 #else
8281 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
8282 strcpy (dpyinfo->mac_id_name, "Mac Display");
8283 #endif
8285 main_device_handle = LMGetMainDevice();
8287 dpyinfo->reference_count = 0;
8288 dpyinfo->resx = 75.0;
8289 dpyinfo->resy = 75.0;
8290 dpyinfo->n_planes = 1;
8291 dpyinfo->n_cbits = 16;
8292 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8293 dpyinfo->width = (**main_device_handle).gdRect.right;
8294 dpyinfo->grabbed = 0;
8295 dpyinfo->root_window = NULL;
8297 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8298 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8299 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8300 dpyinfo->mouse_face_window = Qnil;
8303 struct mac_display_info *
8304 mac_term_init (display_name, xrm_option, resource_name)
8305 Lisp_Object display_name;
8306 char *xrm_option;
8307 char *resource_name;
8309 struct mac_display_info *dpyinfo;
8310 GDHandle main_device_handle;
8312 if (!mac_initialized)
8314 mac_initialize ();
8315 mac_initialized = 1;
8318 mac_initialize_display_info (display_name);
8320 dpyinfo = &one_mac_display_info;
8322 main_device_handle = LMGetMainDevice();
8324 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8325 dpyinfo->width = (**main_device_handle).gdRect.right;
8327 return dpyinfo;
8330 #ifdef MAC_OSX
8331 void
8332 mac_check_bundle()
8334 extern int inhibit_window_system;
8335 extern int noninteractive;
8336 CFBundleRef appsBundle;
8337 pid_t child;
8339 /* No need to test if already -nw*/
8340 if (inhibit_window_system || noninteractive)
8341 return;
8343 appsBundle = CFBundleGetMainBundle();
8344 if (appsBundle != NULL)
8346 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
8347 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
8348 /* We found the bundle identifier, now we know we are valid. */
8349 if (res != NULL)
8351 CFRelease(res);
8352 return;
8355 /* MAC_TODO: Have this start the bundled executable */
8357 /* For now, prevent the fatal error by bringing it up in the terminal */
8358 inhibit_window_system = 1;
8361 void
8362 MakeMeTheFrontProcess ()
8364 ProcessSerialNumber psn;
8365 OSErr err;
8367 err = GetCurrentProcess (&psn);
8368 if (err == noErr)
8369 (void) SetFrontProcess (&psn);
8372 /***** Code to handle C-g testing *****/
8374 /* Contains the Mac modifier formed from quit_char */
8375 static mac_quit_char_modifiers = 0;
8376 static mac_quit_char_keycode;
8377 extern int quit_char;
8379 static void
8380 mac_determine_quit_char_modifiers()
8382 /* Todo: Determine modifiers from quit_char. */
8383 UInt32 qc_modifiers = ctrl_modifier;
8385 /* Map modifiers */
8386 mac_quit_char_modifiers = 0;
8387 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
8388 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
8389 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
8390 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
8393 static void
8394 init_quit_char_handler ()
8396 /* TODO: Let this support keys other the 'g' */
8397 mac_quit_char_keycode = 5;
8398 /* Look at <architecture/adb_kb_map.h> for details */
8399 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
8401 mac_determine_quit_char_modifiers();
8404 static Boolean
8405 quit_char_comp (EventRef inEvent, void *inCompData)
8407 if (GetEventClass(inEvent) != kEventClassKeyboard)
8408 return false;
8409 if (GetEventKind(inEvent) != kEventRawKeyDown)
8410 return false;
8412 UInt32 keyCode;
8413 UInt32 keyModifiers;
8414 GetEventParameter(inEvent, kEventParamKeyCode,
8415 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
8416 if (keyCode != mac_quit_char_keycode)
8417 return false;
8418 GetEventParameter(inEvent, kEventParamKeyModifiers,
8419 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
8420 if (keyModifiers != mac_quit_char_modifiers)
8421 return false;
8423 return true;
8426 void
8427 mac_check_for_quit_char ()
8429 EventRef event;
8430 static EMACS_TIME last_check_time = { 0, 0 };
8431 static EMACS_TIME one_second = { 1, 0 };
8432 EMACS_TIME now, t;
8434 /* If windows are not initialized, return immediately (keep it bouncin'). */
8435 if (!mac_quit_char_modifiers)
8436 return;
8438 /* Don't check if last check is less than a second ago. */
8439 EMACS_GET_TIME (now);
8440 EMACS_SUB_TIME (t, now, last_check_time);
8441 if (EMACS_TIME_LT (t, one_second))
8442 return;
8443 last_check_time = now;
8445 /* Redetermine modifiers because they are based on lisp variables */
8446 mac_determine_quit_char_modifiers ();
8448 /* Fill the queue with events */
8449 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
8450 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
8451 NULL);
8452 if (event)
8454 struct input_event e;
8455 struct mac_output *mwp =
8456 (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
8457 /* Use an input_event to emulate what the interrupt handler does. */
8458 EVENT_INIT (e);
8459 e.kind = ASCII_KEYSTROKE_EVENT;
8460 e.code = quit_char;
8461 e.arg = NULL;
8462 e.modifiers = NULL;
8463 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
8464 XSETFRAME (e.frame_or_window, mwp->mFP);
8465 /* Remove event from queue to prevent looping. */
8466 RemoveEventFromQueue (GetMainEventQueue (), event);
8467 ReleaseEvent (event);
8468 kbd_buffer_store_event (&e);
8472 #endif /* MAC_OSX */
8474 /* Set up use of X before we make the first connection. */
8476 extern frame_parm_handler mac_frame_parm_handlers[];
8478 static struct redisplay_interface x_redisplay_interface =
8480 mac_frame_parm_handlers,
8481 x_produce_glyphs,
8482 x_write_glyphs,
8483 x_insert_glyphs,
8484 x_clear_end_of_line,
8485 x_scroll_run,
8486 x_after_update_window_line,
8487 x_update_window_begin,
8488 x_update_window_end,
8489 x_cursor_to,
8490 x_flush,
8491 x_flush,
8492 x_clear_window_mouse_face,
8493 x_get_glyph_overhangs,
8494 x_fix_overlapping_area,
8495 x_draw_fringe_bitmap,
8496 mac_per_char_metric,
8497 mac_encode_char,
8498 NULL, /* mac_compute_glyph_string_overhangs */
8499 x_draw_glyph_string,
8500 mac_define_frame_cursor,
8501 mac_clear_frame_area,
8502 mac_draw_window_cursor,
8503 mac_draw_vertical_window_border,
8504 mac_shift_glyphs_for_insert
8507 void
8508 mac_initialize ()
8510 rif = &x_redisplay_interface;
8512 clear_frame_hook = x_clear_frame;
8513 ins_del_lines_hook = x_ins_del_lines;
8514 delete_glyphs_hook = x_delete_glyphs;
8515 ring_bell_hook = XTring_bell;
8516 reset_terminal_modes_hook = XTreset_terminal_modes;
8517 set_terminal_modes_hook = XTset_terminal_modes;
8518 update_begin_hook = x_update_begin;
8519 update_end_hook = x_update_end;
8520 set_terminal_window_hook = XTset_terminal_window;
8521 read_socket_hook = XTread_socket;
8522 frame_up_to_date_hook = XTframe_up_to_date;
8523 mouse_position_hook = XTmouse_position;
8524 frame_rehighlight_hook = XTframe_rehighlight;
8525 frame_raise_lower_hook = XTframe_raise_lower;
8527 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
8528 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
8529 redeem_scroll_bar_hook = XTredeem_scroll_bar;
8530 judge_scroll_bars_hook = XTjudge_scroll_bars;
8532 scroll_region_ok = 1; /* we'll scroll partial frames */
8533 char_ins_del_ok = 1;
8534 line_ins_del_ok = 1; /* we'll just blt 'em */
8535 fast_clear_end_of_line = 1; /* X does this well */
8536 memory_below_frame = 0; /* we don't remember what scrolls
8537 off the bottom */
8538 baud_rate = 19200;
8540 x_noop_count = 0;
8541 last_tool_bar_item = -1;
8542 any_help_event_p = 0;
8544 /* Try to use interrupt input; if we can't, then start polling. */
8545 Fset_input_mode (Qt, Qnil, Qt, Qnil);
8547 #ifdef USE_X_TOOLKIT
8548 XtToolkitInitialize ();
8549 Xt_app_con = XtCreateApplicationContext ();
8550 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
8552 /* Install an asynchronous timer that processes Xt timeout events
8553 every 0.1s. This is necessary because some widget sets use
8554 timeouts internally, for example the LessTif menu bar, or the
8555 Xaw3d scroll bar. When Xt timouts aren't processed, these
8556 widgets don't behave normally. */
8558 EMACS_TIME interval;
8559 EMACS_SET_SECS_USECS (interval, 0, 100000);
8560 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
8562 #endif
8564 #if USE_TOOLKIT_SCROLL_BARS
8565 xaw3d_arrow_scroll = False;
8566 xaw3d_pick_top = True;
8567 #endif
8569 #if 0
8570 /* Note that there is no real way portable across R3/R4 to get the
8571 original error handler. */
8572 XSetErrorHandler (x_error_handler);
8573 XSetIOErrorHandler (x_io_error_quitter);
8575 /* Disable Window Change signals; they are handled by X events. */
8576 #ifdef SIGWINCH
8577 signal (SIGWINCH, SIG_DFL);
8578 #endif /* ! defined (SIGWINCH) */
8580 signal (SIGPIPE, x_connection_signal);
8581 #endif
8583 mac_initialize_display_info ();
8585 #if TARGET_API_MAC_CARBON
8586 init_required_apple_events ();
8588 init_mac_drag_n_drop ();
8590 #if USE_CARBON_EVENTS
8591 init_service_handler ();
8593 init_quit_char_handler ();
8594 #endif
8596 DisableMenuCommand (NULL, kHICommandQuit);
8598 if (!inhibit_window_system)
8599 MakeMeTheFrontProcess ();
8600 #endif
8604 void
8605 syms_of_macterm ()
8607 #if 0
8608 staticpro (&x_error_message_string);
8609 x_error_message_string = Qnil;
8610 #endif
8612 Fprovide (intern ("mac-carbon"), Qnil);
8614 staticpro (&x_display_name_list);
8615 x_display_name_list = Qnil;
8617 staticpro (&last_mouse_scroll_bar);
8618 last_mouse_scroll_bar = Qnil;
8620 staticpro (&Qvendor_specific_keysyms);
8621 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
8623 staticpro (&last_mouse_press_frame);
8624 last_mouse_press_frame = Qnil;
8626 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
8627 staticpro (&Qmac_ready_for_drag_n_drop);
8629 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
8630 doc: /* *Non-nil means autoselect window with mouse pointer. */);
8631 x_autoselect_window_p = 0;
8633 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
8634 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
8635 Vx_toolkit_scroll_bars = Qt;
8637 DEFVAR_BOOL ("x-use-underline-position-properties",
8638 &x_use_underline_position_properties,
8639 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
8640 nil means ignore them. If you encounter fonts with bogus
8641 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
8642 to 4.1, set this to nil. */);
8643 x_use_underline_position_properties = 0;
8645 staticpro (&last_mouse_motion_frame);
8646 last_mouse_motion_frame = Qnil;
8648 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
8649 doc: /* Non-nil means that the command key is used as the Emacs meta key.
8650 Otherwise the option key is used. */);
8651 Vmac_command_key_is_meta = Qt;
8653 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
8654 doc: /* Non-nil means that the control and meta keys are reversed. This is
8655 useful for non-standard keyboard layouts. */);
8656 Vmac_reverse_ctrl_meta = Qnil;
8658 #if USE_CARBON_EVENTS
8659 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
8660 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
8661 the right click will be mouse-3.
8662 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
8663 Vmac_wheel_button_is_mouse_2 = Qt;
8665 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
8666 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
8667 Toolbox for processing before Emacs sees it. */);
8668 Vmac_pass_command_to_system = Qt;
8670 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
8671 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
8672 Toolbox for processing before Emacs sees it. */);
8673 Vmac_pass_control_to_system = Qt;
8674 #endif
8676 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
8677 doc: /* One of the Text Encoding Base constant values defined in the
8678 Basic Text Constants section of Inside Macintosh - Text Encoding
8679 Conversion Manager. Its value determines the encoding characters
8680 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
8681 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
8682 its default value, no conversion takes place. If it is set to
8683 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
8684 characters typed on Mac keyboard are first converted into the
8685 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
8686 passed to Emacs. Together with Emacs's set-keyboard-coding-system
8687 command, this enables the Mac keyboard to be used to enter non-ASCII
8688 characters directly. */);
8689 mac_keyboard_text_encoding = kTextEncodingMacRoman;
8692 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
8693 (do not change this comment) */