1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
71 #include <sys/param.h>
76 #include "dispextern.h"
78 #include "termhooks.h"
86 #include "intervals.h"
89 #include "character.h"
92 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
93 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
95 #define macShiftKey (shiftKey)
96 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
97 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
99 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
102 /* Non-nil means Emacs uses toolkit scroll bars. */
104 Lisp_Object Vx_toolkit_scroll_bars
;
106 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
107 Lisp_Object Vmac_use_core_graphics
;
110 /* Non-zero means that a HELP_EVENT has been generated since Emacs
113 static int any_help_event_p
;
115 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
116 static Lisp_Object last_window
;
118 /* This is a chain of structures for all the X displays currently in
121 struct x_display_info
*x_display_list
;
123 /* This is a list of cons cells, each of the form (NAME
124 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
125 x_display_list and in the same order. NAME is the name of the
126 frame. FONT-LIST-CACHE records previous values returned by
127 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
128 equivalent, which is implemented with a Lisp object, for the
131 Lisp_Object x_display_name_list
;
133 /* This is display since Mac does not support multiple ones. */
134 struct mac_display_info one_mac_display_info
;
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the XT functions.
138 It is zero while not inside an update. In that case, the XT
139 functions assume that `selected_frame' is the frame to apply to. */
141 extern struct frame
*updating_frame
;
143 /* This is a frame waiting to be auto-raised, within XTread_socket. */
145 struct frame
*pending_autoraise_frame
;
149 Formerly, we used PointerMotionHintMask (in standard_event_mask)
150 so that we would have to call XQueryPointer after each MotionNotify
151 event to ask for another such event. However, this made mouse tracking
152 slow, and there was a bug that made it eventually stop.
154 Simply asking for MotionNotify all the time seems to work better.
156 In order to avoid asking for motion events and then throwing most
157 of them away or busy-polling the server for mouse positions, we ask
158 the server for pointer motion hints. This means that we get only
159 one event per group of mouse movements. "Groups" are delimited by
160 other kinds of events (focus changes and button clicks, for
161 example), or by XQueryPointer calls; when one of these happens, we
162 get another MotionNotify event the next time the mouse moves. This
163 is at least as efficient as getting motion events when mouse
164 tracking is on, and I suspect only negligibly worse when tracking
167 /* Where the mouse was last time we reported a mouse event. */
169 static Rect last_mouse_glyph
;
171 /* The scroll bar in which the last X motion event occurred.
173 If the last X motion event occurred in a scroll bar, we set this so
174 XTmouse_position can know whether to report a scroll bar motion or
177 If the last X motion event didn't occur in a scroll bar, we set
178 this to Qnil, to tell XTmouse_position to return an ordinary motion
181 static Lisp_Object last_mouse_scroll_bar
;
183 /* This is a hack. We would really prefer that XTmouse_position would
184 return the time associated with the position it returns, but there
185 doesn't seem to be any way to wrest the time-stamp from the server
186 along with the position query. So, we just keep track of the time
187 of the last movement we received, and return that in hopes that
188 it's somewhat accurate. */
190 static Time last_mouse_movement_time
;
192 struct scroll_bar
*tracked_scroll_bar
= NULL
;
194 /* Incremented by XTread_socket whenever it really tries to read
198 static int volatile input_signal_count
;
200 static int input_signal_count
;
203 extern Lisp_Object Vsystem_name
;
205 /* A mask of extra modifier bits to put into every keyboard char. */
207 extern EMACS_INT extra_keyboard_modifiers
;
209 /* The keysyms to use for the various modifiers. */
211 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
213 extern int inhibit_window_system
;
215 #if __MRC__ && !TARGET_API_MAC_CARBON
216 QDGlobals qd
; /* QuickDraw global information structure. */
219 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
221 struct mac_display_info
*mac_display_info_for_display (Display
*);
222 static void x_update_window_end
P_ ((struct window
*, int, int));
223 static int x_io_error_quitter
P_ ((Display
*));
224 int x_catch_errors
P_ ((Display
*));
225 void x_uncatch_errors
P_ ((Display
*, int));
226 void x_lower_frame
P_ ((struct frame
*));
227 void x_scroll_bar_clear
P_ ((struct frame
*));
228 int x_had_errors_p
P_ ((Display
*));
229 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
230 void x_raise_frame
P_ ((struct frame
*));
231 void x_set_window_size
P_ ((struct frame
*, int, int, int));
232 void x_wm_set_window_state
P_ ((struct frame
*, int));
233 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
234 void mac_initialize
P_ ((void));
235 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
236 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
237 static void x_update_end
P_ ((struct frame
*));
238 static void XTframe_up_to_date
P_ ((struct frame
*));
239 static void XTset_terminal_modes
P_ ((void));
240 static void XTreset_terminal_modes
P_ ((void));
241 static void x_clear_frame
P_ ((void));
242 static void frame_highlight
P_ ((struct frame
*));
243 static void frame_unhighlight
P_ ((struct frame
*));
244 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
245 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
246 struct frame
*, struct input_event
*));
247 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
248 EventRecord
*, struct input_event
*));
249 static void XTframe_rehighlight
P_ ((struct frame
*));
250 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
251 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
252 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
253 enum text_cursor_kinds
));
255 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
256 static void x_flush
P_ ((struct frame
*f
));
257 static void x_update_begin
P_ ((struct frame
*));
258 static void x_update_window_begin
P_ ((struct window
*));
259 static void x_after_update_window_line
P_ ((struct glyph_row
*));
260 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
261 enum scroll_bar_part
*,
262 Lisp_Object
*, Lisp_Object
*,
265 static int is_emacs_window
P_ ((WindowPtr
));
267 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
269 /* Defined in macmenu.h. */
270 extern void menubar_selection_callback (FRAME_PTR
, int);
272 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
273 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
274 #define GC_FONT(gc) ((gc)->xgcv.font)
275 #define MAC_WINDOW_NORMAL_GC(w) (((mac_output *) GetWRefCon (w))->normal_gc)
278 /* X display function emulation */
281 XFreePixmap (display
, pixmap
)
282 Display
*display
; /* not used */
285 DisposeGWorld (pixmap
);
289 /* Mac version of XDrawLine. */
292 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
298 SetPortWindowPort (w
);
300 RGBForeColor (GC_FORE_COLOR (gc
));
307 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
316 GetGWorld (&old_port
, &old_gdh
);
319 RGBForeColor (GC_FORE_COLOR (gc
));
321 LockPixels (GetGWorldPixMap (p
));
324 UnlockPixels (GetGWorldPixMap (p
));
326 SetGWorld (old_port
, old_gdh
);
331 mac_erase_rectangle (w
, gc
, x
, y
, width
, height
)
335 unsigned int width
, height
;
339 SetPortWindowPort (w
);
341 RGBBackColor (GC_BACK_COLOR (gc
));
342 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
346 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
350 /* Mac version of XClearArea. */
353 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
357 unsigned int width
, height
;
360 mac_erase_rectangle (w
, MAC_WINDOW_NORMAL_GC (w
), x
, y
, width
, height
);
363 /* Mac version of XClearWindow. */
366 XClearWindow (display
, w
)
370 SetPortWindowPort (w
);
372 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
374 #if TARGET_API_MAC_CARBON
378 GetWindowPortBounds (w
, &r
);
381 #else /* not TARGET_API_MAC_CARBON */
382 EraseRect (&(w
->portRect
));
383 #endif /* not TARGET_API_MAC_CARBON */
387 /* Mac replacement for XCopyArea. */
390 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
394 int x
, y
, width
, height
;
395 unsigned short *bits
;
401 bitmap
.rowBytes
= sizeof(unsigned short);
402 bitmap
.baseAddr
= (char *)bits
;
403 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
405 SetPortWindowPort (w
);
407 RGBForeColor (GC_FORE_COLOR (gc
));
408 RGBBackColor (GC_BACK_COLOR (gc
));
409 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
411 #if TARGET_API_MAC_CARBON
412 LockPortBits (GetWindowPort (w
));
413 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
414 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
415 UnlockPortBits (GetWindowPort (w
));
416 #else /* not TARGET_API_MAC_CARBON */
417 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
418 overlay_p
? srcOr
: srcCopy
, 0);
419 #endif /* not TARGET_API_MAC_CARBON */
421 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
425 /* Mac replacement for XSetClipRectangles. */
428 mac_set_clip_rectangle (display
, w
, r
)
433 SetPortWindowPort (w
);
439 /* Mac replacement for XSetClipMask. */
442 mac_reset_clipping (display
, w
)
448 SetPortWindowPort (w
);
450 SetRect (&r
, -32767, -32767, 32767, 32767);
455 /* Mac replacement for XCreateBitmapFromBitmapData. */
458 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
463 static unsigned char swap_nibble
[16]
464 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
465 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
466 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
467 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
471 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
472 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
473 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
474 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
475 for (i
= 0; i
< h
; i
++)
477 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
478 for (j
= 0; j
< w1
; j
++)
480 /* Bitswap XBM bytes to match how Mac does things. */
481 unsigned char c
= *bits
++;
482 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
483 | (swap_nibble
[(c
>>4) & 0xf]));;
487 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
492 mac_free_bitmap (bitmap
)
495 xfree (bitmap
->baseAddr
);
500 XCreatePixmap (display
, w
, width
, height
, depth
)
501 Display
*display
; /* not used */
503 unsigned int width
, height
;
510 SetPortWindowPort (w
);
512 SetRect (&r
, 0, 0, width
, height
);
513 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
521 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
522 Display
*display
; /* not used */
525 unsigned int width
, height
;
526 unsigned long fg
, bg
;
533 static GC gc
= NULL
; /* not reentrant */
536 gc
= XCreateGC (display
, w
, 0, NULL
);
538 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
542 GetGWorld (&old_port
, &old_gdh
);
543 SetGWorld (pixmap
, NULL
);
544 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
545 XSetForeground (display
, gc
, fg
);
546 XSetBackground (display
, gc
, bg
);
547 RGBForeColor (GC_FORE_COLOR (gc
));
548 RGBBackColor (GC_BACK_COLOR (gc
));
549 LockPixels (GetGWorldPixMap (pixmap
));
550 #if TARGET_API_MAC_CARBON
551 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
552 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
553 #else /* not TARGET_API_MAC_CARBON */
554 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
555 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
556 #endif /* not TARGET_API_MAC_CARBON */
557 UnlockPixels (GetGWorldPixMap (pixmap
));
558 SetGWorld (old_port
, old_gdh
);
559 mac_free_bitmap (&bitmap
);
565 /* Mac replacement for XFillRectangle. */
568 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
573 unsigned int width
, height
;
577 SetPortWindowPort (w
);
579 RGBForeColor (GC_FORE_COLOR (gc
));
580 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
582 PaintRect (&r
); /* using foreground color of gc */
586 #if 0 /* TODO: figure out if we need to do this on Mac. */
588 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
593 unsigned int width
, height
;
599 GetGWorld (&old_port
, &old_gdh
);
601 RGBForeColor (GC_FORE_COLOR (gc
));
602 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
604 LockPixels (GetGWorldPixMap (p
));
605 PaintRect (&r
); /* using foreground color of gc */
606 UnlockPixels (GetGWorldPixMap (p
));
608 SetGWorld (old_port
, old_gdh
);
613 /* Mac replacement for XDrawRectangle: dest is a window. */
616 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
621 unsigned int width
, height
;
625 SetPortWindowPort (w
);
627 RGBForeColor (GC_FORE_COLOR (gc
));
628 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
630 FrameRect (&r
); /* using foreground color of gc */
634 #if 0 /* TODO: figure out if we need to do this on Mac. */
635 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
638 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
643 unsigned int width
, height
;
649 GetGWorld (&old_port
, &old_gdh
);
651 RGBForeColor (GC_FORE_COLOR (gc
));
652 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
654 LockPixels (GetGWorldPixMap (p
));
655 FrameRect (&r
); /* using foreground color of gc */
656 UnlockPixels (GetGWorldPixMap (p
));
658 SetGWorld (old_port
, old_gdh
);
664 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
671 int nchars
, mode
, bytes_per_char
;
673 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
674 UInt32 textFlags
, savedFlags
;
675 if (!NILP(Vmac_use_core_graphics
)) {
676 textFlags
= kQDUseCGTextRendering
;
677 savedFlags
= SwapQDTextFlags(textFlags
);
681 SetPortWindowPort (w
);
683 RGBForeColor (GC_FORE_COLOR (gc
));
685 RGBBackColor (GC_BACK_COLOR (gc
));
687 TextFont (GC_FONT (gc
)->mac_fontnum
);
688 TextSize (GC_FONT (gc
)->mac_fontsize
);
689 TextFace (GC_FONT (gc
)->mac_fontface
);
693 DrawText (buf
, 0, nchars
* bytes_per_char
);
696 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
697 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
698 if (!NILP(Vmac_use_core_graphics
))
699 SwapQDTextFlags(savedFlags
);
704 /* Mac replacement for XDrawString. */
707 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
715 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
719 /* Mac replacement for XDrawString16. */
722 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
730 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
735 /* Mac replacement for XDrawImageString. */
738 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
746 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
750 /* Mac replacement for XDrawString16. */
753 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
761 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
766 /* Mac replacement for XCopyArea: dest must be window. */
769 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
776 unsigned int width
, height
;
781 SetPortWindowPort (dest
);
783 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
784 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
786 ForeColor (blackColor
);
787 BackColor (whiteColor
);
789 LockPixels (GetGWorldPixMap (src
));
790 #if TARGET_API_MAC_CARBON
791 LockPortBits (GetWindowPort (dest
));
792 CopyBits (GetPortBitMapForCopyBits (src
),
793 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
794 &src_r
, &dest_r
, srcCopy
, 0);
795 UnlockPortBits (GetWindowPort (dest
));
796 #else /* not TARGET_API_MAC_CARBON */
797 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
798 &src_r
, &dest_r
, srcCopy
, 0);
799 #endif /* not TARGET_API_MAC_CARBON */
800 UnlockPixels (GetGWorldPixMap (src
));
802 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest
)));
807 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
808 width
, height
, dest_x
, dest_y
)
814 unsigned int width
, height
;
819 SetPortWindowPort (dest
);
821 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
822 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
824 ForeColor (blackColor
);
825 BackColor (whiteColor
);
827 LockPixels (GetGWorldPixMap (src
));
828 LockPixels (GetGWorldPixMap (mask
));
829 #if TARGET_API_MAC_CARBON
830 LockPortBits (GetWindowPort (dest
));
831 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
832 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
833 &src_r
, &src_r
, &dest_r
);
834 UnlockPortBits (GetWindowPort (dest
));
835 #else /* not TARGET_API_MAC_CARBON */
836 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
837 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
838 #endif /* not TARGET_API_MAC_CARBON */
839 UnlockPixels (GetGWorldPixMap (mask
));
840 UnlockPixels (GetGWorldPixMap (src
));
842 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest
)));
846 /* Mac replacement for XCopyArea: used only for scrolling. */
849 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
854 unsigned int width
, height
;
857 #if TARGET_API_MAC_CARBON
859 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
861 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
862 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
863 kScrollWindowNoOptions
, dummy
);
865 #else /* not TARGET_API_MAC_CARBON */
870 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
871 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
873 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
874 color mapping in CopyBits. Otherwise, it will be slow. */
875 ForeColor (blackColor
);
876 BackColor (whiteColor
);
877 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
879 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
880 #endif /* not TARGET_API_MAC_CARBON */
884 #if 0 /* TODO: figure out if we need to do this on Mac. */
885 /* Mac replacement for XCopyArea: dest must be Pixmap. */
888 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
894 unsigned int width
, height
;
901 GetGWorld (&old_port
, &old_gdh
);
902 SetGWorld (dest
, NULL
);
903 ForeColor (blackColor
);
904 BackColor (whiteColor
);
906 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
907 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
909 LockPixels (GetGWorldPixMap (src
));
910 LockPixels (GetGWorldPixMap (dest
));
911 #if TARGET_API_MAC_CARBON
912 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
913 &src_r
, &dest_r
, srcCopy
, 0);
914 #else /* not TARGET_API_MAC_CARBON */
915 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
916 &src_r
, &dest_r
, srcCopy
, 0);
917 #endif /* not TARGET_API_MAC_CARBON */
918 UnlockPixels (GetGWorldPixMap (dest
));
919 UnlockPixels (GetGWorldPixMap (src
));
921 SetGWorld (old_port
, old_gdh
);
926 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
927 width
, height
, dest_x
, dest_y
)
929 Pixmap src
, mask
, dest
;
932 unsigned int width
, height
;
939 GetGWorld (&old_port
, &old_gdh
);
940 SetGWorld (dest
, NULL
);
941 ForeColor (blackColor
);
942 BackColor (whiteColor
);
944 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
945 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
947 LockPixels (GetGWorldPixMap (src
));
948 LockPixels (GetGWorldPixMap (mask
));
949 LockPixels (GetGWorldPixMap (dest
));
950 #if TARGET_API_MAC_CARBON
951 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
952 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
953 #else /* not TARGET_API_MAC_CARBON */
954 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
955 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
956 #endif /* not TARGET_API_MAC_CARBON */
957 UnlockPixels (GetGWorldPixMap (dest
));
958 UnlockPixels (GetGWorldPixMap (mask
));
959 UnlockPixels (GetGWorldPixMap (src
));
961 SetGWorld (old_port
, old_gdh
);
966 /* Mac replacement for XChangeGC. */
969 XChangeGC (display
, gc
, mask
, xgcv
)
975 if (mask
& GCForeground
)
976 XSetForeground (display
, gc
, xgcv
->foreground
);
977 if (mask
& GCBackground
)
978 XSetBackground (display
, gc
, xgcv
->background
);
980 XSetFont (display
, gc
, xgcv
->font
);
984 /* Mac replacement for XCreateGC. */
987 XCreateGC (display
, window
, mask
, xgcv
)
993 GC gc
= xmalloc (sizeof (*gc
));
997 bzero (gc
, sizeof (*gc
));
998 XChangeGC (display
, gc
, mask
, xgcv
);
1005 /* Used in xfaces.c. */
1008 XFreeGC (display
, gc
)
1016 /* Mac replacement for XGetGCValues. */
1019 XGetGCValues (display
, gc
, mask
, xgcv
)
1025 if (mask
& GCForeground
)
1026 xgcv
->foreground
= gc
->xgcv
.foreground
;
1027 if (mask
& GCBackground
)
1028 xgcv
->background
= gc
->xgcv
.background
;
1030 xgcv
->font
= gc
->xgcv
.font
;
1034 /* Mac replacement for XSetForeground. */
1037 XSetForeground (display
, gc
, color
)
1040 unsigned long color
;
1042 if (gc
->xgcv
.foreground
!= color
)
1044 gc
->xgcv
.foreground
= color
;
1045 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1046 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1047 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1052 /* Mac replacement for XSetBackground. */
1055 XSetBackground (display
, gc
, color
)
1058 unsigned long color
;
1060 if (gc
->xgcv
.background
!= color
)
1062 gc
->xgcv
.background
= color
;
1063 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1064 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1065 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1070 /* Mac replacement for XSetFont. */
1073 XSetFont (display
, gc
, font
)
1078 gc
->xgcv
.font
= font
;
1082 /* Mac replacement for XSetWindowBackground. */
1085 XSetWindowBackground (display
, w
, color
)
1088 unsigned long color
;
1090 #if !TARGET_API_MAC_CARBON
1091 AuxWinHandle aw_handle
;
1092 CTabHandle ctab_handle
;
1093 ColorSpecPtr ct_table
;
1098 bg_color
.red
= RED16_FROM_ULONG (color
);
1099 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1100 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1102 #if TARGET_API_MAC_CARBON
1103 SetWindowContentColor (w
, &bg_color
);
1105 if (GetAuxWin (w
, &aw_handle
))
1107 ctab_handle
= (*aw_handle
)->awCTable
;
1108 HandToHand ((Handle
*) &ctab_handle
);
1109 ct_table
= (*ctab_handle
)->ctTable
;
1110 ct_size
= (*ctab_handle
)->ctSize
;
1111 while (ct_size
> -1)
1113 if (ct_table
->value
== 0)
1115 ct_table
->rgb
= bg_color
;
1116 CTabChanged (ctab_handle
);
1117 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1125 /* x_sync is a no-op on Mac. */
1133 /* Flush display of frame F, or of all frames if F is null. */
1139 #if TARGET_API_MAC_CARBON
1142 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1144 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1150 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1151 Calls to XFlush should be unnecessary because the X output buffer
1152 is flushed automatically as needed by calls to XPending,
1153 XNextEvent, or XWindowEvent according to the XFlush man page.
1154 XTread_socket calls XPending. Removing XFlush improves
1157 #define XFlush(DISPLAY) (void) 0
1160 /* Return the struct mac_display_info corresponding to DPY. There's
1163 struct mac_display_info
*
1164 mac_display_info_for_display (dpy
)
1167 return &one_mac_display_info
;
1172 /***********************************************************************
1173 Starting and ending an update
1174 ***********************************************************************/
1176 /* Start an update of frame F. This function is installed as a hook
1177 for update_begin, i.e. it is called when update_begin is called.
1178 This function is called prior to calls to x_update_window_begin for
1179 each window being updated. */
1185 #if TARGET_API_MAC_CARBON
1186 /* During update of a frame, availability of input events is
1187 periodically checked with ReceiveNextEvent if
1188 redisplay-dont-pause is nil. That normally flushes window buffer
1189 changes for every check, and thus screen update looks waving even
1190 if no input is available. So we disable screen updates during
1191 update of a frame. */
1193 DisableScreenUpdates ();
1199 /* Start update of window W. Set the global variable updated_window
1200 to the window being updated and set output_cursor to the cursor
1204 x_update_window_begin (w
)
1207 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1208 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1211 set_output_cursor (&w
->cursor
);
1215 if (f
== display_info
->mouse_face_mouse_frame
)
1217 /* Don't do highlighting for mouse motion during the update. */
1218 display_info
->mouse_face_defer
= 1;
1220 /* If F needs to be redrawn, simply forget about any prior mouse
1222 if (FRAME_GARBAGED_P (f
))
1223 display_info
->mouse_face_window
= Qnil
;
1225 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1226 their mouse_face_p flag set, which means that they are always
1227 unequal to rows in a desired matrix which never have that
1228 flag set. So, rows containing mouse-face glyphs are never
1229 scrolled, and we don't have to switch the mouse highlight off
1230 here to prevent it from being scrolled. */
1232 /* Can we tell that this update does not affect the window
1233 where the mouse highlight is? If so, no need to turn off.
1234 Likewise, don't do anything if the frame is garbaged;
1235 in that case, the frame's current matrix that we would use
1236 is all wrong, and we will redisplay that line anyway. */
1237 if (!NILP (display_info
->mouse_face_window
)
1238 && w
== XWINDOW (display_info
->mouse_face_window
))
1242 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1243 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1246 if (i
< w
->desired_matrix
->nrows
)
1247 clear_mouse_face (display_info
);
1256 /* Draw a vertical window border from (x,y0) to (x,y1) */
1259 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1263 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1266 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1268 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1271 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1272 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1275 /* End update of window W (which is equal to updated_window).
1277 Draw vertical borders between horizontally adjacent windows, and
1278 display W's cursor if CURSOR_ON_P is non-zero.
1280 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1281 glyphs in mouse-face were overwritten. In that case we have to
1282 make sure that the mouse-highlight is properly redrawn.
1284 W may be a menu bar pseudo-window in case we don't have X toolkit
1285 support. Such windows don't have a cursor, so don't display it
1289 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1291 int cursor_on_p
, mouse_face_overwritten_p
;
1293 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1295 if (!w
->pseudo_window_p
)
1300 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1302 output_cursor
.x
, output_cursor
.y
);
1304 if (draw_window_fringes (w
, 1))
1305 x_draw_vertical_border (w
);
1310 /* If a row with mouse-face was overwritten, arrange for
1311 XTframe_up_to_date to redisplay the mouse highlight. */
1312 if (mouse_face_overwritten_p
)
1314 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1315 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1316 dpyinfo
->mouse_face_window
= Qnil
;
1319 updated_window
= NULL
;
1323 /* End update of frame F. This function is installed as a hook in
1330 /* Mouse highlight may be displayed again. */
1331 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1334 #if TARGET_API_MAC_CARBON
1335 EnableScreenUpdates ();
1337 XFlush (FRAME_MAC_DISPLAY (f
));
1342 /* This function is called from various places in xdisp.c whenever a
1343 complete update has been performed. The global variable
1344 updated_window is not available here. */
1347 XTframe_up_to_date (f
)
1350 if (FRAME_MAC_P (f
))
1352 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1354 if (dpyinfo
->mouse_face_deferred_gc
1355 || f
== dpyinfo
->mouse_face_mouse_frame
)
1358 if (dpyinfo
->mouse_face_mouse_frame
)
1359 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1360 dpyinfo
->mouse_face_mouse_x
,
1361 dpyinfo
->mouse_face_mouse_y
);
1362 dpyinfo
->mouse_face_deferred_gc
= 0;
1369 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1370 arrow bitmaps, or clear the fringes if no bitmaps are required
1371 before DESIRED_ROW is made current. The window being updated is
1372 found in updated_window. This function is called from
1373 update_window_line only if it is known that there are differences
1374 between bitmaps to be drawn between current row and DESIRED_ROW. */
1377 x_after_update_window_line (desired_row
)
1378 struct glyph_row
*desired_row
;
1380 struct window
*w
= updated_window
;
1386 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1387 desired_row
->redraw_fringe_bitmaps_p
= 1;
1389 /* When a window has disappeared, make sure that no rest of
1390 full-width rows stays visible in the internal border. Could
1391 check here if updated_window is the leftmost/rightmost window,
1392 but I guess it's not worth doing since vertically split windows
1393 are almost never used, internal border is rarely set, and the
1394 overhead is very small. */
1395 if (windows_or_buffers_changed
1396 && desired_row
->full_width_p
1397 && (f
= XFRAME (w
->frame
),
1398 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1400 && (height
= desired_row
->visible_height
,
1403 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1405 /* Internal border is drawn below the tool bar. */
1406 if (WINDOWP (f
->tool_bar_window
)
1407 && w
== XWINDOW (f
->tool_bar_window
))
1411 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1412 0, y
, width
, height
, 0);
1413 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1414 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1421 /* Draw the bitmap WHICH in one of the left or right fringes of
1422 window W. ROW is the glyph row for which to display the bitmap; it
1423 determines the vertical position at which the bitmap has to be
1427 x_draw_fringe_bitmap (w
, row
, p
)
1429 struct glyph_row
*row
;
1430 struct draw_fringe_bitmap_params
*p
;
1432 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1433 Display
*display
= FRAME_MAC_DISPLAY (f
);
1434 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1435 GC gc
= f
->output_data
.mac
->normal_gc
;
1436 struct face
*face
= p
->face
;
1439 /* Must clip because of partially visible lines. */
1440 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1443 /* Adjust position of "bottom aligned" bitmap on partially
1444 visible last row. */
1446 int oldVH
= row
->visible_height
;
1447 row
->visible_height
= p
->h
;
1448 row
->y
-= rowY
- p
->y
;
1449 x_clip_to_row (w
, row
, -1, gc
);
1451 row
->visible_height
= oldVH
;
1454 x_clip_to_row (w
, row
, -1, gc
);
1456 if (p
->bx
>= 0 && !p
->overlay_p
)
1458 #if 0 /* MAC_TODO: stipple */
1459 /* In case the same realized face is used for fringes and
1460 for something displayed in the text (e.g. face `region' on
1461 mono-displays, the fill style may have been changed to
1462 FillSolid in x_draw_glyph_string_background. */
1464 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1466 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1469 mac_erase_rectangle (window
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1471 #if 0 /* MAC_TODO: stipple */
1473 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1479 unsigned short *bits
= p
->bits
+ p
->dh
;
1482 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1483 XSetForeground (display
, face
->gc
,
1485 ? (p
->overlay_p
? face
->background
1486 : f
->output_data
.mac
->cursor_pixel
)
1487 : face
->foreground
));
1488 mac_draw_bitmap (display
, window
, face
->gc
, p
->x
, p
->y
,
1489 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1490 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1493 mac_reset_clipping (display
, window
);
1498 /* This is called when starting Emacs and when restarting after
1499 suspend. When starting Emacs, no window is mapped. And nothing
1500 must be done to Emacs's own window if it is suspended (though that
1504 XTset_terminal_modes ()
1508 /* This is called when exiting or suspending Emacs. Exiting will make
1509 the windows go away, and suspending requires no action. */
1512 XTreset_terminal_modes ()
1518 /***********************************************************************
1520 ***********************************************************************/
1522 /* Function prototypes of this page. */
1524 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1525 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*,
1526 struct charset
*, int *));
1529 /* Return a pointer to per-char metric information in FONT of a
1530 character pointed by B which is a pointer to an XChar2b. */
1532 #define PER_CHAR_METRIC(font, b) \
1534 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1535 + (((font)->min_byte1 || (font)->max_byte1) \
1536 ? (((b)->byte1 - (font)->min_byte1) \
1537 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1539 : &((font)->max_bounds))
1542 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1543 is not contained in the font. */
1545 static INLINE XCharStruct
*
1546 x_per_char_metric (font
, char2b
)
1550 /* The result metric information. */
1551 XCharStruct
*pcm
= NULL
;
1553 xassert (font
&& char2b
);
1555 if (font
->per_char
!= NULL
)
1557 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1559 /* min_char_or_byte2 specifies the linear character index
1560 corresponding to the first element of the per_char array,
1561 max_char_or_byte2 is the index of the last character. A
1562 character with non-zero CHAR2B->byte1 is not in the font.
1563 A character with byte2 less than min_char_or_byte2 or
1564 greater max_char_or_byte2 is not in the font. */
1565 if (char2b
->byte1
== 0
1566 && char2b
->byte2
>= font
->min_char_or_byte2
1567 && char2b
->byte2
<= font
->max_char_or_byte2
)
1568 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1572 /* If either min_byte1 or max_byte1 are nonzero, both
1573 min_char_or_byte2 and max_char_or_byte2 are less than
1574 256, and the 2-byte character index values corresponding
1575 to the per_char array element N (counting from 0) are:
1577 byte1 = N/D + min_byte1
1578 byte2 = N\D + min_char_or_byte2
1582 D = max_char_or_byte2 - min_char_or_byte2 + 1
1583 / = integer division
1584 \ = integer modulus */
1585 if (char2b
->byte1
>= font
->min_byte1
1586 && char2b
->byte1
<= font
->max_byte1
1587 && char2b
->byte2
>= font
->min_char_or_byte2
1588 && char2b
->byte2
<= font
->max_char_or_byte2
)
1590 pcm
= (font
->per_char
1591 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1592 * (char2b
->byte1
- font
->min_byte1
))
1593 + (char2b
->byte2
- font
->min_char_or_byte2
));
1599 /* If the per_char pointer is null, all glyphs between the first
1600 and last character indexes inclusive have the same
1601 information, as given by both min_bounds and max_bounds. */
1602 if (char2b
->byte2
>= font
->min_char_or_byte2
1603 && char2b
->byte2
<= font
->max_char_or_byte2
)
1604 pcm
= &font
->max_bounds
;
1607 return ((pcm
== NULL
1608 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1615 static XCharStruct
*
1616 mac_per_char_metric (font
, char2b
, font_type
)
1621 return x_per_char_metric (font
, char2b
);
1625 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1626 the two-byte form of C. Encoding is returned in *CHAR2B. */
1629 mac_encode_char (c
, char2b
, font_info
, charset
, two_byte_p
)
1632 struct font_info
*font_info
;
1633 struct charset
*charset
;
1636 XFontStruct
*font
= font_info
->font
;
1638 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1639 This may be either a program in a special encoder language or a
1641 if (font_info
->font_encoder
)
1643 /* It's a program. */
1644 struct ccl_program
*ccl
= font_info
->font_encoder
;
1646 check_ccl_update (ccl
);
1647 if (CHARSET_DIMENSION (charset
) == 1)
1649 ccl
->reg
[0] = CHARSET_ID (charset
);
1650 ccl
->reg
[1] = XCHAR2B_BYTE2 (char2b
);
1655 ccl
->reg
[0] = CHARSET_ID (charset
);
1656 ccl
->reg
[1] = XCHAR2B_BYTE1 (char2b
);
1657 ccl
->reg
[2] = XCHAR2B_BYTE2 (char2b
);
1660 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1662 /* We assume that MSBs are appropriately set/reset by CCL
1664 if (font
->max_byte1
== 0) /* 1-byte font */
1665 STORE_XCHAR2B (char2b
, 0, ccl
->reg
[1]);
1667 STORE_XCHAR2B (char2b
, ccl
->reg
[1], ccl
->reg
[2]);
1669 else if (font_info
->encoding_type
)
1671 /* Fixed encoding scheme. See fontset.h for the meaning of the
1672 encoding numbers. */
1673 unsigned char enc
= font_info
->encoding_type
;
1675 if ((enc
== 1 || enc
== 2)
1676 && CHARSET_DIMENSION (charset
) == 2)
1677 char2b
->byte1
|= 0x80;
1679 if (enc
== 1 || enc
== 3)
1680 char2b
->byte2
|= 0x80;
1687 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1688 char2b->byte1 = sjis1;
1689 char2b->byte2 = sjis2;
1695 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1697 return FONT_TYPE_UNKNOWN
;
1702 /***********************************************************************
1704 ***********************************************************************/
1708 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1709 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1710 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1712 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1713 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1714 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1715 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1716 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
1717 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1718 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1719 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1720 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1721 unsigned long *, double, int));*/
1722 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1723 double, int, unsigned long));
1724 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1725 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1726 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1727 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1728 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1729 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1731 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1732 int, int, int, int, int, int,
1734 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1735 int, int, int, Rect
*));
1738 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1742 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1747 struct glyph_string
*s
;
1749 if (s
->font
== FRAME_FONT (s
->f
)
1750 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1751 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1753 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1756 /* Cursor on non-default face: must merge. */
1760 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1761 xgcv
.foreground
= s
->face
->background
;
1763 /* If the glyph would be invisible, try a different foreground. */
1764 if (xgcv
.foreground
== xgcv
.background
)
1765 xgcv
.foreground
= s
->face
->foreground
;
1766 if (xgcv
.foreground
== xgcv
.background
)
1767 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1768 if (xgcv
.foreground
== xgcv
.background
)
1769 xgcv
.foreground
= s
->face
->foreground
;
1771 /* Make sure the cursor is distinct from text in this face. */
1772 if (xgcv
.background
== s
->face
->background
1773 && xgcv
.foreground
== s
->face
->foreground
)
1775 xgcv
.background
= s
->face
->foreground
;
1776 xgcv
.foreground
= s
->face
->background
;
1779 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1780 xgcv
.font
= s
->font
;
1781 mask
= GCForeground
| GCBackground
| GCFont
;
1783 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1784 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1787 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1788 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1790 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1795 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1798 x_set_mouse_face_gc (s
)
1799 struct glyph_string
*s
;
1804 /* What face has to be used last for the mouse face? */
1805 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1806 face
= FACE_FROM_ID (s
->f
, face_id
);
1808 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1810 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1811 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
, -1, Qnil
);
1813 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0, -1, Qnil
);
1814 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1815 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1817 /* If font in this face is same as S->font, use it. */
1818 if (s
->font
== s
->face
->font
)
1819 s
->gc
= s
->face
->gc
;
1822 /* Otherwise construct scratch_cursor_gc with values from FACE
1827 xgcv
.background
= s
->face
->background
;
1828 xgcv
.foreground
= s
->face
->foreground
;
1829 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1830 xgcv
.font
= s
->font
;
1831 mask
= GCForeground
| GCBackground
| GCFont
;
1833 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1834 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1837 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1838 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1840 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1843 xassert (s
->gc
!= 0);
1847 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1848 Faces to use in the mode line have already been computed when the
1849 matrix was built, so there isn't much to do, here. */
1852 x_set_mode_line_face_gc (s
)
1853 struct glyph_string
*s
;
1855 s
->gc
= s
->face
->gc
;
1859 /* Set S->gc of glyph string S for drawing that glyph string. Set
1860 S->stippled_p to a non-zero value if the face of S has a stipple
1864 x_set_glyph_string_gc (s
)
1865 struct glyph_string
*s
;
1867 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1869 if (s
->hl
== DRAW_NORMAL_TEXT
)
1871 s
->gc
= s
->face
->gc
;
1872 s
->stippled_p
= s
->face
->stipple
!= 0;
1874 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1876 x_set_mode_line_face_gc (s
);
1877 s
->stippled_p
= s
->face
->stipple
!= 0;
1879 else if (s
->hl
== DRAW_CURSOR
)
1881 x_set_cursor_gc (s
);
1884 else if (s
->hl
== DRAW_MOUSE_FACE
)
1886 x_set_mouse_face_gc (s
);
1887 s
->stippled_p
= s
->face
->stipple
!= 0;
1889 else if (s
->hl
== DRAW_IMAGE_RAISED
1890 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1892 s
->gc
= s
->face
->gc
;
1893 s
->stippled_p
= s
->face
->stipple
!= 0;
1897 s
->gc
= s
->face
->gc
;
1898 s
->stippled_p
= s
->face
->stipple
!= 0;
1901 /* GC must have been set. */
1902 xassert (s
->gc
!= 0);
1906 /* Set clipping for output of glyph string S. S may be part of a mode
1907 line or menu if we don't have X toolkit support. */
1910 x_set_glyph_string_clipping (s
)
1911 struct glyph_string
*s
;
1914 get_glyph_string_clip_rect (s
, &r
);
1915 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1920 Compute left and right overhang of glyph string S. If S is a glyph
1921 string for a composition, assume overhangs don't exist. */
1924 mac_compute_glyph_string_overhangs (s
)
1925 struct glyph_string
*s
;
1928 && s
->first_glyph
->type
== CHAR_GLYPH
)
1931 MacFontStruct
*font
= s
->font
;
1933 TextFont (font
->mac_fontnum
);
1934 TextSize (font
->mac_fontsize
);
1935 TextFace (font
->mac_fontface
);
1938 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
1942 char *buf
= xmalloc (s
->nchars
);
1945 SetRect (&r
, 0, 0, 0, 0);
1948 for (i
= 0; i
< s
->nchars
; ++i
)
1949 buf
[i
] = s
->char2b
[i
].byte2
;
1950 QDTextBounds (s
->nchars
, buf
, &r
);
1955 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
1956 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
1961 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1964 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1965 struct glyph_string
*s
;
1968 mac_erase_rectangle (s
->window
, s
->gc
, x
, y
, w
, h
);
1972 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
1973 on Mac OS X because:
1974 - Screen is double-buffered. (In srcCopy mode, a text is drawn
1975 into an offscreen graphics world first. So performance gain
1976 cannot be expected.)
1977 - It lowers rendering quality.
1978 - Some fonts leave garbage on cursor movement. */
1980 /* Draw the background of glyph_string S. If S->background_filled_p
1981 is non-zero don't draw it. FORCE_P non-zero means draw the
1982 background even if it wouldn't be drawn normally. This is used
1983 when a string preceding S draws into the background of S, or S
1984 contains the first component of a composition. */
1987 x_draw_glyph_string_background (s
, force_p
)
1988 struct glyph_string
*s
;
1991 /* Nothing to do if background has already been drawn or if it
1992 shouldn't be drawn in the first place. */
1993 if (!s
->background_filled_p
)
1995 int box_line_width
= max (s
->face
->box_line_width
, 0);
1997 #if 0 /* MAC_TODO: stipple */
2000 /* Fill background with a stipple pattern. */
2001 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2002 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2003 s
->y
+ box_line_width
,
2004 s
->background_width
,
2005 s
->height
- 2 * box_line_width
);
2006 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2007 s
->background_filled_p
= 1;
2012 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2013 || s
->font_not_found_p
2014 || s
->extends_to_end_of_line_p
2018 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2019 s
->background_width
,
2020 s
->height
- 2 * box_line_width
);
2021 s
->background_filled_p
= 1;
2027 /* Draw the foreground of glyph string S. */
2030 x_draw_glyph_string_foreground (s
)
2031 struct glyph_string
*s
;
2035 /* If first glyph of S has a left box line, start drawing the text
2036 of S to the right of that box line. */
2037 if (s
->face
->box
!= FACE_NO_BOX
2038 && s
->first_glyph
->left_box_line_p
)
2039 x
= s
->x
+ abs (s
->face
->box_line_width
);
2043 /* Draw characters of S as rectangles if S's font could not be
2045 if (s
->font_not_found_p
)
2047 for (i
= 0; i
< s
->nchars
; ++i
)
2049 struct glyph
*g
= s
->first_glyph
+ i
;
2050 mac_draw_rectangle (s
->display
, s
->window
,
2051 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2053 x
+= g
->pixel_width
;
2058 char *char1b
= (char *) s
->char2b
;
2059 int boff
= s
->font_info
->baseline_offset
;
2061 if (s
->font_info
->vertical_centering
)
2062 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2064 /* If we can use 8-bit functions, condense S->char2b. */
2066 for (i
= 0; i
< s
->nchars
; ++i
)
2067 char1b
[i
] = s
->char2b
[i
].byte2
;
2070 /* Draw text with XDrawString if background has already been
2071 filled. Otherwise, use XDrawImageString. (Note that
2072 XDrawImageString is usually faster than XDrawString.) Always
2073 use XDrawImageString when drawing the cursor so that there is
2074 no chance that characters under a box cursor are invisible. */
2075 if (s
->for_overlaps_p
2076 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2079 /* Draw characters with 16-bit or 8-bit functions. */
2081 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2082 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2084 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2085 s
->ybase
- boff
, char1b
, s
->nchars
);
2091 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2092 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2094 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2095 s
->ybase
- boff
, char1b
, s
->nchars
);
2101 /* Draw the foreground of composite glyph string S. */
2104 x_draw_composite_glyph_string_foreground (s
)
2105 struct glyph_string
*s
;
2109 /* If first glyph of S has a left box line, start drawing the text
2110 of S to the right of that box line. */
2111 if (s
->face
->box
!= FACE_NO_BOX
2112 && s
->first_glyph
->left_box_line_p
)
2113 x
= s
->x
+ abs (s
->face
->box_line_width
);
2117 /* S is a glyph string for a composition. S->gidx is the index of
2118 the first character drawn for glyphs of this composition.
2119 S->gidx == 0 means we are drawing the very first character of
2120 this composition. */
2122 /* Draw a rectangle for the composition if the font for the very
2123 first character of the composition could not be loaded. */
2124 if (s
->font_not_found_p
)
2127 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2128 s
->width
- 1, s
->height
- 1);
2132 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2133 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2134 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2135 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2141 #ifdef USE_X_TOOLKIT
2143 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2146 /* Return the frame on which widget WIDGET is used.. Abort if frame
2147 cannot be determined. */
2149 static struct frame
*
2150 x_frame_of_widget (widget
)
2153 struct x_display_info
*dpyinfo
;
2157 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2159 /* Find the top-level shell of the widget. Note that this function
2160 can be called when the widget is not yet realized, so XtWindow
2161 (widget) == 0. That's the reason we can't simply use
2162 x_any_window_to_frame. */
2163 while (!XtIsTopLevelShell (widget
))
2164 widget
= XtParent (widget
);
2166 /* Look for a frame with that top-level widget. Allocate the color
2167 on that frame to get the right gamma correction value. */
2168 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2169 if (GC_FRAMEP (XCAR (tail
))
2170 && (f
= XFRAME (XCAR (tail
)),
2171 (f
->output_data
.nothing
!= 1
2172 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2173 && f
->output_data
.x
->widget
== widget
)
2180 /* Allocate the color COLOR->pixel on the screen and display of
2181 widget WIDGET in colormap CMAP. If an exact match cannot be
2182 allocated, try the nearest color available. Value is non-zero
2183 if successful. This is called from lwlib. */
2186 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2191 struct frame
*f
= x_frame_of_widget (widget
);
2192 return x_alloc_nearest_color (f
, cmap
, color
);
2196 #endif /* USE_X_TOOLKIT */
2198 #if 0 /* MAC_TODO */
2200 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2201 CMAP. If an exact match can't be allocated, try the nearest color
2202 available. Value is non-zero if successful. Set *COLOR to the
2206 x_alloc_nearest_color (f
, cmap
, color
)
2211 Display
*display
= FRAME_X_DISPLAY (f
);
2212 Screen
*screen
= FRAME_X_SCREEN (f
);
2215 gamma_correct (f
, color
);
2216 rc
= XAllocColor (display
, cmap
, color
);
2219 /* If we got to this point, the colormap is full, so we're going
2220 to try to get the next closest color. The algorithm used is
2221 a least-squares matching, which is what X uses for closest
2222 color matching with StaticColor visuals. */
2224 unsigned long nearest_delta
= ~0;
2225 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2226 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2228 for (i
= 0; i
< ncells
; ++i
)
2230 XQueryColors (display
, cmap
, cells
, ncells
);
2232 for (nearest
= i
= 0; i
< ncells
; ++i
)
2234 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2235 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2236 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2237 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2239 if (delta
< nearest_delta
)
2242 nearest_delta
= delta
;
2246 color
->red
= cells
[nearest
].red
;
2247 color
->green
= cells
[nearest
].green
;
2248 color
->blue
= cells
[nearest
].blue
;
2249 rc
= XAllocColor (display
, cmap
, color
);
2252 #ifdef DEBUG_X_COLORS
2254 register_color (color
->pixel
);
2255 #endif /* DEBUG_X_COLORS */
2261 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2262 It's necessary to do this instead of just using PIXEL directly to
2263 get color reference counts right. */
2266 x_copy_color (f
, pixel
)
2268 unsigned long pixel
;
2272 color
.pixel
= pixel
;
2274 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2275 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2277 #ifdef DEBUG_X_COLORS
2278 register_color (pixel
);
2284 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2285 It's necessary to do this instead of just using PIXEL directly to
2286 get color reference counts right. */
2289 x_copy_dpy_color (dpy
, cmap
, pixel
)
2292 unsigned long pixel
;
2296 color
.pixel
= pixel
;
2298 XQueryColor (dpy
, cmap
, &color
);
2299 XAllocColor (dpy
, cmap
, &color
);
2301 #ifdef DEBUG_X_COLORS
2302 register_color (pixel
);
2307 #endif /* MAC_TODO */
2310 /* Brightness beyond which a color won't have its highlight brightness
2313 Nominally, highlight colors for `3d' faces are calculated by
2314 brightening an object's color by a constant scale factor, but this
2315 doesn't yield good results for dark colors, so for colors who's
2316 brightness is less than this value (on a scale of 0-255) have to
2317 use an additional additive factor.
2319 The value here is set so that the default menu-bar/mode-line color
2320 (grey75) will not have its highlights changed at all. */
2321 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2324 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2325 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2326 If this produces the same color as COLOR, try a color where all RGB
2327 values have DELTA added. Return the allocated color in *COLOR.
2328 DISPLAY is the X display, CMAP is the colormap to operate on.
2329 Value is non-zero if successful. */
2332 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2334 unsigned long *color
;
2341 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2344 /* Change RGB values by specified FACTOR. Avoid overflow! */
2345 xassert (factor
>= 0);
2346 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2347 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2348 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2350 /* Calculate brightness of COLOR. */
2351 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2352 + BLUE_FROM_ULONG (*color
)) / 6;
2354 /* We only boost colors that are darker than
2355 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2356 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2357 /* Make an additive adjustment to NEW, because it's dark enough so
2358 that scaling by FACTOR alone isn't enough. */
2360 /* How far below the limit this color is (0 - 1, 1 being darker). */
2361 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2362 /* The additive adjustment. */
2363 int min_delta
= delta
* dimness
* factor
/ 2;
2366 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2367 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2368 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2370 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2371 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2372 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2376 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2377 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2378 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2380 /* MAC_TODO: Map to palette and retry with delta if same? */
2381 /* MAC_TODO: Free colors (if using palette)? */
2392 /* Set up the foreground color for drawing relief lines of glyph
2393 string S. RELIEF is a pointer to a struct relief containing the GC
2394 with which lines will be drawn. Use a color that is FACTOR or
2395 DELTA lighter or darker than the relief's background which is found
2396 in S->f->output_data.x->relief_background. If such a color cannot
2397 be allocated, use DEFAULT_PIXEL, instead. */
2400 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2402 struct relief
*relief
;
2405 unsigned long default_pixel
;
2408 struct mac_output
*di
= f
->output_data
.mac
;
2409 unsigned long mask
= GCForeground
;
2410 unsigned long pixel
;
2411 unsigned long background
= di
->relief_background
;
2412 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2414 /* MAC_TODO: Free colors (if using palette)? */
2416 /* Allocate new color. */
2417 xgcv
.foreground
= default_pixel
;
2419 if (dpyinfo
->n_planes
!= 1
2420 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2422 relief
->allocated_p
= 1;
2423 xgcv
.foreground
= relief
->pixel
= pixel
;
2426 if (relief
->gc
== 0)
2428 #if 0 /* MAC_TODO: stipple */
2429 xgcv
.stipple
= dpyinfo
->gray
;
2432 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2435 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2439 /* Set up colors for the relief lines around glyph string S. */
2442 x_setup_relief_colors (s
)
2443 struct glyph_string
*s
;
2445 struct mac_output
*di
= s
->f
->output_data
.mac
;
2446 unsigned long color
;
2448 if (s
->face
->use_box_color_for_shadows_p
)
2449 color
= s
->face
->box_color
;
2450 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2452 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2453 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2458 /* Get the background color of the face. */
2459 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2460 color
= xgcv
.background
;
2463 if (di
->white_relief
.gc
== 0
2464 || color
!= di
->relief_background
)
2466 di
->relief_background
= color
;
2467 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2468 WHITE_PIX_DEFAULT (s
->f
));
2469 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2470 BLACK_PIX_DEFAULT (s
->f
));
2475 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2476 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2477 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2478 relief. LEFT_P non-zero means draw a relief on the left side of
2479 the rectangle. RIGHT_P non-zero means draw a relief on the right
2480 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2484 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2485 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2487 int left_x
, top_y
, right_x
, bottom_y
, width
;
2488 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2491 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2492 Window window
= FRAME_MAC_WINDOW (f
);
2497 gc
= f
->output_data
.mac
->white_relief
.gc
;
2499 gc
= f
->output_data
.mac
->black_relief
.gc
;
2500 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2504 for (i
= 0; i
< width
; ++i
)
2505 XDrawLine (dpy
, window
, gc
,
2506 left_x
+ i
* left_p
, top_y
+ i
,
2507 right_x
- i
* right_p
, top_y
+ i
);
2511 for (i
= 0; i
< width
; ++i
)
2512 XDrawLine (dpy
, window
, gc
,
2513 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2515 mac_reset_clipping (dpy
, window
);
2517 gc
= f
->output_data
.mac
->black_relief
.gc
;
2519 gc
= f
->output_data
.mac
->white_relief
.gc
;
2520 mac_set_clip_rectangle (dpy
, window
,
2525 for (i
= 0; i
< width
; ++i
)
2526 XDrawLine (dpy
, window
, gc
,
2527 left_x
+ i
* left_p
, bottom_y
- i
,
2528 right_x
- i
* right_p
, bottom_y
- i
);
2532 for (i
= 0; i
< width
; ++i
)
2533 XDrawLine (dpy
, window
, gc
,
2534 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2536 mac_reset_clipping (dpy
, window
);
2540 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2541 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2542 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2543 left side of the rectangle. RIGHT_P non-zero means draw a line
2544 on the right side of the rectangle. CLIP_RECT is the clipping
2545 rectangle to use when drawing. */
2548 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2549 left_p
, right_p
, clip_rect
)
2550 struct glyph_string
*s
;
2551 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2556 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2557 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2558 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2561 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2562 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2566 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2567 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2570 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2571 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2575 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2576 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2578 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2579 mac_reset_clipping (s
->display
, s
->window
);
2583 /* Draw a box around glyph string S. */
2586 x_draw_glyph_string_box (s
)
2587 struct glyph_string
*s
;
2589 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2590 int left_p
, right_p
;
2591 struct glyph
*last_glyph
;
2594 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2595 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2596 : window_box_right (s
->w
, s
->area
));
2598 /* The glyph that may have a right box line. */
2599 last_glyph
= (s
->cmp
|| s
->img
2601 : s
->first_glyph
+ s
->nchars
- 1);
2603 width
= abs (s
->face
->box_line_width
);
2604 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2606 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2608 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2610 bottom_y
= top_y
+ s
->height
- 1;
2612 left_p
= (s
->first_glyph
->left_box_line_p
2613 || (s
->hl
== DRAW_MOUSE_FACE
2615 || s
->prev
->hl
!= s
->hl
)));
2616 right_p
= (last_glyph
->right_box_line_p
2617 || (s
->hl
== DRAW_MOUSE_FACE
2619 || s
->next
->hl
!= s
->hl
)));
2621 get_glyph_string_clip_rect (s
, &clip_rect
);
2623 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2624 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2625 left_p
, right_p
, &clip_rect
);
2628 x_setup_relief_colors (s
);
2629 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2630 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2635 /* Draw foreground of image glyph string S. */
2638 x_draw_image_foreground (s
)
2639 struct glyph_string
*s
;
2642 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2644 /* If first glyph of S has a left box line, start drawing it to the
2645 right of that line. */
2646 if (s
->face
->box
!= FACE_NO_BOX
2647 && s
->first_glyph
->left_box_line_p
2649 x
+= abs (s
->face
->box_line_width
);
2651 /* If there is a margin around the image, adjust x- and y-position
2653 if (s
->slice
.x
== 0)
2654 x
+= s
->img
->hmargin
;
2655 if (s
->slice
.y
== 0)
2656 y
+= s
->img
->vmargin
;
2660 x_set_glyph_string_clipping (s
);
2663 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2664 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2665 s
->slice
.width
, s
->slice
.height
, x
, y
);
2668 mac_copy_area (s
->display
, s
->img
->pixmap
,
2669 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2670 s
->slice
.width
, s
->slice
.height
, x
, y
);
2672 /* When the image has a mask, we can expect that at
2673 least part of a mouse highlight or a block cursor will
2674 be visible. If the image doesn't have a mask, make
2675 a block cursor visible by drawing a rectangle around
2676 the image. I believe it's looking better if we do
2677 nothing here for mouse-face. */
2678 if (s
->hl
== DRAW_CURSOR
)
2680 int r
= s
->img
->relief
;
2682 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2684 s
->slice
.width
+ r
*2 - 1,
2685 s
->slice
.height
+ r
*2 - 1);
2690 /* Draw a rectangle if image could not be loaded. */
2691 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2692 s
->slice
.width
- 1, s
->slice
.height
- 1);
2696 /* Draw a relief around the image glyph string S. */
2699 x_draw_image_relief (s
)
2700 struct glyph_string
*s
;
2702 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2705 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2707 /* If first glyph of S has a left box line, start drawing it to the
2708 right of that line. */
2709 if (s
->face
->box
!= FACE_NO_BOX
2710 && s
->first_glyph
->left_box_line_p
2712 x
+= abs (s
->face
->box_line_width
);
2714 /* If there is a margin around the image, adjust x- and y-position
2716 if (s
->slice
.x
== 0)
2717 x
+= s
->img
->hmargin
;
2718 if (s
->slice
.y
== 0)
2719 y
+= s
->img
->vmargin
;
2721 if (s
->hl
== DRAW_IMAGE_SUNKEN
2722 || s
->hl
== DRAW_IMAGE_RAISED
)
2724 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2725 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2729 thick
= abs (s
->img
->relief
);
2730 raised_p
= s
->img
->relief
> 0;
2735 x1
= x
+ s
->slice
.width
+ thick
- 1;
2736 y1
= y
+ s
->slice
.height
+ thick
- 1;
2738 x_setup_relief_colors (s
);
2739 get_glyph_string_clip_rect (s
, &r
);
2740 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2742 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2744 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2749 #if 0 /* TODO: figure out if we need to do this on Mac. */
2750 /* Draw the foreground of image glyph string S to PIXMAP. */
2753 x_draw_image_foreground_1 (s
, pixmap
)
2754 struct glyph_string
*s
;
2758 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2760 /* If first glyph of S has a left box line, start drawing it to the
2761 right of that line. */
2762 if (s
->face
->box
!= FACE_NO_BOX
2763 && s
->first_glyph
->left_box_line_p
2765 x
+= abs (s
->face
->box_line_width
);
2767 /* If there is a margin around the image, adjust x- and y-position
2769 if (s
->slice
.x
== 0)
2770 x
+= s
->img
->hmargin
;
2771 if (s
->slice
.y
== 0)
2772 y
+= s
->img
->vmargin
;
2777 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2778 s
->img
->mask
, pixmap
, s
->gc
,
2779 s
->slice
.x
, s
->slice
.y
,
2780 s
->slice
.width
, s
->slice
.height
,
2784 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2785 s
->slice
.x
, s
->slice
.y
,
2786 s
->slice
.width
, s
->slice
.height
,
2789 /* When the image has a mask, we can expect that at
2790 least part of a mouse highlight or a block cursor will
2791 be visible. If the image doesn't have a mask, make
2792 a block cursor visible by drawing a rectangle around
2793 the image. I believe it's looking better if we do
2794 nothing here for mouse-face. */
2795 if (s
->hl
== DRAW_CURSOR
)
2797 int r
= s
->img
->relief
;
2799 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2800 s
->slice
.width
+ r
*2 - 1,
2801 s
->slice
.height
+ r
*2 - 1);
2806 /* Draw a rectangle if image could not be loaded. */
2807 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2808 s
->slice
.width
- 1, s
->slice
.height
- 1);
2813 /* Draw part of the background of glyph string S. X, Y, W, and H
2814 give the rectangle to draw. */
2817 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2818 struct glyph_string
*s
;
2821 #if 0 /* MAC_TODO: stipple */
2824 /* Fill background with a stipple pattern. */
2825 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2826 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2827 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2830 #endif /* MAC_TODO */
2831 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2835 /* Draw image glyph string S.
2838 s->x +-------------------------
2841 | +-------------------------
2844 | | +-------------------
2850 x_draw_image_glyph_string (s
)
2851 struct glyph_string
*s
;
2854 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2855 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2859 height
= s
->height
- 2 * box_line_vwidth
;
2862 /* Fill background with face under the image. Do it only if row is
2863 taller than image or if image has a clip mask to reduce
2865 s
->stippled_p
= s
->face
->stipple
!= 0;
2866 if (height
> s
->slice
.height
2870 || s
->img
->pixmap
== 0
2871 || s
->width
!= s
->background_width
)
2874 if (s
->first_glyph
->left_box_line_p
2876 x
+= box_line_hwidth
;
2879 if (s
->slice
.y
== 0)
2880 y
+= box_line_vwidth
;
2882 #if 0 /* TODO: figure out if we need to do this on Mac. */
2885 /* Create a pixmap as large as the glyph string. Fill it
2886 with the background color. Copy the image to it, using
2887 its mask. Copy the temporary pixmap to the display. */
2888 int depth
= one_mac_display_info
.n_planes
;
2890 /* Create a pixmap as large as the glyph string. */
2891 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2892 s
->background_width
,
2895 /* Fill the pixmap with the background color/stipple. */
2896 #if 0 /* TODO: stipple */
2899 /* Fill background with a stipple pattern. */
2900 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2901 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2902 0, 0, s
->background_width
, s
->height
);
2903 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2909 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2911 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2912 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2913 0, 0, s
->background_width
,
2915 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2920 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2922 s
->background_filled_p
= 1;
2925 /* Draw the foreground. */
2926 #if 0 /* TODO: figure out if we need to do this on Mac. */
2929 x_draw_image_foreground_1 (s
, pixmap
);
2930 x_set_glyph_string_clipping (s
);
2931 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
2932 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2933 mac_reset_clipping (s
->display
, s
->window
);
2934 XFreePixmap (s
->display
, pixmap
);
2938 x_draw_image_foreground (s
);
2940 /* If we must draw a relief around the image, do it. */
2942 || s
->hl
== DRAW_IMAGE_RAISED
2943 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2944 x_draw_image_relief (s
);
2948 /* Draw stretch glyph string S. */
2951 x_draw_stretch_glyph_string (s
)
2952 struct glyph_string
*s
;
2954 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2955 s
->stippled_p
= s
->face
->stipple
!= 0;
2957 if (s
->hl
== DRAW_CURSOR
2958 && !x_stretch_cursor_p
)
2960 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2961 as wide as the stretch glyph. */
2962 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2965 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2967 /* Clear rest using the GC of the original non-cursor face. */
2968 if (width
< s
->background_width
)
2970 int x
= s
->x
+ width
, y
= s
->y
;
2971 int w
= s
->background_width
- width
, h
= s
->height
;
2975 if (s
->row
->mouse_face_p
2976 && cursor_in_mouse_face_p (s
->w
))
2978 x_set_mouse_face_gc (s
);
2984 get_glyph_string_clip_rect (s
, &r
);
2985 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2987 #if 0 /* MAC_TODO: stipple */
2988 if (s
->face
->stipple
)
2990 /* Fill background with a stipple pattern. */
2991 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2992 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2993 XSetFillStyle (s
->display
, gc
, FillSolid
);
2996 #endif /* MAC_TODO */
2997 mac_erase_rectangle (s
->window
, gc
, x
, y
, w
, h
);
2999 mac_reset_clipping (s
->display
, s
->window
);
3002 else if (!s
->background_filled_p
)
3003 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3006 s
->background_filled_p
= 1;
3010 /* Draw glyph string S. */
3013 x_draw_glyph_string (s
)
3014 struct glyph_string
*s
;
3016 int relief_drawn_p
= 0;
3018 /* If S draws into the background of its successor that does not
3019 draw a cursor, draw the background of the successor first so that
3020 S can draw into it. This makes S->next use XDrawString instead
3021 of XDrawImageString. */
3022 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
3023 && s
->next
->hl
!= DRAW_CURSOR
)
3025 xassert (s
->next
->img
== NULL
);
3026 x_set_glyph_string_gc (s
->next
);
3027 x_set_glyph_string_clipping (s
->next
);
3028 x_draw_glyph_string_background (s
->next
, 1);
3031 /* Set up S->gc, set clipping and draw S. */
3032 x_set_glyph_string_gc (s
);
3034 /* Draw relief (if any) in advance for char/composition so that the
3035 glyph string can be drawn over it. */
3036 if (!s
->for_overlaps_p
3037 && s
->face
->box
!= FACE_NO_BOX
3038 && (s
->first_glyph
->type
== CHAR_GLYPH
3039 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3042 x_set_glyph_string_clipping (s
);
3043 x_draw_glyph_string_background (s
, 1);
3044 x_draw_glyph_string_box (s
);
3045 x_set_glyph_string_clipping (s
);
3049 x_set_glyph_string_clipping (s
);
3051 switch (s
->first_glyph
->type
)
3054 x_draw_image_glyph_string (s
);
3058 x_draw_stretch_glyph_string (s
);
3062 if (s
->for_overlaps_p
)
3063 s
->background_filled_p
= 1;
3065 x_draw_glyph_string_background (s
, 0);
3066 x_draw_glyph_string_foreground (s
);
3069 case COMPOSITE_GLYPH
:
3070 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3071 s
->background_filled_p
= 1;
3073 x_draw_glyph_string_background (s
, 1);
3074 x_draw_composite_glyph_string_foreground (s
);
3081 if (!s
->for_overlaps_p
)
3083 /* Draw underline. */
3084 if (s
->face
->underline_p
)
3086 unsigned long h
= 1;
3087 unsigned long dy
= s
->height
- h
;
3089 if (s
->face
->underline_defaulted_p
)
3090 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3095 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3096 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3097 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3099 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3103 /* Draw overline. */
3104 if (s
->face
->overline_p
)
3106 unsigned long dy
= 0, h
= 1;
3108 if (s
->face
->overline_color_defaulted_p
)
3109 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3114 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3115 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3116 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3118 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3122 /* Draw strike-through. */
3123 if (s
->face
->strike_through_p
)
3125 unsigned long h
= 1;
3126 unsigned long dy
= (s
->height
- h
) / 2;
3128 if (s
->face
->strike_through_color_defaulted_p
)
3129 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3134 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3135 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3136 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3138 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3142 /* Draw relief if not yet drawn. */
3143 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3144 x_draw_glyph_string_box (s
);
3147 /* Reset clipping. */
3148 mac_reset_clipping (s
->display
, s
->window
);
3151 /* Shift display to make room for inserted glyphs. */
3154 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3156 int x
, y
, width
, height
, shift_by
;
3158 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3159 f
->output_data
.mac
->normal_gc
,
3160 x
, y
, width
, height
,
3164 /* Delete N glyphs at the nominal cursor position. Not implemented
3175 /* Clear entire frame. If updating_frame is non-null, clear that
3176 frame. Otherwise clear the selected frame. */
3186 f
= SELECTED_FRAME ();
3188 /* Clearing the frame will erase any cursor, so mark them all as no
3190 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3191 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3192 output_cursor
.x
= -1;
3194 /* We don't set the output cursor here because there will always
3195 follow an explicit cursor_to. */
3197 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3199 /* We have to clear the scroll bars, too. If we have changed
3200 colors or something like that, then they should be notified. */
3201 x_scroll_bar_clear (f
);
3203 XFlush (FRAME_MAC_DISPLAY (f
));
3209 /* Invert the middle quarter of the frame for .15 sec. */
3211 /* We use the select system call to do the waiting, so we have to make
3212 sure it's available. If it isn't, we just won't do visual bells. */
3214 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3217 /* Subtract the `struct timeval' values X and Y, storing the result in
3218 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3221 timeval_subtract (result
, x
, y
)
3222 struct timeval
*result
, x
, y
;
3224 /* Perform the carry for the later subtraction by updating y. This
3225 is safer because on some systems the tv_sec member is unsigned. */
3226 if (x
.tv_usec
< y
.tv_usec
)
3228 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3229 y
.tv_usec
-= 1000000 * nsec
;
3233 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3235 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3236 y
.tv_usec
+= 1000000 * nsec
;
3240 /* Compute the time remaining to wait. tv_usec is certainly
3242 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3243 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3245 /* Return indication of whether the result should be considered
3247 return x
.tv_sec
< y
.tv_sec
;
3259 struct timeval wakeup
;
3261 EMACS_GET_TIME (wakeup
);
3263 /* Compute time to wait until, propagating carry from usecs. */
3264 wakeup
.tv_usec
+= 150000;
3265 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3266 wakeup
.tv_usec
%= 1000000;
3268 /* Keep waiting until past the time wakeup. */
3271 struct timeval timeout
;
3273 EMACS_GET_TIME (timeout
);
3275 /* In effect, timeout = wakeup - timeout.
3276 Break if result would be negative. */
3277 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3280 /* Try to wait that long--but we might wake up sooner. */
3281 select (0, NULL
, NULL
, NULL
, &timeout
);
3290 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3293 /* Make audible bell. */
3298 struct frame
*f
= SELECTED_FRAME ();
3300 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3308 XFlush (FRAME_MAC_DISPLAY (f
));
3314 /* Specify how many text lines, from the top of the window,
3315 should be affected by insert-lines and delete-lines operations.
3316 This, and those operations, are used only within an update
3317 that is bounded by calls to x_update_begin and x_update_end. */
3320 XTset_terminal_window (n
)
3323 /* This function intentionally left blank. */
3328 /***********************************************************************
3330 ***********************************************************************/
3332 /* Perform an insert-lines or delete-lines operation, inserting N
3333 lines or deleting -N lines at vertical position VPOS. */
3336 x_ins_del_lines (vpos
, n
)
3343 /* Scroll part of the display as described by RUN. */
3346 x_scroll_run (w
, run
)
3350 struct frame
*f
= XFRAME (w
->frame
);
3351 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3353 /* Get frame-relative bounding box of the text display area of W,
3354 without mode lines. Include in this box the left and right
3356 window_box (w
, -1, &x
, &y
, &width
, &height
);
3358 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3359 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3360 bottom_y
= y
+ height
;
3364 /* Scrolling up. Make sure we don't copy part of the mode
3365 line at the bottom. */
3366 if (from_y
+ run
->height
> bottom_y
)
3367 height
= bottom_y
- from_y
;
3369 height
= run
->height
;
3373 /* Scolling down. Make sure we don't copy over the mode line.
3375 if (to_y
+ run
->height
> bottom_y
)
3376 height
= bottom_y
- to_y
;
3378 height
= run
->height
;
3383 /* Cursor off. Will be switched on again in x_update_window_end. */
3387 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3388 f
->output_data
.mac
->normal_gc
,
3398 /***********************************************************************
3400 ***********************************************************************/
3408 ControlRef root_control
;
3411 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3413 ActivateControl (root_control
);
3415 x_update_cursor (f
, 1);
3419 frame_unhighlight (f
)
3423 ControlRef root_control
;
3426 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3428 DeactivateControl (root_control
);
3430 x_update_cursor (f
, 1);
3433 /* The focus has changed. Update the frames as necessary to reflect
3434 the new situation. Note that we can't change the selected frame
3435 here, because the Lisp code we are interrupting might become confused.
3436 Each event gets marked with the frame in which it occurred, so the
3437 Lisp code can tell when the switch took place by examining the events. */
3440 x_new_focus_frame (dpyinfo
, frame
)
3441 struct x_display_info
*dpyinfo
;
3442 struct frame
*frame
;
3444 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3446 if (frame
!= dpyinfo
->x_focus_frame
)
3448 /* Set this before calling other routines, so that they see
3449 the correct value of x_focus_frame. */
3450 dpyinfo
->x_focus_frame
= frame
;
3452 if (old_focus
&& old_focus
->auto_lower
)
3453 x_lower_frame (old_focus
);
3456 selected_frame
= frame
;
3457 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3459 Fselect_window (selected_frame
->selected_window
, Qnil
);
3460 choose_minibuf_frame ();
3463 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3464 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3466 pending_autoraise_frame
= 0;
3469 x_frame_rehighlight (dpyinfo
);
3472 /* Handle FocusIn and FocusOut state changes for FRAME.
3473 If FRAME has focus and there exists more than one frame, puts
3474 a FOCUS_IN_EVENT into *BUFP. */
3477 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3479 struct mac_display_info
*dpyinfo
;
3480 struct frame
*frame
;
3481 struct input_event
*bufp
;
3483 if (type
== activeFlag
)
3485 if (dpyinfo
->x_focus_event_frame
!= frame
)
3487 x_new_focus_frame (dpyinfo
, frame
);
3488 dpyinfo
->x_focus_event_frame
= frame
;
3490 /* Don't stop displaying the initial startup message
3491 for a switch-frame event we don't need. */
3492 if (GC_NILP (Vterminal_frame
)
3493 && GC_CONSP (Vframe_list
)
3494 && !GC_NILP (XCDR (Vframe_list
)))
3496 bufp
->kind
= FOCUS_IN_EVENT
;
3497 XSETFRAME (bufp
->frame_or_window
, frame
);
3503 if (dpyinfo
->x_focus_event_frame
== frame
)
3505 dpyinfo
->x_focus_event_frame
= 0;
3506 x_new_focus_frame (dpyinfo
, 0);
3511 /* The focus may have changed. Figure out if it is a real focus change,
3512 by checking both FocusIn/Out and Enter/LeaveNotify events.
3514 Returns FOCUS_IN_EVENT event in *BUFP. */
3517 x_detect_focus_change (dpyinfo
, event
, bufp
)
3518 struct mac_display_info
*dpyinfo
;
3520 struct input_event
*bufp
;
3522 struct frame
*frame
;
3524 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3528 /* On Mac, this is only called from focus events, so no switch needed. */
3529 mac_focus_changed ((event
->modifiers
& activeFlag
),
3530 dpyinfo
, frame
, bufp
);
3534 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3537 x_mouse_leave (dpyinfo
)
3538 struct x_display_info
*dpyinfo
;
3540 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3543 /* The focus has changed, or we have redirected a frame's focus to
3544 another frame (this happens when a frame uses a surrogate
3545 mini-buffer frame). Shift the highlight as appropriate.
3547 The FRAME argument doesn't necessarily have anything to do with which
3548 frame is being highlighted or un-highlighted; we only use it to find
3549 the appropriate X display info. */
3552 XTframe_rehighlight (frame
)
3553 struct frame
*frame
;
3555 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3559 x_frame_rehighlight (dpyinfo
)
3560 struct x_display_info
*dpyinfo
;
3562 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3564 if (dpyinfo
->x_focus_frame
)
3566 dpyinfo
->x_highlight_frame
3567 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3568 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3569 : dpyinfo
->x_focus_frame
);
3570 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3572 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3573 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3577 dpyinfo
->x_highlight_frame
= 0;
3579 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3582 frame_unhighlight (old_highlight
);
3583 if (dpyinfo
->x_highlight_frame
)
3584 frame_highlight (dpyinfo
->x_highlight_frame
);
3590 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3592 #if 0 /* MAC_TODO */
3593 /* Initialize mode_switch_bit and modifier_meaning. */
3595 x_find_modifier_meanings (dpyinfo
)
3596 struct x_display_info
*dpyinfo
;
3598 int min_code
, max_code
;
3601 XModifierKeymap
*mods
;
3603 dpyinfo
->meta_mod_mask
= 0;
3604 dpyinfo
->shift_lock_mask
= 0;
3605 dpyinfo
->alt_mod_mask
= 0;
3606 dpyinfo
->super_mod_mask
= 0;
3607 dpyinfo
->hyper_mod_mask
= 0;
3610 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3612 min_code
= dpyinfo
->display
->min_keycode
;
3613 max_code
= dpyinfo
->display
->max_keycode
;
3616 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3617 min_code
, max_code
- min_code
+ 1,
3619 mods
= XGetModifierMapping (dpyinfo
->display
);
3621 /* Scan the modifier table to see which modifier bits the Meta and
3622 Alt keysyms are on. */
3624 int row
, col
; /* The row and column in the modifier table. */
3626 for (row
= 3; row
< 8; row
++)
3627 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3630 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3632 /* Zeroes are used for filler. Skip them. */
3636 /* Are any of this keycode's keysyms a meta key? */
3640 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3642 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3648 dpyinfo
->meta_mod_mask
|= (1 << row
);
3653 dpyinfo
->alt_mod_mask
|= (1 << row
);
3658 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3663 dpyinfo
->super_mod_mask
|= (1 << row
);
3667 /* Ignore this if it's not on the lock modifier. */
3668 if ((1 << row
) == LockMask
)
3669 dpyinfo
->shift_lock_mask
= LockMask
;
3677 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3678 if (! dpyinfo
->meta_mod_mask
)
3680 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3681 dpyinfo
->alt_mod_mask
= 0;
3684 /* If some keys are both alt and meta,
3685 make them just meta, not alt. */
3686 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3688 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3691 XFree ((char *) syms
);
3692 XFreeModifiermap (mods
);
3695 #endif /* MAC_TODO */
3697 /* Convert between the modifier bits X uses and the modifier bits
3701 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3702 struct x_display_info
*dpyinfo
;
3703 unsigned short state
;
3705 return (((state
& shiftKey
) ? shift_modifier
: 0)
3706 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3707 | ((state
& cmdKey
) ? meta_modifier
: 0)
3708 | ((state
& optionKey
) ? alt_modifier
: 0));
3711 #if 0 /* MAC_TODO */
3712 static unsigned short
3713 x_emacs_to_x_modifiers (dpyinfo
, state
)
3714 struct x_display_info
*dpyinfo
;
3717 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3718 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3719 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3720 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3721 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3722 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3724 #endif /* MAC_TODO */
3726 /* Convert a keysym to its name. */
3729 x_get_keysym_name (keysym
)
3736 value
= XKeysymToString (keysym
);
3747 /* Function to report a mouse movement to the mainstream Emacs code.
3748 The input handler calls this.
3750 We have received a mouse movement event, which is given in *event.
3751 If the mouse is over a different glyph than it was last time, tell
3752 the mainstream emacs code by setting mouse_moved. If not, ask for
3753 another motion event, so we can check again the next time it moves. */
3755 static Point last_mouse_motion_position
;
3756 static Lisp_Object last_mouse_motion_frame
;
3759 note_mouse_movement (frame
, pos
)
3763 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3764 #if TARGET_API_MAC_CARBON
3768 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3769 last_mouse_motion_position
= *pos
;
3770 XSETFRAME (last_mouse_motion_frame
, frame
);
3772 #if TARGET_API_MAC_CARBON
3773 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3775 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3778 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3779 /* This case corresponds to LeaveNotify in X11. */
3781 /* If we move outside the frame, then we're certainly no
3782 longer on any text in the frame. */
3783 clear_mouse_face (dpyinfo
);
3784 dpyinfo
->mouse_face_mouse_frame
= 0;
3785 if (!dpyinfo
->grabbed
)
3786 rif
->define_frame_cursor (frame
,
3787 frame
->output_data
.mac
->nontext_cursor
);
3790 /* Has the mouse moved off the glyph it was on at the last sighting? */
3791 else if (pos
->h
< last_mouse_glyph
.left
3792 || pos
->h
>= last_mouse_glyph
.right
3793 || pos
->v
< last_mouse_glyph
.top
3794 || pos
->v
>= last_mouse_glyph
.bottom
)
3796 frame
->mouse_moved
= 1;
3797 last_mouse_scroll_bar
= Qnil
;
3798 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3803 /************************************************************************
3805 ************************************************************************/
3807 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3810 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3813 redo_mouse_highlight ()
3815 if (!NILP (last_mouse_motion_frame
)
3816 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3817 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3818 last_mouse_motion_position
.h
,
3819 last_mouse_motion_position
.v
);
3823 /* Try to determine frame pixel position and size of the glyph under
3824 frame pixel coordinates X/Y on frame F . Return the position and
3825 size in *RECT. Value is non-zero if we could compute these
3829 glyph_rect (f
, x
, y
, rect
)
3836 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3840 struct window
*w
= XWINDOW (window
);
3841 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3842 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3844 for (; r
< end
&& r
->enabled_p
; ++r
)
3845 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3847 /* Found the row at y. */
3848 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3849 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3852 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3853 rect
->bottom
= rect
->top
+ r
->height
;
3857 /* x is to the left of the first glyph in the row. */
3858 /* Shouldn't this be a pixel value?
3859 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3861 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3862 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3866 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3867 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3869 /* x is on a glyph. */
3870 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3871 rect
->right
= rect
->left
+ g
->pixel_width
;
3875 /* x is to the right of the last glyph in the row. */
3876 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3877 /* Shouldn't this be a pixel value?
3878 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3880 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3885 /* The y is not on any row. */
3889 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3891 /* Record the position of the mouse in last_mouse_glyph. */
3893 remember_mouse_glyph (f1
, gx
, gy
)
3897 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3899 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3900 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3902 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3903 round down even for negative values. */
3909 /* This was the original code from XTmouse_position, but it seems
3910 to give the position of the glyph diagonally next to the one
3911 the mouse is over. */
3912 gx
= (gx
+ width
- 1) / width
* width
;
3913 gy
= (gy
+ height
- 1) / height
* height
;
3915 gx
= gx
/ width
* width
;
3916 gy
= gy
/ height
* height
;
3919 last_mouse_glyph
.left
= gx
;
3920 last_mouse_glyph
.top
= gy
;
3921 last_mouse_glyph
.right
= gx
+ width
;
3922 last_mouse_glyph
.bottom
= gy
+ height
;
3927 static struct frame
*
3928 mac_focus_frame (dpyinfo
)
3929 struct mac_display_info
*dpyinfo
;
3931 if (dpyinfo
->x_focus_frame
)
3932 return dpyinfo
->x_focus_frame
;
3934 /* Mac version may get events, such as a menu bar click, even when
3935 all the frames are invisible. In this case, we regard the
3936 event came to the selected frame. */
3937 return SELECTED_FRAME ();
3941 /* Return the current position of the mouse.
3942 *fp should be a frame which indicates which display to ask about.
3944 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3945 and *part to the frame, window, and scroll bar part that the mouse
3946 is over. Set *x and *y to the portion and whole of the mouse's
3947 position on the scroll bar.
3949 If the mouse movement started elsewhere, set *fp to the frame the
3950 mouse is on, *bar_window to nil, and *x and *y to the character cell
3953 Set *time to the server time-stamp for the time at which the mouse
3954 was at this position.
3956 Don't store anything if we don't have a valid set of values to report.
3958 This clears the mouse_moved flag, so we can wait for the next mouse
3962 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3965 Lisp_Object
*bar_window
;
3966 enum scroll_bar_part
*part
;
3968 unsigned long *time
;
3971 int ignore1
, ignore2
;
3972 struct frame
*f
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
3973 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
3974 Lisp_Object frame
, tail
;
3978 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3979 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3982 /* Clear the mouse-moved flag for every frame on this display. */
3983 FOR_EACH_FRAME (tail
, frame
)
3984 XFRAME (frame
)->mouse_moved
= 0;
3986 last_mouse_scroll_bar
= Qnil
;
3988 SetPortWindowPort (wp
);
3990 GetMouse (&mouse_pos
);
3992 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
3993 &last_mouse_glyph
, insist
);
3996 *part
= scroll_bar_handle
;
3998 XSETINT (*x
, mouse_pos
.h
);
3999 XSETINT (*y
, mouse_pos
.v
);
4000 *time
= last_mouse_movement_time
;
4007 /************************************************************************
4009 ************************************************************************/
4011 #ifdef USE_TOOLKIT_SCROLL_BARS
4013 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4014 static OSStatus install_scroll_bar_timer
P_ ((void));
4015 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4016 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4017 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4018 struct input_event
*));
4019 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4021 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4023 struct input_event
*));
4024 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4025 struct input_event
*));
4026 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4027 Point
, struct input_event
*));
4028 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4031 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4033 static int last_scroll_bar_part
;
4035 static EventLoopTimerRef scroll_bar_timer
;
4037 static int scroll_bar_timer_event_posted_p
;
4039 #define SCROLL_BAR_FIRST_DELAY 0.5
4040 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4043 scroll_bar_timer_callback (timer
, data
)
4044 EventLoopTimerRef timer
;
4047 EventRef event
= NULL
;
4050 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4051 kEventAttributeNone
, &event
);
4056 GetMouse (&mouse_pos
);
4057 LocalToGlobal (&mouse_pos
);
4058 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4059 sizeof (Point
), &mouse_pos
);
4063 UInt32 modifiers
= GetCurrentKeyModifiers ();
4065 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4066 sizeof (UInt32
), &modifiers
);
4069 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4070 kEventPriorityStandard
);
4072 scroll_bar_timer_event_posted_p
= 1;
4075 ReleaseEvent (event
);
4079 install_scroll_bar_timer ()
4081 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4083 if (scroll_bar_timer_callbackUPP
== NULL
)
4084 scroll_bar_timer_callbackUPP
=
4085 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4087 if (scroll_bar_timer
== NULL
)
4088 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4089 kEventDurationForever as delays. */
4091 InstallEventLoopTimer (GetCurrentEventLoop (),
4092 kEventDurationForever
, kEventDurationForever
,
4093 scroll_bar_timer_callbackUPP
, NULL
,
4098 set_scroll_bar_timer (delay
)
4099 EventTimerInterval delay
;
4101 if (scroll_bar_timer
== NULL
)
4102 install_scroll_bar_timer ();
4104 scroll_bar_timer_event_posted_p
= 0;
4106 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4110 control_part_code_to_scroll_bar_part (part_code
)
4111 ControlPartCode part_code
;
4115 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4116 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4117 case kControlPageUpPart
: return scroll_bar_above_handle
;
4118 case kControlPageDownPart
: return scroll_bar_below_handle
;
4119 case kControlIndicatorPart
: return scroll_bar_handle
;
4126 construct_scroll_bar_click (bar
, part
, bufp
)
4127 struct scroll_bar
*bar
;
4129 struct input_event
*bufp
;
4131 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4132 bufp
->frame_or_window
= bar
->window
;
4136 XSETINT (bufp
->x
, 0);
4137 XSETINT (bufp
->y
, 0);
4138 bufp
->modifiers
= 0;
4142 get_control_part_bounds (ch
, part_code
, rect
)
4144 ControlPartCode part_code
;
4147 RgnHandle region
= NewRgn ();
4150 err
= GetControlRegion (ch
, part_code
, region
);
4152 GetRegionBounds (region
, rect
);
4153 DisposeRgn (region
);
4159 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4160 struct scroll_bar
*bar
;
4161 ControlPartCode part_code
;
4162 struct input_event
*bufp
;
4164 int part
= control_part_code_to_scroll_bar_part (part_code
);
4169 if (part
!= scroll_bar_handle
)
4171 construct_scroll_bar_click (bar
, part
, bufp
);
4172 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4173 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4176 last_scroll_bar_part
= part
;
4177 bar
->dragging
= Qnil
;
4178 tracked_scroll_bar
= bar
;
4182 x_scroll_bar_handle_release (bar
, bufp
)
4183 struct scroll_bar
*bar
;
4184 struct input_event
*bufp
;
4186 if (last_scroll_bar_part
!= scroll_bar_handle
4187 || !GC_NILP (bar
->dragging
))
4188 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4190 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4191 set_scroll_bar_timer (kEventDurationForever
);
4193 last_scroll_bar_part
= -1;
4194 bar
->dragging
= Qnil
;
4195 tracked_scroll_bar
= NULL
;
4199 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4201 struct scroll_bar
*bar
;
4203 struct input_event
*bufp
;
4205 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4207 if (last_scroll_bar_part
== scroll_bar_handle
)
4212 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4213 kControlIndicatorPart
, &r
);
4215 if (GC_NILP (bar
->dragging
))
4216 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4218 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4219 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4220 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4225 if (top
> top_range
)
4228 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4229 XSETINT (bufp
->x
, top
);
4230 XSETINT (bufp
->y
, top_range
);
4234 ControlPartCode part_code
;
4235 int unhilite_p
= 0, part
;
4237 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4241 part
= control_part_code_to_scroll_bar_part (part_code
);
4243 switch (last_scroll_bar_part
)
4245 case scroll_bar_above_handle
:
4246 case scroll_bar_below_handle
:
4247 if (part
!= scroll_bar_above_handle
4248 && part
!= scroll_bar_below_handle
)
4252 case scroll_bar_up_arrow
:
4253 case scroll_bar_down_arrow
:
4254 if (part
!= scroll_bar_up_arrow
4255 && part
!= scroll_bar_down_arrow
)
4262 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4263 else if (part
!= last_scroll_bar_part
4264 || scroll_bar_timer_event_posted_p
)
4266 construct_scroll_bar_click (bar
, part
, bufp
);
4267 last_scroll_bar_part
= part
;
4268 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4269 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4274 /* Set the thumb size and position of scroll bar BAR. We are currently
4275 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4278 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4279 struct scroll_bar
*bar
;
4280 int portion
, position
, whole
;
4282 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4284 int value
, viewsize
, maximum
;
4286 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4287 value
= 0, viewsize
= 1, maximum
= 0;
4292 maximum
= max (0, whole
- portion
);
4297 SetControl32BitMinimum (ch
, 0);
4298 SetControl32BitMaximum (ch
, maximum
);
4299 SetControl32BitValue (ch
, value
);
4300 SetControlViewSize (ch
, viewsize
);
4305 #endif /* USE_TOOLKIT_SCROLL_BARS */
4309 /************************************************************************
4310 Scroll bars, general
4311 ************************************************************************/
4313 /* Create a scroll bar and return the scroll bar vector for it. W is
4314 the Emacs window on which to create the scroll bar. TOP, LEFT,
4315 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4318 static struct scroll_bar
*
4319 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4321 int top
, left
, width
, height
, disp_top
, disp_height
;
4323 struct frame
*f
= XFRAME (w
->frame
);
4324 struct scroll_bar
*bar
4325 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4333 r
.right
= left
+ width
;
4334 r
.bottom
= disp_top
+ disp_height
;
4336 #if TARGET_API_MAC_CARBON
4337 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4338 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4340 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4341 0, 0, 0, scrollBarProc
, (long) bar
);
4343 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4345 XSETWINDOW (bar
->window
, w
);
4346 XSETINT (bar
->top
, top
);
4347 XSETINT (bar
->left
, left
);
4348 XSETINT (bar
->width
, width
);
4349 XSETINT (bar
->height
, height
);
4350 XSETINT (bar
->start
, 0);
4351 XSETINT (bar
->end
, 0);
4352 bar
->dragging
= Qnil
;
4353 #ifdef USE_TOOLKIT_SCROLL_BARS
4354 bar
->track_top
= Qnil
;
4355 bar
->track_height
= Qnil
;
4358 /* Add bar to its frame's list of scroll bars. */
4359 bar
->next
= FRAME_SCROLL_BARS (f
);
4361 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4362 if (!NILP (bar
->next
))
4363 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4370 /* Draw BAR's handle in the proper position.
4372 If the handle is already drawn from START to END, don't bother
4373 redrawing it, unless REBUILD is non-zero; in that case, always
4374 redraw it. (REBUILD is handy for drawing the handle after expose
4377 Normally, we want to constrain the start and end of the handle to
4378 fit inside its rectangle, but if the user is dragging the scroll
4379 bar handle, we want to let them drag it down all the way, so that
4380 the bar's top is as far down as it goes; otherwise, there's no way
4381 to move to the very end of the buffer. */
4383 #ifndef USE_TOOLKIT_SCROLL_BARS
4386 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4387 struct scroll_bar
*bar
;
4391 int dragging
= ! NILP (bar
->dragging
);
4392 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4393 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4394 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4395 int length
= end
- start
;
4397 /* If the display is already accurate, do nothing. */
4399 && start
== XINT (bar
->start
)
4400 && end
== XINT (bar
->end
))
4405 /* Make sure the values are reasonable, and try to preserve the
4406 distance between start and end. */
4409 else if (start
> top_range
)
4411 end
= start
+ length
;
4415 else if (end
> top_range
&& ! dragging
)
4418 /* Store the adjusted setting in the scroll bar. */
4419 XSETINT (bar
->start
, start
);
4420 XSETINT (bar
->end
, end
);
4422 /* Clip the end position, just for display. */
4423 if (end
> top_range
)
4426 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4427 top positions, to make sure the handle is always at least that
4428 many pixels tall. */
4429 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4431 SetControlMinimum (ch
, 0);
4432 /* Don't inadvertently activate deactivated scroll bars */
4433 if (GetControlMaximum (ch
) != -1)
4434 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4436 SetControlValue (ch
, start
);
4437 #if TARGET_API_MAC_CARBON
4438 SetControlViewSize (ch
, end
- start
);
4444 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4446 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4450 x_scroll_bar_remove (bar
)
4451 struct scroll_bar
*bar
;
4453 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4457 /* Destroy the Mac scroll bar control */
4458 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4460 /* Disassociate this scroll bar from its window. */
4461 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4467 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4468 that we are displaying PORTION characters out of a total of WHOLE
4469 characters, starting at POSITION. If WINDOW has no scroll bar,
4473 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4475 int portion
, whole
, position
;
4477 struct frame
*f
= XFRAME (w
->frame
);
4478 struct scroll_bar
*bar
;
4479 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4480 int window_y
, window_height
;
4482 /* Get window dimensions. */
4483 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4485 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4486 height
= window_height
;
4488 /* Compute the left edge of the scroll bar area. */
4489 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4491 /* Compute the width of the scroll bar which might be less than
4492 the width of the area reserved for the scroll bar. */
4493 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4494 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4498 /* Compute the left edge of the scroll bar. */
4499 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4502 sb_left
= left
+ width
- sb_width
;
4504 /* Adjustments according to Inside Macintosh to make it look nice */
4506 disp_height
= height
;
4512 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4518 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4521 /* Does the scroll bar exist yet? */
4522 if (NILP (w
->vertical_scroll_bar
))
4525 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4526 left
, top
, width
, height
, 0);
4528 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4530 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4534 /* It may just need to be moved and resized. */
4537 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4538 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4542 /* If already correctly positioned, do nothing. */
4543 if (!(XINT (bar
->left
) == sb_left
4544 && XINT (bar
->top
) == top
4545 && XINT (bar
->width
) == sb_width
4546 && XINT (bar
->height
) == height
))
4548 /* Since toolkit scroll bars are smaller than the space reserved
4549 for them on the frame, we have to clear "under" them. */
4550 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4551 left
, top
, width
, height
, 0);
4554 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4555 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4556 sb_left
- 1, top
, 1, height
, 0);
4560 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4561 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4563 if (sb_width
< disp_height
)
4566 /* Remember new settings. */
4567 XSETINT (bar
->left
, sb_left
);
4568 XSETINT (bar
->top
, top
);
4569 XSETINT (bar
->width
, sb_width
);
4570 XSETINT (bar
->height
, height
);
4571 #ifdef USE_TOOLKIT_SCROLL_BARS
4572 bar
->track_top
= Qnil
;
4573 bar
->track_height
= Qnil
;
4580 #ifdef USE_TOOLKIT_SCROLL_BARS
4581 if (NILP (bar
->track_top
))
4583 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4588 SetControl32BitMinimum (ch
, 0);
4589 SetControl32BitMaximum (ch
, 1);
4590 SetControlViewSize (ch
, 1);
4592 /* Move the scroll bar thumb to the top. */
4593 SetControl32BitValue (ch
, 0);
4594 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4596 /* Move the scroll bar thumb to the bottom. */
4597 SetControl32BitValue (ch
, 1);
4598 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4600 UnionRect (&r0
, &r1
, &r0
);
4601 XSETINT (bar
->track_top
, r0
.top
);
4602 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4607 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4608 #else /* not USE_TOOLKIT_SCROLL_BARS */
4609 /* Set the scroll bar's current state, unless we're currently being
4611 if (NILP (bar
->dragging
))
4613 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4616 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4619 int start
= ((double) position
* top_range
) / whole
;
4620 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4621 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4624 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4628 /* The following three hooks are used when we're doing a thorough
4629 redisplay of the frame. We don't explicitly know which scroll bars
4630 are going to be deleted, because keeping track of when windows go
4631 away is a real pain - "Can you say set-window-configuration, boys
4632 and girls?" Instead, we just assert at the beginning of redisplay
4633 that *all* scroll bars are to be removed, and then save a scroll bar
4634 from the fiery pit when we actually redisplay its window. */
4636 /* Arrange for all scroll bars on FRAME to be removed at the next call
4637 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4638 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4641 XTcondemn_scroll_bars (frame
)
4644 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4645 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4648 bar
= FRAME_SCROLL_BARS (frame
);
4649 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4650 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4651 XSCROLL_BAR (bar
)->prev
= Qnil
;
4652 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4653 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4654 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4659 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4660 Note that WINDOW isn't necessarily condemned at all. */
4663 XTredeem_scroll_bar (window
)
4664 struct window
*window
;
4666 struct scroll_bar
*bar
;
4669 /* We can't redeem this window's scroll bar if it doesn't have one. */
4670 if (NILP (window
->vertical_scroll_bar
))
4673 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4675 /* Unlink it from the condemned list. */
4676 f
= XFRAME (WINDOW_FRAME (window
));
4677 if (NILP (bar
->prev
))
4679 /* If the prev pointer is nil, it must be the first in one of
4681 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4682 /* It's not condemned. Everything's fine. */
4684 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4685 window
->vertical_scroll_bar
))
4686 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4688 /* If its prev pointer is nil, it must be at the front of
4689 one or the other! */
4693 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4695 if (! NILP (bar
->next
))
4696 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4698 bar
->next
= FRAME_SCROLL_BARS (f
);
4700 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4701 if (! NILP (bar
->next
))
4702 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4705 /* Remove all scroll bars on FRAME that haven't been saved since the
4706 last call to `*condemn_scroll_bars_hook'. */
4709 XTjudge_scroll_bars (f
)
4712 Lisp_Object bar
, next
;
4714 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4716 /* Clear out the condemned list now so we won't try to process any
4717 more events on the hapless scroll bars. */
4718 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4720 for (; ! NILP (bar
); bar
= next
)
4722 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4724 x_scroll_bar_remove (b
);
4727 b
->next
= b
->prev
= Qnil
;
4730 /* Now there should be no references to the condemned scroll bars,
4731 and they should get garbage-collected. */
4735 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4736 is set to something other than NO_EVENT, it is enqueued.
4738 This may be called from a signal handler, so we have to ignore GC
4742 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4743 struct scroll_bar
*bar
;
4744 ControlPartCode part_code
;
4746 struct input_event
*bufp
;
4748 int win_y
, top_range
;
4750 if (! GC_WINDOWP (bar
->window
))
4753 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4754 bufp
->frame_or_window
= bar
->window
;
4757 bar
->dragging
= Qnil
;
4761 case kControlUpButtonPart
:
4762 bufp
->part
= scroll_bar_up_arrow
;
4764 case kControlDownButtonPart
:
4765 bufp
->part
= scroll_bar_down_arrow
;
4767 case kControlPageUpPart
:
4768 bufp
->part
= scroll_bar_above_handle
;
4770 case kControlPageDownPart
:
4771 bufp
->part
= scroll_bar_below_handle
;
4773 #if TARGET_API_MAC_CARBON
4776 case kControlIndicatorPart
:
4778 if (er
->what
== mouseDown
)
4779 bar
->dragging
= make_number (0);
4780 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4781 bufp
->part
= scroll_bar_handle
;
4785 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4786 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4788 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4792 if (! NILP (bar
->dragging
))
4793 win_y
-= XINT (bar
->dragging
);
4797 if (win_y
> top_range
)
4800 XSETINT (bufp
->x
, win_y
);
4801 XSETINT (bufp
->y
, top_range
);
4804 #ifndef USE_TOOLKIT_SCROLL_BARS
4806 /* Handle some mouse motion while someone is dragging the scroll bar.
4808 This may be called from a signal handler, so we have to ignore GC
4812 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4813 struct scroll_bar
*bar
;
4817 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4819 last_mouse_movement_time
= t
;
4822 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4824 /* If we're dragging the bar, display it. */
4825 if (! GC_NILP (bar
->dragging
))
4827 /* Where should the handle be now? */
4828 int new_start
= y_pos
- 24;
4830 if (new_start
!= XINT (bar
->start
))
4832 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4834 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4839 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4841 /* Return information to the user about the current position of the mouse
4842 on the scroll bar. */
4845 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4847 Lisp_Object
*bar_window
;
4848 enum scroll_bar_part
*part
;
4850 unsigned long *time
;
4852 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4853 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4854 #if TARGET_API_MAC_CARBON
4855 WindowPtr wp
= GetControlOwner (ch
);
4857 WindowPtr wp
= (*ch
)->contrlOwner
;
4860 struct frame
*f
= mac_window_to_frame (wp
);
4861 int win_y
, top_range
;
4863 SetPortWindowPort (wp
);
4865 GetMouse (&mouse_pos
);
4867 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4868 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4870 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4874 if (! NILP (bar
->dragging
))
4875 win_y
-= XINT (bar
->dragging
);
4879 if (win_y
> top_range
)
4883 *bar_window
= bar
->window
;
4885 if (! NILP (bar
->dragging
))
4886 *part
= scroll_bar_handle
;
4887 else if (win_y
< XINT (bar
->start
))
4888 *part
= scroll_bar_above_handle
;
4889 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4890 *part
= scroll_bar_handle
;
4892 *part
= scroll_bar_below_handle
;
4894 XSETINT (*x
, win_y
);
4895 XSETINT (*y
, top_range
);
4898 last_mouse_scroll_bar
= Qnil
;
4900 *time
= last_mouse_movement_time
;
4904 /* The screen has been cleared so we may have changed foreground or
4905 background colors, and the scroll bars may need to be redrawn.
4906 Clear out the scroll bars, and ask for expose events, so we can
4910 x_scroll_bar_clear (f
)
4913 XTcondemn_scroll_bars (f
);
4914 XTjudge_scroll_bars (f
);
4918 /***********************************************************************
4920 ***********************************************************************/
4922 /* Set clipping for output in glyph row ROW. W is the window in which
4923 we operate. GC is the graphics context to set clipping in.
4925 ROW may be a text row or, e.g., a mode line. Text rows must be
4926 clipped to the interior of the window dedicated to text display,
4927 mode lines must be clipped to the whole window. */
4930 x_clip_to_row (w
, row
, area
, gc
)
4932 struct glyph_row
*row
;
4936 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4938 int window_x
, window_y
, window_width
;
4940 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4942 clip_rect
.left
= window_x
;
4943 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4944 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4945 clip_rect
.right
= clip_rect
.left
+ window_width
;
4946 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4948 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4952 /* Draw a hollow box cursor on window W in glyph row ROW. */
4955 x_draw_hollow_cursor (w
, row
)
4957 struct glyph_row
*row
;
4959 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4960 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4961 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4964 struct glyph
*cursor_glyph
;
4967 /* Get the glyph the cursor is on. If we can't tell because
4968 the current matrix is invalid or such, give up. */
4969 cursor_glyph
= get_phys_cursor_glyph (w
);
4970 if (cursor_glyph
== NULL
)
4973 /* Compute frame-relative coordinates for phys cursor. */
4974 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4975 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
4976 wd
= w
->phys_cursor_width
;
4978 /* The foreground of cursor_gc is typically the same as the normal
4979 background color, which can cause the cursor box to be invisible. */
4980 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4981 if (dpyinfo
->scratch_cursor_gc
)
4982 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4984 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4985 GCForeground
, &xgcv
);
4986 gc
= dpyinfo
->scratch_cursor_gc
;
4988 /* Set clipping, draw the rectangle, and reset clipping again. */
4989 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
4990 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4991 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4995 /* Draw a bar cursor on window W in glyph row ROW.
4997 Implementation note: One would like to draw a bar cursor with an
4998 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4999 Unfortunately, I didn't find a font yet that has this property set.
5003 x_draw_bar_cursor (w
, row
, width
, kind
)
5005 struct glyph_row
*row
;
5007 enum text_cursor_kinds kind
;
5009 struct frame
*f
= XFRAME (w
->frame
);
5010 struct glyph
*cursor_glyph
;
5012 /* If cursor is out of bounds, don't draw garbage. This can happen
5013 in mini-buffer windows when switching between echo area glyphs
5015 cursor_glyph
= get_phys_cursor_glyph (w
);
5016 if (cursor_glyph
== NULL
)
5019 /* If on an image, draw like a normal cursor. That's usually better
5020 visible than drawing a bar, esp. if the image is large so that
5021 the bar might not be in the window. */
5022 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5024 struct glyph_row
*row
;
5025 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5026 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5030 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5031 Window window
= FRAME_MAC_WINDOW (f
);
5032 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5033 unsigned long mask
= GCForeground
| GCBackground
;
5034 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5037 /* If the glyph's background equals the color we normally draw
5038 the bar cursor in, the bar cursor in its normal color is
5039 invisible. Use the glyph's foreground color instead in this
5040 case, on the assumption that the glyph's colors are chosen so
5041 that the glyph is legible. */
5042 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5043 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5045 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5048 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5051 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5052 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5056 width
= FRAME_CURSOR_WIDTH (f
);
5057 width
= min (cursor_glyph
->pixel_width
, width
);
5059 w
->phys_cursor_width
= width
;
5060 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5062 if (kind
== BAR_CURSOR
)
5063 XFillRectangle (dpy
, window
, gc
,
5064 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5065 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5066 width
, row
->height
);
5068 XFillRectangle (dpy
, window
, gc
,
5069 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5070 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5071 row
->height
- width
),
5072 cursor_glyph
->pixel_width
,
5075 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5080 /* RIF: Define cursor CURSOR on frame F. */
5083 mac_define_frame_cursor (f
, cursor
)
5087 SetThemeCursor (cursor
);
5091 /* RIF: Clear area on frame F. */
5094 mac_clear_frame_area (f
, x
, y
, width
, height
)
5096 int x
, y
, width
, height
;
5098 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5099 x
, y
, width
, height
, 0);
5103 /* RIF: Draw cursor on window W. */
5106 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5108 struct glyph_row
*glyph_row
;
5110 int cursor_type
, cursor_width
;
5115 w
->phys_cursor_type
= cursor_type
;
5116 w
->phys_cursor_on_p
= 1;
5118 if (glyph_row
->exact_window_width_line_p
5119 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5121 glyph_row
->cursor_in_fringe_p
= 1;
5122 draw_fringe_bitmap (w
, glyph_row
, 0);
5125 switch (cursor_type
)
5127 case HOLLOW_BOX_CURSOR
:
5128 x_draw_hollow_cursor (w
, glyph_row
);
5131 case FILLED_BOX_CURSOR
:
5132 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5136 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5140 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5144 w
->phys_cursor_width
= 0;
5156 #if 0 /* MAC_TODO: no icon support yet. */
5158 x_bitmap_icon (f
, icon
)
5164 if (FRAME_W32_WINDOW (f
) == 0)
5168 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5169 else if (STRINGP (icon
))
5170 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5171 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5172 else if (SYMBOLP (icon
))
5176 if (EQ (icon
, intern ("application")))
5177 name
= (LPCTSTR
) IDI_APPLICATION
;
5178 else if (EQ (icon
, intern ("hand")))
5179 name
= (LPCTSTR
) IDI_HAND
;
5180 else if (EQ (icon
, intern ("question")))
5181 name
= (LPCTSTR
) IDI_QUESTION
;
5182 else if (EQ (icon
, intern ("exclamation")))
5183 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5184 else if (EQ (icon
, intern ("asterisk")))
5185 name
= (LPCTSTR
) IDI_ASTERISK
;
5186 else if (EQ (icon
, intern ("winlogo")))
5187 name
= (LPCTSTR
) IDI_WINLOGO
;
5191 hicon
= LoadIcon (NULL
, name
);
5199 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5204 #endif /* MAC_TODO */
5206 /************************************************************************
5208 ************************************************************************/
5210 /* Display Error Handling functions not used on W32. Listing them here
5211 helps diff stay in step when comparing w32term.c with xterm.c.
5213 x_error_catcher (display, error)
5214 x_catch_errors (dpy)
5215 x_catch_errors_unwind (old_val)
5216 x_check_errors (dpy, format)
5217 x_had_errors_p (dpy)
5218 x_clear_errors (dpy)
5219 x_uncatch_errors (dpy, count)
5221 x_connection_signal (signalnum)
5222 x_connection_closed (dpy, error_message)
5223 x_error_quitter (display, error)
5224 x_error_handler (display, error)
5225 x_io_error_quitter (display)
5230 /* Changing the font of the frame. */
5232 /* Give frame F the font named FONTNAME as its default font, and
5233 return the full name of that font. FONTNAME may be a wildcard
5234 pattern; in that case, we choose some font that fits the pattern.
5235 The return value shows which font we chose. */
5238 x_new_font (f
, fontname
)
5240 register char *fontname
;
5242 struct font_info
*fontp
5243 = FS_LOAD_FONT (f
, fontname
);
5248 if (FRAME_FONT (f
) == (XFontStruct
*) (fontp
->font
))
5249 /* This font is already set in frame F. There's nothing more to
5251 return build_string (fontp
->full_name
);
5253 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5254 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5255 FRAME_FONTSET (f
) = -1;
5257 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5258 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5259 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5261 compute_fringe_widths (f
, 1);
5263 /* Compute the scroll bar width in character columns. */
5264 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5266 int wid
= FRAME_COLUMN_WIDTH (f
);
5267 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5268 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5272 int wid
= FRAME_COLUMN_WIDTH (f
);
5273 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5276 /* Now make the frame display the given font. */
5277 if (FRAME_MAC_WINDOW (f
) != 0)
5279 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5281 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5283 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5286 /* Don't change the size of a tip frame; there's no point in
5287 doing it because it's done in Fx_show_tip, and it leads to
5288 problems because the tip frame has no widget. */
5289 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5290 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5293 return build_string (fontp
->full_name
);
5296 /* Give frame F the fontset named FONTSETNAME as its default font, and
5297 return the full name of that fontset. FONTSETNAME may be a wildcard
5298 pattern; in that case, we choose some fontset that fits the pattern.
5299 The return value shows which fontset we chose. */
5302 x_new_fontset (f
, fontsetname
)
5304 Lisp_Object fontsetname
;
5306 int fontset
= fs_query_fontset (fontsetname
, 0);
5309 if (fontset
> 0 && FRAME_FONTSET(f
) == fontset
)
5310 /* This fontset is already set in frame F. There's nothing more
5312 return fontset_name (fontset
);
5313 else if (fontset
== 0)
5314 /* The default fontset can't be the default font. */
5318 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5320 result
= x_new_font (f
, SDATA (fontsetname
));
5322 if (!STRINGP (result
))
5323 /* Can't load ASCII font. */
5327 fontset
= new_fontset_from_font_name (result
);
5329 /* Since x_new_font doesn't update any fontset information, do it now. */
5330 FRAME_FONTSET (f
) = fontset
;
5332 return fontset_name (fontset
);
5336 /***********************************************************************
5337 TODO: W32 Input Methods
5338 ***********************************************************************/
5339 /* Listing missing functions from xterm.c helps diff stay in step.
5341 xim_destroy_callback (xim, client_data, call_data)
5342 xim_open_dpy (dpyinfo, resource_name)
5344 xim_instantiate_callback (display, client_data, call_data)
5345 xim_initialize (dpyinfo, resource_name)
5346 xim_close_dpy (dpyinfo)
5352 mac_get_window_bounds (f
, inner
, outer
)
5354 Rect
*inner
, *outer
;
5356 #if TARGET_API_MAC_CARBON
5357 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5358 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5359 #else /* not TARGET_API_MAC_CARBON */
5360 RgnHandle region
= NewRgn ();
5362 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5363 *inner
= (*region
)->rgnBBox
;
5364 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5365 *outer
= (*region
)->rgnBBox
;
5366 DisposeRgn (region
);
5367 #endif /* not TARGET_API_MAC_CARBON */
5372 /* Calculate the absolute position in frame F
5373 from its current recorded position values and gravity. */
5376 x_calc_absolute_position (f
)
5379 int width_diff
= 0, height_diff
= 0;
5380 int flags
= f
->size_hint_flags
;
5383 /* We have nothing to do if the current position
5384 is already for the top-left corner. */
5385 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5388 /* Find the offsets of the outside upper-left corner of
5389 the inner window, with respect to the outer window. */
5390 mac_get_window_bounds (f
, &inner
, &outer
);
5392 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5393 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5395 /* Treat negative positions as relative to the leftmost bottommost
5396 position that fits on the screen. */
5397 if (flags
& XNegative
)
5398 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5400 - FRAME_PIXEL_WIDTH (f
)
5403 if (flags
& YNegative
)
5404 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5406 - FRAME_PIXEL_HEIGHT (f
)
5409 /* The left_pos and top_pos
5410 are now relative to the top and left screen edges,
5411 so the flags should correspond. */
5412 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5415 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5416 to really change the position, and 0 when calling from
5417 x_make_frame_visible (in that case, XOFF and YOFF are the current
5418 position values). It is -1 when calling from x_set_frame_parameters,
5419 which means, do adjust for borders but don't change the gravity. */
5422 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5424 register int xoff
, yoff
;
5427 if (change_gravity
> 0)
5431 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5433 f
->size_hint_flags
|= XNegative
;
5435 f
->size_hint_flags
|= YNegative
;
5436 f
->win_gravity
= NorthWestGravity
;
5438 x_calc_absolute_position (f
);
5441 x_wm_set_size_hint (f
, (long) 0, 0);
5443 #if TARGET_API_MAC_CARBON
5444 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5445 /* If the title bar is completely outside the screen, adjust the
5447 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5448 kWindowConstrainMoveRegardlessOfFit
5449 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5450 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5453 Rect inner
, outer
, screen_rect
, dummy
;
5454 RgnHandle region
= NewRgn ();
5456 mac_get_window_bounds (f
, &inner
, &outer
);
5457 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5458 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5459 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5460 f
->top_pos
+ f
->y_pixels_diff
, false);
5462 /* If the title bar is completely outside the screen, adjust the
5463 position. The variable `outer' holds the title bar rectangle.
5464 The variable `inner' holds slightly smaller one than `outer',
5465 so that the calculation of overlapping may not become too
5467 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5468 outer
= (*region
)->rgnBBox
;
5469 DisposeRgn (region
);
5471 InsetRect (&inner
, 8, 8);
5472 screen_rect
= qd
.screenBits
.bounds
;
5473 screen_rect
.top
+= GetMBarHeight ();
5475 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5477 if (inner
.right
<= screen_rect
.left
)
5478 f
->left_pos
= screen_rect
.left
;
5479 else if (inner
.left
>= screen_rect
.right
)
5480 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5482 if (inner
.bottom
<= screen_rect
.top
)
5483 f
->top_pos
= screen_rect
.top
;
5484 else if (inner
.top
>= screen_rect
.bottom
)
5485 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5487 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5488 f
->top_pos
+ f
->y_pixels_diff
, false);
5496 /* Call this to change the size of frame F's x-window.
5497 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5498 for this size change and subsequent size changes.
5499 Otherwise we leave the window gravity unchanged. */
5502 x_set_window_size (f
, change_gravity
, cols
, rows
)
5507 int pixelwidth
, pixelheight
;
5511 check_frame_size (f
, &rows
, &cols
);
5512 f
->scroll_bar_actual_width
5513 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5515 compute_fringe_widths (f
, 0);
5517 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5518 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5520 f
->win_gravity
= NorthWestGravity
;
5521 x_wm_set_size_hint (f
, (long) 0, 0);
5523 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5524 #if TARGET_API_MAC_CARBON
5525 if (f
->output_data
.mac
->hourglass_control
)
5526 MoveControl (f
->output_data
.mac
->hourglass_control
,
5527 pixelwidth
- HOURGLASS_WIDTH
, 0);
5530 /* Now, strictly speaking, we can't be sure that this is accurate,
5531 but the window manager will get around to dealing with the size
5532 change request eventually, and we'll hear how it went when the
5533 ConfigureNotify event gets here.
5535 We could just not bother storing any of this information here,
5536 and let the ConfigureNotify event set everything up, but that
5537 might be kind of confusing to the Lisp code, since size changes
5538 wouldn't be reported in the frame parameters until some random
5539 point in the future when the ConfigureNotify event arrives.
5541 We pass 1 for DELAY since we can't run Lisp code inside of
5543 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5544 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5545 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5547 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5548 receive in the ConfigureNotify event; if we get what we asked
5549 for, then the event won't cause the screen to become garbaged, so
5550 we have to make sure to do it here. */
5551 SET_FRAME_GARBAGED (f
);
5553 XFlush (FRAME_X_DISPLAY (f
));
5555 /* If cursor was outside the new size, mark it as off. */
5556 mark_window_cursors_off (XWINDOW (f
->root_window
));
5558 /* Clear out any recollection of where the mouse highlighting was,
5559 since it might be in a place that's outside the new frame size.
5560 Actually checking whether it is outside is a pain in the neck,
5561 so don't try--just let the highlighting be done afresh with new size. */
5562 cancel_mouse_face (f
);
5567 /* Mouse warping. */
5569 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5572 x_set_mouse_position (f
, x
, y
)
5578 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5579 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5581 if (pix_x
< 0) pix_x
= 0;
5582 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5584 if (pix_y
< 0) pix_y
= 0;
5585 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5587 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5591 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5595 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5598 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5599 0, 0, 0, 0, pix_x
, pix_y
);
5604 /* focus shifting, raising and lowering. */
5607 x_focus_on_frame (f
)
5610 #if 0 /* This proves to be unpleasant. */
5614 /* I don't think that the ICCCM allows programs to do things like this
5615 without the interaction of the window manager. Whatever you end up
5616 doing with this code, do it to x_unfocus_frame too. */
5617 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5618 RevertToPointerRoot
, CurrentTime
);
5628 /* Raise frame F. */
5634 if (f
->async_visible
)
5637 SelectWindow (FRAME_MAC_WINDOW (f
));
5642 /* Lower frame F. */
5648 if (f
->async_visible
)
5651 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5657 XTframe_raise_lower (f
, raise_flag
)
5667 /* Change of visibility. */
5670 mac_handle_visibility_change (f
)
5673 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5674 int visible
= 0, iconified
= 0;
5675 struct input_event buf
;
5677 if (IsWindowVisible (wp
))
5678 if (IsWindowCollapsed (wp
))
5683 if (!f
->async_visible
&& visible
)
5687 /* wait_reading_process_output will notice this and update
5688 the frame's display structures. If we were made
5689 invisible, we should not set garbaged, because that stops
5690 redrawing on Update events. */
5691 SET_FRAME_GARBAGED (f
);
5694 buf
.kind
= DEICONIFY_EVENT
;
5695 XSETFRAME (buf
.frame_or_window
, f
);
5696 kbd_buffer_store_event (&buf
);
5698 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5699 /* Force a redisplay sooner or later to update the
5700 frame titles in case this is the second frame. */
5701 record_asynch_buffer_change ();
5703 else if (f
->async_visible
&& !visible
)
5707 buf
.kind
= ICONIFY_EVENT
;
5708 XSETFRAME (buf
.frame_or_window
, f
);
5709 kbd_buffer_store_event (&buf
);
5712 f
->async_visible
= visible
;
5713 f
->async_iconified
= iconified
;
5716 /* This tries to wait until the frame is really visible.
5717 However, if the window manager asks the user where to position
5718 the frame, this will return before the user finishes doing that.
5719 The frame will not actually be visible at that time,
5720 but it will become visible later when the window manager
5721 finishes with it. */
5724 x_make_frame_visible (f
)
5728 int original_top
, original_left
;
5732 if (! FRAME_VISIBLE_P (f
))
5734 /* We test FRAME_GARBAGED_P here to make sure we don't
5735 call x_set_offset a second time
5736 if we get to x_make_frame_visible a second time
5737 before the window gets really visible. */
5738 if (! FRAME_ICONIFIED_P (f
)
5739 && ! f
->output_data
.mac
->asked_for_visible
)
5740 #if TARGET_API_MAC_CARBON
5741 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5743 struct frame
*sf
= SELECTED_FRAME ();
5744 if (!FRAME_MAC_P (sf
))
5745 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5746 kWindowCenterOnMainScreen
);
5748 RepositionWindow (FRAME_MAC_WINDOW (f
),
5749 FRAME_MAC_WINDOW (sf
),
5750 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5751 kWindowCascadeStartAtParentWindowScreen
5753 kWindowCascadeOnParentWindowScreen
5756 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5760 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5762 f
->output_data
.mac
->asked_for_visible
= 1;
5764 SelectWindow (FRAME_MAC_WINDOW (f
));
5765 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
5766 ShowWindow (FRAME_MAC_WINDOW (f
));
5769 XFlush (FRAME_MAC_DISPLAY (f
));
5771 /* Synchronize to ensure Emacs knows the frame is visible
5772 before we do anything else. We do this loop with input not blocked
5773 so that incoming events are handled. */
5778 /* This must come after we set COUNT. */
5781 XSETFRAME (frame
, f
);
5783 /* Wait until the frame is visible. Process X events until a
5784 MapNotify event has been seen, or until we think we won't get a
5785 MapNotify at all.. */
5786 for (count
= input_signal_count
+ 10;
5787 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5789 /* Force processing of queued events. */
5792 /* Machines that do polling rather than SIGIO have been
5793 observed to go into a busy-wait here. So we'll fake an
5794 alarm signal to let the handler know that there's something
5795 to be read. We used to raise a real alarm, but it seems
5796 that the handler isn't always enabled here. This is
5798 if (input_polling_used ())
5800 /* It could be confusing if a real alarm arrives while
5801 processing the fake one. Turn it off and let the
5802 handler reset it. */
5803 extern void poll_for_input_1
P_ ((void));
5804 int old_poll_suppress_count
= poll_suppress_count
;
5805 poll_suppress_count
= 1;
5806 poll_for_input_1 ();
5807 poll_suppress_count
= old_poll_suppress_count
;
5810 /* See if a MapNotify event has been processed. */
5811 FRAME_SAMPLE_VISIBILITY (f
);
5816 /* Change from mapped state to withdrawn state. */
5818 /* Make the frame visible (mapped and not iconified). */
5821 x_make_frame_invisible (f
)
5824 /* A deactivate event does not occur when the last visible frame is
5825 made invisible. So if we clear the highlight here, it will not
5826 be rehighlighted when it is made visible. */
5828 /* Don't keep the highlight on an invisible frame. */
5829 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5830 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5835 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5836 that the current position of the window is user-specified, rather than
5837 program-specified, so that when the window is mapped again, it will be
5838 placed at the same location, without forcing the user to position it
5839 by hand again (they have already done that once for this window.) */
5840 x_wm_set_size_hint (f
, (long) 0, 1);
5842 HideWindow (FRAME_MAC_WINDOW (f
));
5846 #if !USE_CARBON_EVENTS
5847 mac_handle_visibility_change (f
);
5851 /* Change window state from mapped to iconified. */
5859 /* A deactivate event does not occur when the last visible frame is
5860 iconified. So if we clear the highlight here, it will not be
5861 rehighlighted when it is deiconified. */
5863 /* Don't keep the highlight on an invisible frame. */
5864 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5865 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5868 if (f
->async_iconified
)
5873 FRAME_SAMPLE_VISIBILITY (f
);
5875 if (! FRAME_VISIBLE_P (f
))
5876 ShowWindow (FRAME_MAC_WINDOW (f
));
5878 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5883 error ("Can't notify window manager of iconification");
5885 #if !USE_CARBON_EVENTS
5886 mac_handle_visibility_change (f
);
5891 /* Free X resources of frame F. */
5894 x_free_frame_resources (f
)
5897 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5898 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5902 if (wp
!= tip_window
)
5903 remove_window_handler (wp
);
5906 if (wp
== tip_window
)
5907 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5908 closed' event. So we reset tip_window here. */
5911 free_frame_menubar (f
);
5913 if (FRAME_FACE_CACHE (f
))
5914 free_frame_faces (f
);
5918 if (FRAME_SIZE_HINTS (f
))
5919 xfree (FRAME_SIZE_HINTS (f
));
5921 xfree (f
->output_data
.mac
);
5922 f
->output_data
.mac
= NULL
;
5924 if (f
== dpyinfo
->x_focus_frame
)
5925 dpyinfo
->x_focus_frame
= 0;
5926 if (f
== dpyinfo
->x_focus_event_frame
)
5927 dpyinfo
->x_focus_event_frame
= 0;
5928 if (f
== dpyinfo
->x_highlight_frame
)
5929 dpyinfo
->x_highlight_frame
= 0;
5931 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5933 dpyinfo
->mouse_face_beg_row
5934 = dpyinfo
->mouse_face_beg_col
= -1;
5935 dpyinfo
->mouse_face_end_row
5936 = dpyinfo
->mouse_face_end_col
= -1;
5937 dpyinfo
->mouse_face_window
= Qnil
;
5938 dpyinfo
->mouse_face_deferred_gc
= 0;
5939 dpyinfo
->mouse_face_mouse_frame
= 0;
5946 /* Destroy the X window of frame F. */
5949 x_destroy_window (f
)
5952 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5954 x_free_frame_resources (f
);
5956 dpyinfo
->reference_count
--;
5960 /* Setting window manager hints. */
5962 /* Set the normal size hints for the window manager, for frame F.
5963 FLAGS is the flags word to use--or 0 meaning preserve the flags
5964 that the window now has.
5965 If USER_POSITION is nonzero, we set the USPosition
5966 flag (this is useful when FLAGS is 0). */
5968 x_wm_set_size_hint (f
, flags
, user_position
)
5973 int base_width
, base_height
, width_inc
, height_inc
;
5974 int min_rows
= 0, min_cols
= 0;
5975 XSizeHints
*size_hints
;
5977 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5978 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5979 width_inc
= FRAME_COLUMN_WIDTH (f
);
5980 height_inc
= FRAME_LINE_HEIGHT (f
);
5982 check_frame_size (f
, &min_rows
, &min_cols
);
5984 size_hints
= FRAME_SIZE_HINTS (f
);
5985 if (size_hints
== NULL
)
5987 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
5988 bzero (size_hints
, sizeof (XSizeHints
));
5991 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
5992 size_hints
->width_inc
= width_inc
;
5993 size_hints
->height_inc
= height_inc
;
5994 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
5995 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
5996 size_hints
->base_width
= base_width
;
5997 size_hints
->base_height
= base_height
;
6000 size_hints
->flags
= flags
;
6001 else if (user_position
)
6003 size_hints
->flags
&= ~ PPosition
;
6004 size_hints
->flags
|= USPosition
;
6008 #if 0 /* MAC_TODO: hide application instead of iconify? */
6009 /* Used for IconicState or NormalState */
6012 x_wm_set_window_state (f
, state
)
6016 #ifdef USE_X_TOOLKIT
6019 XtSetArg (al
[0], XtNinitialState
, state
);
6020 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6021 #else /* not USE_X_TOOLKIT */
6022 Window window
= FRAME_X_WINDOW (f
);
6024 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6025 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6027 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6028 #endif /* not USE_X_TOOLKIT */
6032 x_wm_set_icon_pixmap (f
, pixmap_id
)
6038 #ifndef USE_X_TOOLKIT
6039 Window window
= FRAME_X_WINDOW (f
);
6044 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6045 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6049 /* It seems there is no way to turn off use of an icon pixmap.
6050 The following line does it, only if no icon has yet been created,
6051 for some window managers. But with mwm it crashes.
6052 Some people say it should clear the IconPixmapHint bit in this case,
6053 but that doesn't work, and the X consortium said it isn't the
6054 right thing at all. Since there is no way to win,
6055 best to explicitly give up. */
6057 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6063 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6067 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6068 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6071 #else /* not USE_X_TOOLKIT */
6073 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6074 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6076 #endif /* not USE_X_TOOLKIT */
6079 #endif /* MAC_TODO */
6082 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6086 #if 0 /* MAC_TODO: no icons on Mac */
6087 #ifdef USE_X_TOOLKIT
6088 Window window
= XtWindow (f
->output_data
.x
->widget
);
6090 Window window
= FRAME_X_WINDOW (f
);
6093 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6094 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6095 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6097 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6098 #endif /* MAC_TODO */
6102 /***********************************************************************
6104 ***********************************************************************/
6106 /* An XLFD pattern is divided into blocks delimited by '*'. This
6107 structure holds information for each block. */
6108 struct xlfdpat_block
6110 /* Length of the pattern string in this block. Non-zero except for
6111 the first and the last blocks. */
6114 /* Pattern string except the last character in this block. The last
6115 character is replaced with NUL in order to use it as a
6117 unsigned char *pattern
;
6119 /* Last character of the pattern string. Must not be '?'. */
6120 unsigned char last_char
;
6122 /* One of the tables for the Boyer-Moore string search. It
6123 specifies the number of positions to proceed for each character
6124 with which the match fails. */
6127 /* The skip value for the last character in the above `skip' is
6128 assigned to `infinity' in order to simplify a loop condition.
6129 The original value is saved here. */
6135 /* Normalized pattern string. "Normalized" means that capital
6136 letters are lowered, blocks are not empty except the first and
6137 the last ones, and trailing '?'s in a block that is not the last
6138 one are moved to the next one. The last character in each block
6139 is replaced with NUL. */
6142 /* Number of characters except '*'s and trailing '?'s in the
6143 normalized pattern string. */
6146 /* Number of trailing '?'s in the normalized pattern string. */
6147 int trailing_anychars
;
6149 /* Number of blocks and information for each block. The latter is
6150 NULL if the pattern is exact (no '*' or '?' in it). */
6152 struct xlfdpat_block
*blocks
;
6156 xlfdpat_destroy (pat
)
6157 struct xlfdpat
*pat
;
6164 xfree (pat
->blocks
);
6171 static struct xlfdpat
*
6172 xlfdpat_create (pattern
)
6175 struct xlfdpat
*pat
;
6176 int nblocks
, i
, skip
;
6177 unsigned char last_char
, *p
, *q
, *anychar_head
;
6178 struct xlfdpat_block
*blk
;
6180 pat
= xmalloc (sizeof (struct xlfdpat
));
6184 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6185 if (pat
->buf
== NULL
)
6188 /* Normalize the pattern string and store it to `pat->buf'. */
6190 anychar_head
= NULL
;
6193 for (p
= pattern
; *p
; p
++)
6195 unsigned char c
= *p
;
6198 if (last_char
== '*')
6199 /* ...a** -> ...a* */
6203 if (last_char
== '?')
6204 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6205 /* ...*??* -> ...*?? */
6208 /* ...a??* -> ...a*?? */
6210 *anychar_head
++ = '*';
6217 if (last_char
!= '?')
6221 /* On Mac OS X 10.3, tolower also converts non-ASCII
6222 characters for some locales. */
6226 *q
++ = last_char
= c
;
6230 pat
->nblocks
= nblocks
;
6231 if (last_char
!= '?')
6232 pat
->trailing_anychars
= 0;
6235 pat
->trailing_anychars
= q
- anychar_head
;
6238 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6240 if (anychar_head
== NULL
&& nblocks
== 1)
6242 /* The pattern is exact. */
6247 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6248 if (pat
->blocks
== NULL
)
6251 /* Divide the normalized pattern into blocks. */
6253 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6258 blk
->len
= p
- blk
->pattern
;
6262 blk
->len
= q
- blk
->pattern
;
6264 /* Setup a table for the Boyer-Moore string search. */
6265 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6268 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6269 blk
->pattern
[blk
->len
- 1] = '\0';
6271 for (skip
= 1; skip
< blk
->len
; skip
++)
6272 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6275 for (i
= 0; i
< 256; i
++)
6276 blk
->skip
[i
] = skip
;
6278 p
= blk
->pattern
+ (blk
->len
- skip
);
6280 blk
->skip
[*p
++] = skip
;
6282 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6288 xlfdpat_destroy (pat
);
6293 xlfdpat_exact_p (pat
)
6294 struct xlfdpat
*pat
;
6296 return (pat
)->blocks
== NULL
;
6299 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6300 that the pattern in *BLK matches with its prefix. Return NULL
6301 there is no such strings. STRING must be lowered in advance. */
6304 xlfdpat_block_match_1 (blk
, string
, start_max
)
6305 struct xlfdpat_block
*blk
;
6306 unsigned char *string
;
6309 int start
, infinity
;
6310 unsigned char *p
, *s
;
6312 xassert (blk
->len
> 0);
6313 xassert (start_max
+ blk
->len
<= strlen (string
));
6314 xassert (blk
->pattern
[blk
->len
- 1] != '?');
6316 /* See the comments in the function `boyer_moore' (search.c) for the
6317 use of `infinity'. */
6318 infinity
= start_max
+ blk
->len
+ 1;
6319 blk
->skip
[blk
->last_char
] = infinity
;
6324 /* Check the last character of the pattern. */
6325 s
= string
+ blk
->len
- 1;
6328 start
+= blk
->skip
[*(s
+ start
)];
6330 while (start
<= start_max
);
6332 if (start
< infinity
)
6333 /* Couldn't find the last character. */
6336 /* No less than `infinity' means we could find the last
6337 character at `s[start - infinity]'. */
6340 /* Check the remaining characters. We prefer making no-'?'
6341 cases faster because the use of '?' is really rare. */
6346 while (*p
++ == *s
++)
6349 while (*(p
- 1) == '?');
6351 if (*(p
- 1) == '\0')
6353 return string
+ start
;
6356 start
+= blk
->last_char_skip
;
6358 while (start
<= start_max
);
6363 #define xlfdpat_block_match(b, s, m) \
6364 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6365 : xlfdpat_block_match_1 (b, s, m))
6367 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6368 matches with STRING. STRING must be lowered in advance. */
6371 xlfdpat_match (pat
, string
)
6372 struct xlfdpat
*pat
;
6373 unsigned char *string
;
6375 int str_len
, nblocks
, i
, start_max
;
6376 struct xlfdpat_block
*blk
;
6379 xassert (pat
->nblocks
> 0);
6381 if (xlfdpat_exact_p (pat
))
6382 return strcmp (pat
->buf
, string
) == 0;
6384 /* The number of the characters in the string must not be smaller
6385 than that in the pattern. */
6386 str_len
= strlen (string
);
6387 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6390 /* Chop off the trailing '?'s. */
6391 str_len
-= pat
->trailing_anychars
;
6393 /* The last block. When it is non-empty, it must match at the end
6395 nblocks
= pat
->nblocks
;
6396 blk
= pat
->blocks
+ (nblocks
- 1);
6398 /* The last block is also the first one. */
6399 return (str_len
== blk
->len
6400 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6401 else if (blk
->len
!= 0)
6402 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6405 /* The first block. When it is non-empty, it must match at the
6406 beginning of the string. */
6410 s
= xlfdpat_block_match (blk
, string
, 0);
6413 string
= s
+ blk
->len
;
6416 /* The rest of the blocks. */
6417 start_max
= str_len
- pat
->nchars
;
6418 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6420 s
= xlfdpat_block_match (blk
, string
, start_max
);
6423 start_max
-= s
- string
;
6424 string
= s
+ blk
->len
;
6431 /***********************************************************************
6433 ***********************************************************************/
6435 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6438 x_get_font_info (f
, font_idx
)
6442 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6445 /* the global font name table */
6446 static char **font_name_table
= NULL
;
6447 static int font_name_table_size
= 0;
6448 static int font_name_count
= 0;
6450 /* Alist linking character set strings to Mac text encoding and Emacs
6452 static Lisp_Object Vmac_charset_info_alist
;
6455 create_text_encoding_info_alist ()
6457 Lisp_Object result
= Qnil
, rest
;
6459 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6461 Lisp_Object charset_info
= XCAR (rest
);
6462 Lisp_Object charset
, coding_system
, text_encoding
;
6463 Lisp_Object existing_info
;
6465 if (!(CONSP (charset_info
)
6466 && STRINGP (charset
= XCAR (charset_info
))
6467 && CONSP (XCDR (charset_info
))
6468 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6469 && CONSP (XCDR (XCDR (charset_info
)))
6470 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6473 existing_info
= assq_no_quit (text_encoding
, result
);
6474 if (NILP (existing_info
))
6475 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6478 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6479 XSETCDR (XCDR (existing_info
),
6480 Fcons (charset
, XCDR (XCDR (existing_info
))));
6488 decode_mac_font_name (name
, size
, coding_system
)
6491 Lisp_Object coding_system
;
6493 struct coding_system coding
;
6496 for (p
= name
; *p
; p
++)
6497 if (!isascii (*p
) || iscntrl (*p
))
6501 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6505 /* MAC_TODO: Fix encoding system... */
6506 setup_coding_system (coding_system
, &coding
);
6507 coding
.src_multibyte
= 0;
6508 coding
.dst_multibyte
= 1;
6509 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6510 coding
.dst_bytes
= MAX_MULTsize
;
6511 coding
.destination
= (char *) alloca (size
);
6512 coding_decode_c_string(&coding
, name
, strlen(name
), qNil
);
6514 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6515 bcopy (buf
, name
, coding
.produced
);
6516 name
[coding
.produced
] = '\0';
6522 mac_to_x_fontname (name
, size
, style
, charset
)
6530 char xf
[256], *result
;
6533 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6537 strcpy(foundry
, "Apple");
6538 strcpy(family
, name
);
6541 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6542 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6543 size
, size
* 10, size
? 75 : 0, size
? 75 : 0, size
* 10, charset
);
6545 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6546 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6547 for (p
= result
; *p
; p
++)
6548 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6549 for some locales. */
6556 /* Convert an X font spec to the corresponding mac font name, which
6557 can then be passed to GetFNum after conversion to a Pascal string.
6558 For ordinary Mac fonts, this should just be their names, like
6559 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6560 collection contain their charset designation in their names, like
6561 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6562 names are handled accordingly. */
6564 x_font_name_to_mac_font_name (xf
, mf
, mf_decoded
, style
, cs
)
6565 char *xf
, *mf
, *mf_decoded
;
6571 char weight
[20], slant
[2], *p
;
6572 Lisp_Object charset_info
, coding_system
= Qnil
;
6573 struct coding_system coding
;
6577 if (sscanf (xf
, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6578 foundry
, family
, weight
, slant
, cs
) != 5 &&
6579 sscanf (xf
, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6580 foundry
, family
, weight
, slant
, cs
) != 5)
6584 if (strcmp (weight
, "bold") == 0)
6589 charset_info
= Fassoc (build_string (cs
), Vmac_charset_info_alist
);
6590 if (!NILP (charset_info
))
6592 strcpy (mf_decoded
, family
);
6593 coding_system
= Fcar (Fcdr (Fcdr (charset_info
)));
6596 sprintf (mf_decoded
, "%s-%s-%s", foundry
, family
, cs
);
6598 for (p
= mf_decoded
; *p
; p
++)
6599 if (!isascii (*p
) || iscntrl (*p
))
6603 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6604 strcpy (mf
, mf_decoded
);
6606 /* MAC_TODO: Fix coding system to use objects */
6609 setup_coding_system (coding_system
, &coding
);
6610 coding
.src_multibyte
= 1;
6611 coding
.dst_multibyte
= 0;
6612 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6613 encode_coding (&coding
, mf_decoded
, mf
,
6614 strlen (mf_decoded
), sizeof (Str255
) - 1);
6615 mf
[coding
.produced
] = '\0';
6622 add_font_name_table_entry (char *font_name
)
6624 if (font_name_table_size
== 0)
6626 font_name_table_size
= 256;
6627 font_name_table
= (char **)
6628 xmalloc (font_name_table_size
* sizeof (char *));
6630 else if (font_name_count
+ 1 >= font_name_table_size
)
6632 font_name_table_size
*= 2;
6633 font_name_table
= (char **)
6634 xrealloc (font_name_table
,
6635 font_name_table_size
* sizeof (char *));
6638 font_name_table
[font_name_count
++] = font_name
;
6641 /* Sets up the table font_name_table to contain the list of all fonts
6642 in the system the first time the table is used so that the Resource
6643 Manager need not be accessed every time this information is
6647 init_font_name_table ()
6649 #if TARGET_API_MAC_CARBON
6650 FMFontFamilyIterator ffi
;
6651 FMFontFamilyInstanceIterator ffii
;
6653 Lisp_Object text_encoding_info_alist
;
6654 struct gcpro gcpro1
;
6656 /* Create a dummy instance iterator here to avoid creating and
6657 destroying it in the loop. */
6658 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6660 /* Create an iterator to enumerate the font families. */
6661 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6664 FMDisposeFontFamilyInstanceIterator (&ffii
);
6668 text_encoding_info_alist
= create_text_encoding_info_alist ();
6670 GCPRO1 (text_encoding_info_alist
);
6672 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6678 TextEncoding encoding
;
6679 TextEncodingBase sc
;
6680 Lisp_Object text_encoding_info
;
6682 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6688 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6690 sc
= GetTextEncodingBase (encoding
);
6691 text_encoding_info
= assq_no_quit (make_number (sc
),
6692 text_encoding_info_alist
);
6693 if (!NILP (text_encoding_info
))
6694 decode_mac_font_name (name
, sizeof (name
),
6695 XCAR (XCDR (text_encoding_info
)));
6697 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6698 text_encoding_info_alist
);
6700 /* Point the instance iterator at the current font family. */
6701 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6704 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6707 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6709 for (; !NILP (rest
); rest
= XCDR (rest
))
6711 char *cs
= SDATA (XCAR (rest
));
6715 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6717 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6719 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6721 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6727 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6736 /* Dispose of the iterators. */
6737 FMDisposeFontFamilyIterator (&ffi
);
6738 FMDisposeFontFamilyInstanceIterator (&ffii
);
6739 #else /* !TARGET_API_MAC_CARBON */
6741 SInt16 fontnum
, old_fontnum
;
6742 int num_mac_fonts
= CountResources('FOND');
6744 Handle font_handle
, font_handle_2
;
6745 short id
, scriptcode
;
6748 struct FontAssoc
*fat
;
6749 struct AsscEntry
*assc_entry
;
6750 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6751 struct gcpro gcpro1
;
6753 GetPort (&port
); /* save the current font number used */
6754 old_fontnum
= port
->txFont
;
6756 text_encoding_info_alist
= create_text_encoding_info_alist ();
6758 GCPRO1 (text_encoding_info_alist
);
6760 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6762 font_handle
= GetIndResource ('FOND', i
);
6766 GetResInfo (font_handle
, &id
, &type
, name
);
6767 GetFNum (name
, &fontnum
);
6773 scriptcode
= FontToScript (fontnum
);
6774 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6775 text_encoding_info_alist
);
6776 if (!NILP (text_encoding_info
))
6777 decode_mac_font_name (name
, sizeof (name
),
6778 XCAR (XCDR (text_encoding_info
)));
6780 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6781 text_encoding_info_alist
);
6784 HLock (font_handle
);
6786 if (GetResourceSizeOnDisk (font_handle
)
6787 >= sizeof (struct FamRec
))
6789 fat
= (struct FontAssoc
*) (*font_handle
6790 + sizeof (struct FamRec
));
6792 = (struct AsscEntry
*) (*font_handle
6793 + sizeof (struct FamRec
)
6794 + sizeof (struct FontAssoc
));
6796 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6798 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6800 for (; !NILP (rest
); rest
= XCDR (rest
))
6802 char *cs
= SDATA (XCAR (rest
));
6804 add_font_name_table_entry (mac_to_x_fontname (name
,
6805 assc_entry
->fontSize
,
6806 assc_entry
->fontStyle
,
6812 HUnlock (font_handle
);
6813 font_handle_2
= GetNextFOND (font_handle
);
6814 ReleaseResource (font_handle
);
6815 font_handle
= font_handle_2
;
6817 while (ResError () == noErr
&& font_handle
);
6822 TextFont (old_fontnum
);
6823 #endif /* !TARGET_API_MAC_CARBON */
6828 mac_clear_font_name_table ()
6832 for (i
= 0; i
< font_name_count
; i
++)
6833 xfree (font_name_table
[i
]);
6834 xfree (font_name_table
);
6835 font_name_table
= NULL
;
6836 font_name_table_size
= font_name_count
= 0;
6840 enum xlfd_scalable_field_index
6842 XLFD_SCL_PIXEL_SIZE
,
6843 XLFD_SCL_POINT_SIZE
,
6848 static int xlfd_scalable_fields
[] =
6857 mac_do_list_fonts (pattern
, maxnames
)
6862 Lisp_Object font_list
= Qnil
;
6863 struct xlfdpat
*pat
;
6865 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6868 if (font_name_table
== NULL
) /* Initialize when first used. */
6869 init_font_name_table ();
6871 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6874 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6875 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6876 fonts are scaled according to the specified size. */
6879 field
= xlfd_scalable_fields
;
6887 if ('0' <= *ptr
&& *ptr
<= '9')
6889 *val
= *ptr
++ - '0';
6890 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6891 *val
= *val
* 10 + *ptr
++ - '0';
6898 ptr
= strchr (ptr
, '-');
6901 while (ptr
&& i
< 14);
6903 if (i
== 14 && ptr
== NULL
)
6905 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
6906 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
6907 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
6908 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
6910 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
6911 scl_val
[XLFD_SCL_POINT_SIZE
] =
6912 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6913 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
6915 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
6916 scl_val
[XLFD_SCL_AVGWIDTH
] =
6917 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
6918 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
6922 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6924 pat
= xlfdpat_create (pattern
);
6928 exact
= xlfdpat_exact_p (pat
);
6930 for (i
= 0; i
< font_name_count
; i
++)
6932 if (xlfdpat_match (pat
, font_name_table
[i
]))
6934 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
6935 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6938 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6939 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
6941 int former_len
= ptr
- font_name_table
[i
];
6943 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
6946 memcpy (scaled
, font_name_table
[i
], former_len
);
6947 sprintf (scaled
+ former_len
,
6948 "-%d-%d-75-75-m-%d-%s",
6949 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6950 scl_val
[XLFD_SCL_POINT_SIZE
],
6951 scl_val
[XLFD_SCL_AVGWIDTH
],
6952 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
6954 if (xlfdpat_match (pat
, scaled
))
6956 font_list
= Fcons (build_string (scaled
), font_list
);
6958 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
6966 xlfdpat_destroy (pat
);
6971 /* Return a list of names of available fonts matching PATTERN on frame F.
6973 Frame F null means we have not yet created any frame on Mac, and
6974 consult the first display in x_display_list. MAXNAMES sets a limit
6975 on how many fonts to match. */
6978 x_list_fonts (f
, pattern
, size
, maxnames
)
6980 Lisp_Object pattern
;
6983 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
6984 struct mac_display_info
*dpyinfo
6985 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
6987 xassert (size
<= 0);
6989 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6990 if (NILP (patterns
))
6991 patterns
= Fcons (pattern
, Qnil
);
6993 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
6995 pattern
= XCAR (patterns
);
6997 if (!STRINGP (pattern
))
7000 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7001 key
= Fcons (pattern
, make_number (maxnames
));
7003 list
= Fassoc (key
, tem
);
7006 list
= Fcdr_safe (list
);
7007 /* We have a cashed list. Don't have to get the list again. */
7012 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7015 /* MAC_TODO: add code for matching outline fonts here */
7017 /* Now store the result in the cache. */
7018 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7019 Fcons (Fcons (key
, list
),
7020 XCAR (XCDR (dpyinfo
->name_list_element
))));
7023 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7032 /* Check that FONT is valid on frame F. It is if it can be found in F's
7036 x_check_font (f
, font
)
7041 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7043 xassert (font
!= NULL
);
7045 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7046 if (dpyinfo
->font_table
[i
].name
7047 && font
== dpyinfo
->font_table
[i
].font
)
7050 xassert (i
< dpyinfo
->n_fonts
);
7053 #endif /* GLYPH_DEBUG != 0 */
7055 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7056 Note: There are (broken) X fonts out there with invalid XFontStruct
7057 min_bounds contents. For example, handa@etl.go.jp reports that
7058 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7059 have font->min_bounds.width == 0. */
7062 x_font_min_bounds (font
, w
, h
)
7063 MacFontStruct
*font
;
7066 *h
= FONT_HEIGHT (font
);
7067 *w
= font
->min_bounds
.width
;
7071 /* Compute the smallest character width and smallest font height over
7072 all fonts available on frame F. Set the members smallest_char_width
7073 and smallest_font_height in F's x_display_info structure to
7074 the values computed. Value is non-zero if smallest_font_height or
7075 smallest_char_width become smaller than they were before. */
7078 x_compute_min_glyph_bounds (f
)
7082 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7083 MacFontStruct
*font
;
7084 int old_width
= dpyinfo
->smallest_char_width
;
7085 int old_height
= dpyinfo
->smallest_font_height
;
7087 dpyinfo
->smallest_font_height
= 100000;
7088 dpyinfo
->smallest_char_width
= 100000;
7090 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7091 if (dpyinfo
->font_table
[i
].name
)
7093 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7096 font
= (MacFontStruct
*) fontp
->font
;
7097 xassert (font
!= (MacFontStruct
*) ~0);
7098 x_font_min_bounds (font
, &w
, &h
);
7100 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7101 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7104 xassert (dpyinfo
->smallest_char_width
> 0
7105 && dpyinfo
->smallest_font_height
> 0);
7107 return (dpyinfo
->n_fonts
== 1
7108 || dpyinfo
->smallest_char_width
< old_width
7109 || dpyinfo
->smallest_font_height
< old_height
);
7113 /* Determine whether given string is a fully-specified XLFD: all 14
7114 fields are present, none is '*'. */
7117 is_fully_specified_xlfd (char *p
)
7125 for (i
= 0; i
< 13; i
++)
7127 q
= strchr (p
+ 1, '-');
7130 if (q
- p
== 2 && *(p
+ 1) == '*')
7135 if (strchr (p
+ 1, '-') != NULL
)
7138 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7145 const int kDefaultFontSize
= 12;
7148 /* XLoadQueryFont creates and returns an internal representation for a
7149 font in a MacFontStruct struct. There is really no concept
7150 corresponding to "loading" a font on the Mac. But we check its
7151 existence and find the font number and all other information for it
7152 and store them in the returned MacFontStruct. */
7154 static MacFontStruct
*
7155 XLoadQueryFont (Display
*dpy
, char *fontname
)
7157 int i
, size
, point_size
, avgwidth
, is_two_byte_font
, char_width
;
7160 SInt16 old_fontnum
, old_fontsize
;
7162 Str255 mfontname
, mfontname_decoded
;
7166 #if TARGET_API_MAC_CARBON
7167 TextEncoding encoding
;
7172 MacFontStruct
*font
;
7173 FontInfo the_fontinfo
;
7175 UInt32 old_flags
, new_flags
;
7178 if (is_fully_specified_xlfd (fontname
))
7182 Lisp_Object matched_fonts
;
7184 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7185 if (NILP (matched_fonts
))
7187 name
= SDATA (XCAR (matched_fonts
));
7190 GetPort (&port
); /* save the current font number used */
7191 #if TARGET_API_MAC_CARBON
7192 old_fontnum
= GetPortTextFont (port
);
7193 old_fontsize
= GetPortTextSize (port
);
7194 old_fontface
= GetPortTextFace (port
);
7196 old_fontnum
= port
->txFont
;
7197 old_fontsize
= port
->txSize
;
7198 old_fontface
= port
->txFace
;
7201 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size
, &point_size
, &avgwidth
) != 3)
7207 size
= point_size
/ 10;
7208 else if (avgwidth
> 0)
7209 size
= avgwidth
/ 10;
7212 size
= kDefaultFontSize
;
7214 x_font_name_to_mac_font_name (name
, mfontname
, mfontname_decoded
,
7215 &fontface
, charset
);
7217 #if TARGET_API_MAC_CARBON
7218 fontnum
= FMGetFontFamilyFromName (mfontname
);
7219 if (fontnum
== kInvalidFontFamily
7220 || FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7222 scriptcode
= GetTextEncodingBase (encoding
);
7224 GetFNum (mfontname
, &fontnum
);
7227 scriptcode
= FontToScript (fontnum
);
7230 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7232 font
->mac_fontnum
= fontnum
;
7233 font
->mac_fontsize
= size
;
7234 font
->mac_fontface
= fontface
;
7235 font
->mac_scriptcode
= scriptcode
;
7237 /* Apple Japanese (SJIS) font is listed as both
7238 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7239 (Roman script) in init_font_name_table (). The latter should be
7240 treated as a one-byte font. */
7241 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7242 font
->mac_scriptcode
= smRoman
;
7244 font
->full_name
= mac_to_x_fontname (mfontname_decoded
, size
, fontface
, charset
);
7246 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
7247 font
->mac_scriptcode
== smTradChinese
||
7248 font
->mac_scriptcode
== smSimpChinese
||
7249 font
->mac_scriptcode
== smKorean
;
7253 TextFace (fontface
);
7255 GetFontInfo (&the_fontinfo
);
7257 font
->ascent
= the_fontinfo
.ascent
;
7258 font
->descent
= the_fontinfo
.descent
;
7260 font
->min_byte1
= 0;
7261 if (is_two_byte_font
)
7262 font
->max_byte1
= 1;
7264 font
->max_byte1
= 0;
7265 font
->min_char_or_byte2
= 0x20;
7266 font
->max_char_or_byte2
= 0xff;
7268 if (is_two_byte_font
)
7270 /* Use the width of an "ideographic space" of that font because
7271 the_fontinfo.widMax returns the wrong width for some fonts. */
7272 switch (font
->mac_scriptcode
)
7275 char_width
= StringWidth("\p\x81\x40");
7278 char_width
= StringWidth("\p\xa1\x40");
7281 char_width
= StringWidth("\p\xa1\xa1");
7284 char_width
= StringWidth("\p\xa1\xa1");
7289 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7290 returns 15 for 12-point Monaco! */
7291 char_width
= CharWidth ('m');
7293 if (is_two_byte_font
)
7295 font
->per_char
= NULL
;
7297 if (fontface
& italic
)
7298 font
->max_bounds
.rbearing
= char_width
+ 1;
7300 font
->max_bounds
.rbearing
= char_width
;
7301 font
->max_bounds
.lbearing
= 0;
7302 font
->max_bounds
.width
= char_width
;
7303 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7304 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7306 font
->min_bounds
= font
->max_bounds
;
7310 font
->per_char
= (XCharStruct
*)
7311 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7313 int c
, min_width
, max_width
;
7314 Rect char_bounds
, min_bounds
, max_bounds
;
7317 min_width
= max_width
= char_width
;
7318 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7319 SetRect (&max_bounds
, 0, 0, 0, 0);
7320 for (c
= 0x20; c
<= 0xff; c
++)
7323 char_width
= CharWidth (ch
);
7324 QDTextBounds (1, &ch
, &char_bounds
);
7325 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7326 char_width
, char_bounds
);
7327 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7328 character width of 0x7f. */
7331 min_width
= min (min_width
, char_width
);
7332 max_width
= max (max_width
, char_width
);
7334 if (!EmptyRect (&char_bounds
))
7336 SetRect (&min_bounds
,
7337 max (min_bounds
.left
, char_bounds
.left
),
7338 max (min_bounds
.top
, char_bounds
.top
),
7339 min (min_bounds
.right
, char_bounds
.right
),
7340 min (min_bounds
.bottom
, char_bounds
.bottom
));
7341 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7344 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7345 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7346 if (min_width
== max_width
7347 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7349 /* Fixed width and no overhangs. */
7350 xfree (font
->per_char
);
7351 font
->per_char
= NULL
;
7356 TextFont (old_fontnum
); /* restore previous font number, size and face */
7357 TextSize (old_fontsize
);
7358 TextFace (old_fontface
);
7365 mac_unload_font (dpyinfo
, font
)
7366 struct mac_display_info
*dpyinfo
;
7369 xfree (font
->full_name
);
7371 xfree (font
->per_char
);
7376 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7377 pointer to the structure font_info while allocating it dynamically.
7378 If SIZE is 0, load any size of font.
7379 If loading is failed, return NULL. */
7382 x_load_font (f
, fontname
, size
)
7384 register char *fontname
;
7387 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7388 Lisp_Object font_names
;
7390 /* Get a list of all the fonts that match this name. Once we
7391 have a list of matching fonts, we compare them against the fonts
7392 we already have by comparing names. */
7393 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7395 if (!NILP (font_names
))
7400 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7401 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7402 if (dpyinfo
->font_table
[i
].name
7403 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7404 SDATA (XCAR (tail
)))
7405 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7406 SDATA (XCAR (tail
)))))
7407 return (dpyinfo
->font_table
+ i
);
7412 /* Load the font and add it to the table. */
7415 struct MacFontStruct
*font
;
7416 struct font_info
*fontp
;
7417 unsigned long value
;
7420 fontname
= (char *) SDATA (XCAR (font_names
));
7423 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7428 /* Find a free slot in the font table. */
7429 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7430 if (dpyinfo
->font_table
[i
].name
== NULL
)
7433 /* If no free slot found, maybe enlarge the font table. */
7434 if (i
== dpyinfo
->n_fonts
7435 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7438 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7439 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7441 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7444 fontp
= dpyinfo
->font_table
+ i
;
7445 if (i
== dpyinfo
->n_fonts
)
7448 /* Now fill in the slots of *FONTP. */
7450 bzero (fontp
, sizeof (*fontp
));
7452 fontp
->font_idx
= i
;
7453 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7454 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7456 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7458 /* Fixed width font. */
7459 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7466 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7467 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7469 fontp
->space_width
= pcm
->width
;
7471 fontp
->space_width
= FONT_WIDTH (font
);
7475 int width
= pcm
->width
;
7476 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7477 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7478 width
+= pcm
->width
;
7479 fontp
->average_width
= width
/ 95;
7482 fontp
->average_width
= FONT_WIDTH (font
);
7485 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7486 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7488 fontp
->size
= font
->max_bounds
.width
;
7489 fontp
->height
= FONT_HEIGHT (font
);
7491 /* For some font, ascent and descent in max_bounds field is
7492 larger than the above value. */
7493 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7494 if (max_height
> fontp
->height
)
7495 fontp
->height
= max_height
;
7498 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7500 /* MAC_TODO: The script encoding is irrelevant in unicode? */
7501 /* The slot `encoding' specifies how to map a character
7502 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7503 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7504 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7505 2:0xA020..0xFF7F). For the moment, we don't know which charset
7506 uses this font. So, we set information in fontp->encoding[1]
7507 which is never used by any charset. If mapping can't be
7508 decided, set FONT_ENCODING_NOT_DECIDED. */
7509 if (font
->mac_scriptcode
== smJapanese
)
7510 fontp
->encoding
[1] = 4;
7514 = (font
->max_byte1
== 0
7516 ? (font
->min_char_or_byte2
< 0x80
7517 ? (font
->max_char_or_byte2
< 0x80
7518 ? 0 /* 0x20..0x7F */
7519 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7520 : 1) /* 0xA0..0xFF */
7522 : (font
->min_byte1
< 0x80
7523 ? (font
->max_byte1
< 0x80
7524 ? (font
->min_char_or_byte2
< 0x80
7525 ? (font
->max_char_or_byte2
< 0x80
7526 ? 0 /* 0x2020..0x7F7F */
7527 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7528 : 3) /* 0x20A0..0x7FFF */
7529 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7530 : (font
->min_char_or_byte2
< 0x80
7531 ? (font
->max_char_or_byte2
< 0x80
7532 ? 2 /* 0xA020..0xFF7F */
7533 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7534 : 1))); /* 0xA0A0..0xFFFF */
7537 fontp
->baseline_offset
7538 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7539 ? (long) value
: 0);
7540 fontp
->relative_compose
7541 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7542 ? (long) value
: 0);
7543 fontp
->default_ascent
7544 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7545 ? (long) value
: 0);
7547 fontp
->baseline_offset
= 0;
7548 fontp
->relative_compose
= 0;
7549 fontp
->default_ascent
= 0;
7552 /* Set global flag fonts_changed_p to non-zero if the font loaded
7553 has a character with a smaller width than any other character
7554 before, or if the font loaded has a smaller height than any
7555 other font loaded before. If this happens, it will make a
7556 glyph matrix reallocation necessary. */
7557 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
7564 /* Return a pointer to struct font_info of a font named FONTNAME for
7565 frame F. If no such font is loaded, return NULL. */
7568 x_query_font (f
, fontname
)
7570 register char *fontname
;
7572 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7575 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7576 if (dpyinfo
->font_table
[i
].name
7577 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7578 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7579 return (dpyinfo
->font_table
+ i
);
7584 /* Find a CCL program for a font specified by FONTP, and set the member
7585 `encoder' of the structure. */
7588 x_find_ccl_program (fontp
)
7589 struct font_info
*fontp
;
7591 Lisp_Object list
, elt
;
7593 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7597 && STRINGP (XCAR (elt
))
7598 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7604 struct ccl_program
*ccl
7605 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7607 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7610 fontp
->font_encoder
= ccl
;
7616 /* The Mac Event loop code */
7618 #if !TARGET_API_MAC_CARBON
7620 #include <Quickdraw.h>
7621 #include <Balloons.h>
7622 #include <Devices.h>
7624 #include <Gestalt.h>
7626 #include <Processes.h>
7628 #include <ToolUtils.h>
7629 #include <TextUtils.h>
7630 #include <Dialogs.h>
7633 #include <Resources.h>
7638 #endif /* ! TARGET_API_MAC_CARBON */
7643 #define WINDOW_RESOURCE 128
7644 #define TERM_WINDOW_RESOURCE 129
7646 #define DEFAULT_NUM_COLS 80
7648 #define MIN_DOC_SIZE 64
7649 #define MAX_DOC_SIZE 32767
7651 #define EXTRA_STACK_ALLOC (256 * 1024)
7653 #define ARGV_STRING_LIST_ID 129
7654 #define ABOUT_ALERT_ID 128
7655 #define RAM_TOO_LARGE_ALERT_ID 129
7657 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7658 Lisp_Object Qreverse
;
7660 /* True if using command key as meta key. */
7661 Lisp_Object Vmac_command_key_is_meta
;
7663 /* Modifier associated with the option key, or nil for normal behavior. */
7664 Lisp_Object Vmac_option_modifier
;
7666 /* True if the ctrl and meta keys should be reversed. */
7667 Lisp_Object Vmac_reverse_ctrl_meta
;
7669 /* True if the option and command modifiers should be used to emulate
7670 a three button mouse */
7671 Lisp_Object Vmac_emulate_three_button_mouse
;
7673 #if USE_CARBON_EVENTS
7674 /* True if the mouse wheel button (i.e. button 4) should map to
7675 mouse-2, instead of mouse-3. */
7676 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7678 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7679 for processing before Emacs sees it. */
7680 Lisp_Object Vmac_pass_command_to_system
;
7682 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7683 for processing before Emacs sees it. */
7684 Lisp_Object Vmac_pass_control_to_system
;
7687 /* Points to the variable `inev' in the function XTread_socket. It is
7688 used for passing an input event to the function back from
7689 Carbon/Apple event handlers. */
7690 static struct input_event
*read_socket_inev
= NULL
;
7692 /* Set in term/mac-win.el to indicate that event loop can now generate
7693 drag and drop events. */
7694 Lisp_Object Qmac_ready_for_drag_n_drop
;
7696 Point saved_menu_event_location
;
7699 static void init_required_apple_events (void);
7701 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7703 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7704 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7705 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7707 #if TARGET_API_MAC_CARBON
7709 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7710 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7711 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7712 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7715 static Lisp_Object Qapplication
, Qabout
;
7716 #if USE_CARBON_EVENTS
7718 extern void init_service_handler ();
7719 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
7721 /* Window Event Handler */
7722 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7725 OSErr
install_window_handler (WindowPtr
);
7727 extern void init_emacs_passwd_dir ();
7728 extern int emacs_main (int, char **, char **);
7730 extern void initialize_applescript();
7731 extern void terminate_applescript();
7734 #if USE_CARBON_EVENTS
7735 mac_to_emacs_modifiers (UInt32 mods
)
7737 mac_to_emacs_modifiers (EventModifiers mods
)
7740 unsigned int result
= 0;
7741 if (mods
& macShiftKey
)
7742 result
|= shift_modifier
;
7743 if (mods
& macCtrlKey
)
7744 result
|= ctrl_modifier
;
7745 if (mods
& macMetaKey
)
7746 result
|= meta_modifier
;
7747 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7748 result
|= alt_modifier
;
7749 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
7750 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
7752 result
|= XUINT(val
);
7759 mac_get_emulated_btn ( UInt32 modifiers
)
7762 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7763 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7764 if (modifiers
& cmdKey
)
7765 result
= cmdIs3
? 2 : 1;
7766 else if (modifiers
& optionKey
)
7767 result
= cmdIs3
? 1 : 2;
7772 #if USE_CARBON_EVENTS
7773 /* Obtains the event modifiers from the event ref and then calls
7774 mac_to_emacs_modifiers. */
7776 mac_event_to_emacs_modifiers (EventRef eventRef
)
7779 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7780 sizeof (UInt32
), NULL
, &mods
);
7781 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7782 GetEventClass(eventRef
) == kEventClassMouse
)
7784 mods
&= ~(optionKey
| cmdKey
);
7786 return mac_to_emacs_modifiers (mods
);
7789 /* Given an event ref, return the code to use for the mouse button
7790 code in the emacs input_event. */
7792 mac_get_mouse_btn (EventRef ref
)
7794 EventMouseButton result
= kEventMouseButtonPrimary
;
7795 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7796 sizeof (EventMouseButton
), NULL
, &result
);
7799 case kEventMouseButtonPrimary
:
7800 if (NILP (Vmac_emulate_three_button_mouse
))
7804 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7805 sizeof (UInt32
), NULL
, &mods
);
7806 return mac_get_emulated_btn(mods
);
7808 case kEventMouseButtonSecondary
:
7809 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7810 case kEventMouseButtonTertiary
:
7811 case 4: /* 4 is the number for the mouse wheel button */
7812 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7818 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7819 events. However the click of the mouse wheel is not converted to a
7820 mouseDown or mouseUp event. Likewise for dead key down events.
7821 This calls ConvertEventRef, but then checks to see if it is a mouse
7822 up/down, or a dead key down carbon event that has not been
7823 converted, and if so, converts it by hand (to be picked up in the
7824 XTread_socket loop). */
7825 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7827 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7832 switch (GetEventClass (eventRef
))
7834 case kEventClassMouse
:
7835 switch (GetEventKind (eventRef
))
7837 case kEventMouseDown
:
7838 eventRec
->what
= mouseDown
;
7843 eventRec
->what
= mouseUp
;
7852 case kEventClassKeyboard
:
7853 switch (GetEventKind (eventRef
))
7855 case kEventRawKeyDown
:
7857 unsigned char char_codes
;
7860 eventRec
->what
= keyDown
;
7861 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
7862 NULL
, sizeof (char), NULL
, &char_codes
);
7863 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
7864 NULL
, sizeof (UInt32
), NULL
, &key_code
);
7865 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
7881 /* Need where and when. */
7884 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
7885 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
7886 /* Use two step process because new event modifiers are 32-bit
7887 and old are 16-bit. Currently, only loss is NumLock & Fn. */
7888 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
7889 NULL
, sizeof (UInt32
), NULL
, &mods
);
7890 eventRec
->modifiers
= mods
;
7892 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7903 Handle menubar_handle
;
7904 MenuHandle menu_handle
;
7906 menubar_handle
= GetNewMBar (128);
7907 if(menubar_handle
== NULL
)
7909 SetMenuBar (menubar_handle
);
7912 #if !TARGET_API_MAC_CARBON
7913 menu_handle
= GetMenuHandle (M_APPLE
);
7914 if(menu_handle
!= NULL
)
7915 AppendResMenu (menu_handle
,'DRVR');
7923 do_init_managers (void)
7925 #if !TARGET_API_MAC_CARBON
7926 InitGraf (&qd
.thePort
);
7928 FlushEvents (everyEvent
, 0);
7933 #endif /* !TARGET_API_MAC_CARBON */
7936 #if !TARGET_API_MAC_CARBON
7937 /* set up some extra stack space for use by emacs */
7938 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7940 /* MaxApplZone must be called for AppleScript to execute more
7941 complicated scripts */
7944 #endif /* !TARGET_API_MAC_CARBON */
7948 do_check_ram_size (void)
7950 SInt32 physical_ram_size
, logical_ram_size
;
7952 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7953 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7954 || physical_ram_size
> (1 << VALBITS
)
7955 || logical_ram_size
> (1 << VALBITS
))
7957 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7963 do_window_update (WindowPtr win
)
7965 struct frame
*f
= mac_window_to_frame (win
);
7969 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7971 if (win
!= tip_window
)
7973 if (f
->async_visible
== 0)
7975 /* Update events may occur when a frame gets iconified. */
7977 f
->async_visible
= 1;
7978 f
->async_iconified
= 0;
7979 SET_FRAME_GARBAGED (f
);
7985 #if TARGET_API_MAC_CARBON
7986 RgnHandle region
= NewRgn ();
7988 GetPortVisibleRegion (GetWindowPort (win
), region
);
7989 GetRegionBounds (region
, &r
);
7990 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7991 UpdateControls (win
, region
);
7992 DisposeRgn (region
);
7994 r
= (*win
->visRgn
)->rgnBBox
;
7995 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
7996 UpdateControls (win
, win
->visRgn
);
8005 is_emacs_window (WindowPtr win
)
8007 Lisp_Object tail
, frame
;
8012 FOR_EACH_FRAME (tail
, frame
)
8013 if (FRAME_MAC_P (XFRAME (frame
)))
8014 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8023 /* Window-activate events will do the job. */
8029 /* Window-deactivate events will do the job. */
8034 do_apple_menu (SInt16 menu_item
)
8036 #if !TARGET_API_MAC_CARBON
8038 SInt16 da_driver_refnum
;
8040 if (menu_item
== I_ABOUT
)
8041 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8044 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8045 da_driver_refnum
= OpenDeskAcc (item_name
);
8047 #endif /* !TARGET_API_MAC_CARBON */
8051 do_menu_choice (SInt32 menu_choice
)
8053 SInt16 menu_id
, menu_item
;
8055 menu_id
= HiWord (menu_choice
);
8056 menu_item
= LoWord (menu_choice
);
8064 do_apple_menu (menu_item
);
8069 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8070 MenuHandle menu
= GetMenuHandle (menu_id
);
8075 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8076 menubar_selection_callback (f
, refcon
);
8085 /* Handle drags in size box. Based on code contributed by Ben
8086 Mesander and IM - Window Manager A. */
8089 do_grow_window (WindowPtr w
, EventRecord
*e
)
8092 int rows
, columns
, width
, height
;
8093 struct frame
*f
= mac_window_to_frame (w
);
8094 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8095 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8096 #if TARGET_API_MAC_CARBON
8102 if (size_hints
->flags
& PMinSize
)
8104 min_width
= size_hints
->min_width
;
8105 min_height
= size_hints
->min_height
;
8107 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8109 #if TARGET_API_MAC_CARBON
8110 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8112 height
= new_rect
.bottom
- new_rect
.top
;
8113 width
= new_rect
.right
- new_rect
.left
;
8115 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8116 /* see if it really changed size */
8119 height
= HiWord (grow_size
);
8120 width
= LoWord (grow_size
);
8123 if (width
!= FRAME_PIXEL_WIDTH (f
)
8124 || height
!= FRAME_PIXEL_HEIGHT (f
))
8126 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8127 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8129 x_set_window_size (f
, 0, columns
, rows
);
8134 /* Handle clicks in zoom box. Calculation of "standard state" based
8135 on code in IM - Window Manager A and code contributed by Ben
8136 Mesander. The standard state of an Emacs window is 80-characters
8137 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8140 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8143 Rect zoom_rect
, port_rect
;
8145 int w_title_height
, columns
, rows
, width
, height
;
8146 struct frame
*f
= mac_window_to_frame (w
);
8147 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8149 #if TARGET_API_MAC_CARBON
8151 Point standard_size
;
8153 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8154 standard_size
.v
= dpyinfo
->height
;
8156 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8157 zoom_in_or_out
= inZoomIn
;
8160 /* Adjust the standard size according to character boundaries. */
8162 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8163 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8164 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8165 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8166 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8167 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8168 && port_rect
.left
== zoom_rect
.left
8169 && port_rect
.top
== zoom_rect
.top
)
8170 zoom_in_or_out
= inZoomIn
;
8172 zoom_in_or_out
= inZoomOut
;
8175 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8177 #else /* not TARGET_API_MAC_CARBON */
8178 GetPort (&save_port
);
8180 SetPortWindowPort (w
);
8182 /* Clear window to avoid flicker. */
8183 EraseRect (&(w
->portRect
));
8184 if (zoom_in_or_out
== inZoomOut
)
8186 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8187 LocalToGlobal (&top_left
);
8189 /* calculate height of window's title bar */
8190 w_title_height
= top_left
.v
- 1
8191 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8193 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8194 zoom_rect
= qd
.screenBits
.bounds
;
8195 zoom_rect
.top
+= w_title_height
;
8196 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8198 zoom_rect
.right
= zoom_rect
.left
8199 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8201 /* Adjust the standard size according to character boundaries. */
8202 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8204 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8206 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8210 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8212 SetPort (save_port
);
8213 #endif /* not TARGET_API_MAC_CARBON */
8215 /* retrieve window size and update application values */
8216 #if TARGET_API_MAC_CARBON
8217 GetWindowPortBounds (w
, &port_rect
);
8219 port_rect
= w
->portRect
;
8221 height
= port_rect
.bottom
- port_rect
.top
;
8222 width
= port_rect
.right
- port_rect
.left
;
8224 if (width
!= FRAME_PIXEL_WIDTH (f
)
8225 || height
!= FRAME_PIXEL_HEIGHT (f
))
8227 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8228 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8230 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8231 SET_FRAME_GARBAGED (f
);
8232 cancel_mouse_face (f
);
8234 FRAME_PIXEL_WIDTH (f
) = width
;
8235 FRAME_PIXEL_HEIGHT (f
) = height
;
8237 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8240 /* Intialize AppleEvent dispatcher table for the required events. */
8242 init_required_apple_events ()
8247 /* Make sure we have apple events before starting. */
8248 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8252 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8255 #if TARGET_API_MAC_CARBON
8256 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8257 NewAEEventHandlerUPP
8258 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8261 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8262 NewAEEventHandlerProc
8263 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8269 #if TARGET_API_MAC_CARBON
8270 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8271 NewAEEventHandlerUPP
8272 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8275 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8276 NewAEEventHandlerProc
8277 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8283 #if TARGET_API_MAC_CARBON
8284 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8285 NewAEEventHandlerUPP
8286 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8289 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8290 NewAEEventHandlerProc
8291 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8297 #if TARGET_API_MAC_CARBON
8298 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8299 NewAEEventHandlerUPP
8300 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8303 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8304 NewAEEventHandlerProc
8305 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8313 mac_store_application_menu_event (event
)
8314 #if USE_CARBON_EVENTS
8320 struct input_event buf
;
8321 Lisp_Object frame
, entry
;
8325 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8326 buf
.kind
= MENU_BAR_EVENT
;
8327 buf
.frame_or_window
= frame
;
8329 kbd_buffer_store_event (&buf
);
8331 buf
.arg
= Qapplication
;
8332 kbd_buffer_store_event (&buf
);
8334 #if USE_CARBON_EVENTS
8335 switch (GetEventClass (event
))
8338 case kEventClassService
:
8339 buf
.arg
= Qservices
;
8340 kbd_buffer_store_event (&buf
);
8341 switch (GetEventKind (event
))
8343 case kEventServicePaste
:
8347 case kEventServicePerform
:
8350 CFStringRef message
;
8352 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8353 typeCFStringRef
, NULL
,
8354 sizeof (CFStringRef
), NULL
, &message
);
8356 kbd_buffer_store_event (&buf
);
8357 if (err
== noErr
&& message
)
8358 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8368 #endif /* MAC_OSX */
8369 case kEventClassCommand
:
8373 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8374 NULL
, sizeof (HICommand
), NULL
, &command
);
8375 switch (command
.commandID
)
8377 case kHICommandAbout
:
8381 case kHICommandPreferences
:
8382 entry
= Qpreferences
;
8384 #endif /* MAC_OSX */
8385 case kHICommandQuit
:
8397 #else /* USE_CARBON_EVENTS */
8400 case kHICommandAbout
:
8403 case kHICommandQuit
:
8412 kbd_buffer_store_event (&buf
);
8415 #if USE_CARBON_EVENTS
8416 static pascal OSStatus
8417 mac_handle_command_event (next_handler
, event
, data
)
8418 EventHandlerCallRef next_handler
;
8425 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8426 sizeof (HICommand
), NULL
, &command
);
8428 switch (command
.commandID
)
8430 case kHICommandAbout
:
8432 case kHICommandPreferences
:
8433 #endif /* MAC_OSX */
8434 result
= CallNextEventHandler (next_handler
, event
);
8435 if (result
!= eventNotHandledErr
)
8438 mac_store_application_menu_event (event
);
8445 return eventNotHandledErr
;
8449 init_command_handler ()
8452 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8453 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8455 if (handle_command_eventUPP
== NULL
)
8456 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8457 return InstallApplicationEventHandler (handle_command_eventUPP
,
8458 GetEventTypeCount (specs
), specs
,
8462 static pascal OSStatus
8463 mac_handle_window_event (next_handler
, event
, data
)
8464 EventHandlerCallRef next_handler
;
8471 XSizeHints
*size_hints
;
8473 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8474 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8476 switch (GetEventKind (event
))
8478 case kEventWindowUpdate
:
8479 result
= CallNextEventHandler (next_handler
, event
);
8480 if (result
!= eventNotHandledErr
)
8483 do_window_update (wp
);
8486 case kEventWindowBoundsChanging
:
8487 result
= CallNextEventHandler (next_handler
, event
);
8488 if (result
!= eventNotHandledErr
)
8491 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8492 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8493 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8494 if ((attributes
& kWindowBoundsChangeUserResize
)
8495 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8496 == (PResizeInc
| PBaseSize
| PMinSize
)))
8501 GetEventParameter (event
, kEventParamCurrentBounds
,
8503 NULL
, sizeof (Rect
), NULL
, &bounds
);
8504 width
= bounds
.right
- bounds
.left
;
8505 height
= bounds
.bottom
- bounds
.top
;
8507 if (width
< size_hints
->min_width
)
8508 width
= size_hints
->min_width
;
8510 width
= size_hints
->base_width
8511 + (int) ((width
- size_hints
->base_width
)
8512 / (float) size_hints
->width_inc
+ .5)
8513 * size_hints
->width_inc
;
8515 if (height
< size_hints
->min_height
)
8516 height
= size_hints
->min_height
;
8518 height
= size_hints
->base_height
8519 + (int) ((height
- size_hints
->base_height
)
8520 / (float) size_hints
->height_inc
+ .5)
8521 * size_hints
->height_inc
;
8523 bounds
.right
= bounds
.left
+ width
;
8524 bounds
.bottom
= bounds
.top
+ height
;
8525 SetEventParameter (event
, kEventParamCurrentBounds
,
8526 typeQDRectangle
, sizeof (Rect
), &bounds
);
8531 case kEventWindowShown
:
8532 case kEventWindowHidden
:
8533 case kEventWindowExpanded
:
8534 case kEventWindowCollapsed
:
8535 result
= CallNextEventHandler (next_handler
, event
);
8537 mac_handle_visibility_change (mac_window_to_frame (wp
));
8543 return eventNotHandledErr
;
8546 static pascal OSStatus
8547 mac_handle_mouse_event (next_handler
, event
, data
)
8548 EventHandlerCallRef next_handler
;
8554 switch (GetEventKind (event
))
8556 case kEventMouseWheelMoved
:
8560 EventMouseWheelAxis axis
;
8564 result
= CallNextEventHandler (next_handler
, event
);
8565 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
8568 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
8569 NULL
, sizeof (WindowRef
), NULL
, &wp
);
8570 f
= mac_window_to_frame (wp
);
8571 if (f
!= mac_focus_frame (&one_mac_display_info
))
8574 GetEventParameter (event
, kEventParamMouseWheelAxis
,
8575 typeMouseWheelAxis
, NULL
,
8576 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
8577 if (axis
!= kEventMouseWheelAxisY
)
8580 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
8581 NULL
, sizeof (SInt32
), NULL
, &delta
);
8582 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
8583 NULL
, sizeof (Point
), NULL
, &point
);
8584 read_socket_inev
->kind
= WHEEL_EVENT
;
8585 read_socket_inev
->code
= 0;
8586 read_socket_inev
->modifiers
=
8587 (mac_event_to_emacs_modifiers (event
)
8588 | ((delta
< 0) ? down_modifier
: up_modifier
));
8589 SetPortWindowPort (wp
);
8590 GlobalToLocal (&point
);
8591 XSETINT (read_socket_inev
->x
, point
.h
);
8592 XSETINT (read_socket_inev
->y
, point
.v
);
8593 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
8603 return eventNotHandledErr
;
8605 #endif /* USE_CARBON_EVENTS */
8609 install_window_handler (window
)
8613 #if USE_CARBON_EVENTS
8614 EventTypeSpec specs_window
[] =
8615 {{kEventClassWindow
, kEventWindowUpdate
},
8616 {kEventClassWindow
, kEventWindowBoundsChanging
},
8617 {kEventClassWindow
, kEventWindowShown
},
8618 {kEventClassWindow
, kEventWindowHidden
},
8619 {kEventClassWindow
, kEventWindowExpanded
},
8620 {kEventClassWindow
, kEventWindowCollapsed
}};
8621 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
8622 static EventHandlerUPP handle_window_eventUPP
= NULL
;
8623 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
8625 if (handle_window_eventUPP
== NULL
)
8626 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
8627 if (handle_mouse_eventUPP
== NULL
)
8628 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
8629 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
8630 GetEventTypeCount (specs_window
),
8631 specs_window
, NULL
, NULL
);
8633 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
8634 GetEventTypeCount (specs_mouse
),
8635 specs_mouse
, NULL
, NULL
);
8637 #if TARGET_API_MAC_CARBON
8638 if (mac_do_track_dragUPP
== NULL
)
8639 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8640 if (mac_do_receive_dragUPP
== NULL
)
8641 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8644 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8646 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8652 remove_window_handler (window
)
8655 #if TARGET_API_MAC_CARBON
8656 if (mac_do_track_dragUPP
)
8657 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8658 if (mac_do_receive_dragUPP
)
8659 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8663 /* Open Application Apple Event */
8665 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8671 /* Called when we receive an AppleEvent with an ID of
8672 "kAEOpenDocuments". This routine gets the direct parameter,
8673 extracts the FSSpecs in it, and puts their names on a list. */
8674 #pragma options align=mac68k
8675 typedef struct SelectionRange
{
8676 short unused1
; // 0 (not used)
8677 short lineNum
; // line to select (<0 to specify range)
8678 long startRange
; // start of selection range (if line < 0)
8679 long endRange
; // end of selection range (if line < 0)
8680 long unused2
; // 0 (not used)
8681 long theDate
; // modification date/time
8683 #pragma options align=reset
8686 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8691 DescType actual_type
;
8693 SelectionRange position
;
8694 Lisp_Object file_list
= Qnil
;
8696 xassert (read_socket_inev
);
8698 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8700 goto descriptor_error_exit
;
8702 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8704 file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8705 make_number (position
.startRange
+ 1),
8706 make_number (position
.endRange
+ 1)),
8709 /* Check to see that we got all of the required parameters from the
8710 event descriptor. For an 'odoc' event this should just be the
8712 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8713 &actual_type
, (Ptr
) &keyword
,
8714 sizeof (keyword
), &actual_size
);
8715 /* No error means that we found some unused parameters.
8716 errAEDescNotFound means that there are no more parameters. If we
8717 get an error code other than that, flag it. */
8718 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8720 err
= errAEEventNotHandled
;
8725 /* Got all the parameters we need. Now, go through the direct
8726 object list and parse it up. */
8728 long num_files_to_open
;
8730 err
= AECountItems (&the_desc
, &num_files_to_open
);
8735 /* AE file list is one based so just use that for indexing here. */
8736 for (i
= 1; i
<= num_files_to_open
; i
++)
8738 char unix_path_name
[MAXPATHLEN
];
8742 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
8743 &actual_type
, &fref
, sizeof (FSRef
),
8745 if (err
!= noErr
|| actual_type
!= typeFSRef
)
8748 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
8753 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
8754 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
8755 if (err
!= noErr
) continue;
8757 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
8758 sizeof (unix_path_name
) - 1) == noErr
)
8760 /* x-dnd functions expect undecoded filenames. */
8761 file_list
= Fcons (make_unibyte_string (unix_path_name
,
8762 strlen (unix_path_name
)),
8767 /* Build a DRAG_N_DROP_EVENT type event as is done in
8768 constuct_drag_n_drop in w32term.c. */
8769 if (!NILP (file_list
))
8771 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8775 read_socket_inev
->kind
= DRAG_N_DROP_EVENT
;
8776 read_socket_inev
->code
= 0;
8777 read_socket_inev
->modifiers
= 0;
8779 XSETINT (read_socket_inev
->x
, 0);
8780 XSETINT (read_socket_inev
->y
, 0);
8782 XSETFRAME (frame
, f
);
8783 read_socket_inev
->frame_or_window
= Fcons (frame
, file_list
);
8786 /* Regardless of whether Emacs was suspended or in the
8787 foreground, ask it to redraw its entire screen. Otherwise
8788 parts of the screen can be left in an inconsistent
8790 wp
= FRAME_MAC_WINDOW (f
);
8792 #if TARGET_API_MAC_CARBON
8796 GetWindowPortBounds (wp
, &r
);
8797 InvalWindowRect (wp
, &r
);
8799 #else /* not TARGET_API_MAC_CARBON */
8800 InvalRect (&(wp
->portRect
));
8801 #endif /* not TARGET_API_MAC_CARBON */
8807 /* Nuke the coerced file list in any case */
8808 err2
= AEDisposeDesc(&the_desc
);
8810 descriptor_error_exit
:
8811 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8816 #if TARGET_API_MAC_CARBON
8818 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
8819 void *handlerRefCon
, DragReference theDrag
)
8821 static int can_accept
;
8824 ItemReference theItem
;
8825 FlavorFlags theFlags
;
8828 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8829 return dragNotAcceptedErr
;
8833 case kDragTrackingEnterHandler
:
8834 CountDragItems (theDrag
, &items
);
8836 for (index
= 1; index
<= items
; index
++)
8838 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8839 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8840 if (result
== noErr
)
8848 case kDragTrackingEnterWindow
:
8851 RgnHandle hilite_rgn
= NewRgn ();
8853 struct frame
*f
= mac_window_to_frame (window
);
8855 GetWindowPortBounds (window
, &r
);
8856 OffsetRect (&r
, -r
.left
, -r
.top
);
8857 RectRgn (hilite_rgn
, &r
);
8858 ShowDragHilite (theDrag
, hilite_rgn
, true);
8859 DisposeRgn (hilite_rgn
);
8860 SetThemeCursor (kThemeCopyArrowCursor
);
8864 case kDragTrackingInWindow
:
8867 case kDragTrackingLeaveWindow
:
8870 struct frame
*f
= mac_window_to_frame (window
);
8872 HideDragHilite (theDrag
);
8873 SetThemeCursor (kThemeArrowCursor
);
8877 case kDragTrackingLeaveHandler
:
8885 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
8886 DragReference theDrag
)
8890 FlavorFlags theFlags
;
8893 ItemReference theItem
;
8895 Size size
= sizeof (HFSFlavor
);
8896 Lisp_Object file_list
;
8898 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
8899 return dragNotAcceptedErr
;
8902 GetDragMouse (theDrag
, &mouse
, 0L);
8903 CountDragItems (theDrag
, &items
);
8904 for (index
= 1; index
<= items
; index
++)
8906 /* Only handle file references. */
8907 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
8908 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
8909 if (result
== noErr
)
8914 char unix_path_name
[MAXPATHLEN
];
8916 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
8918 /* Use Carbon routines, otherwise it converts the file name
8919 to /Macintosh HD/..., which is not correct. */
8920 FSpMakeFSRef (&data
.fileSpec
, &fref
);
8921 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
8923 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
8924 sizeof (unix_path_name
) - 1) == noErr
)
8926 /* x-dnd functions expect undecoded filenames. */
8927 file_list
= Fcons (make_unibyte_string (unix_path_name
,
8928 strlen (unix_path_name
)),
8932 /* If there are items in the list, construct an event and post it to
8933 the queue like an interrupt using kbd_buffer_store_event. */
8934 if (!NILP (file_list
))
8936 struct input_event event
;
8938 struct frame
*f
= mac_window_to_frame (window
);
8941 GlobalToLocal (&mouse
);
8942 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
8944 event
.kind
= DRAG_N_DROP_EVENT
;
8946 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
8947 event
.timestamp
= TickCount () * (1000 / 60);
8948 XSETINT (event
.x
, mouse
.h
);
8949 XSETINT (event
.y
, mouse
.v
);
8950 XSETFRAME (frame
, f
);
8951 event
.frame_or_window
= Fcons (frame
, file_list
);
8953 /* Post to the interrupt queue */
8954 kbd_buffer_store_event (&event
);
8955 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8957 ProcessSerialNumber psn
;
8958 GetCurrentProcess (&psn
);
8959 SetFrontProcess (&psn
);
8965 return dragNotAcceptedErr
;
8970 /* Print Document Apple Event */
8972 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
8974 return errAEEventNotHandled
;
8979 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
8981 #if USE_CARBON_EVENTS
8983 EventRef event
= NULL
;
8984 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
8986 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
8987 kEventAttributeUserEvent
, &event
);
8989 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
8990 sizeof (HICommand
), &quit_command
);
8992 mac_store_application_menu_event (event
);
8994 ReleaseEvent (event
);
8999 return errAEEventNotHandled
;
9001 mac_store_application_menu_event (kHICommandQuit
);
9010 profiler_exit_proc ()
9012 ProfilerDump ("\pEmacs.prof");
9017 /* These few functions implement Emacs as a normal Mac application
9018 (almost): set up the heap and the Toolbox, handle necessary system
9019 events plus a few simple menu events. They also set up Emacs's
9020 access to functions defined in the rest of this file. Emacs uses
9021 function hooks to perform all its terminal I/O. A complete list of
9022 these functions appear in termhooks.h. For what they do, read the
9023 comments there and see also w32term.c and xterm.c. What's
9024 noticeably missing here is the event loop, which is normally
9025 present in most Mac application. After performing the necessary
9026 Mac initializations, main passes off control to emacs_main
9027 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9028 (defined further below) to read input. This is where
9029 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9036 #if __profile__ /* is the profiler on? */
9037 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9042 /* set creator and type for files created by MSL */
9047 do_init_managers ();
9052 do_check_ram_size ();
9055 init_emacs_passwd_dir ();
9059 initialize_applescript ();
9061 init_required_apple_events ();
9067 /* set up argv array from STR# resource */
9068 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9072 /* free up AppleScript resources on exit */
9073 atexit (terminate_applescript
);
9075 #if __profile__ /* is the profiler on? */
9076 atexit (profiler_exit_proc
);
9079 /* 3rd param "envp" never used in emacs_main */
9080 (void) emacs_main (argc
, argv
, 0);
9083 /* Never reached - real exit in Fkill_emacs */
9088 /* Table for translating Mac keycode to X keysym values. Contributed
9090 Mapping for special keys is now identical to that in Apple X11
9091 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9092 on the right of the Cmd key on laptops, and fn + `enter' (->
9094 static unsigned char keycode_to_xkeysym_table
[] = {
9095 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9096 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9097 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9099 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9100 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9101 /*0x38*/ 0, 0, 0, 0,
9102 /*0x3C*/ 0, 0, 0, 0,
9104 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9105 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9106 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9107 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9109 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9110 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9111 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9112 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9114 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9115 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9116 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9117 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9119 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9120 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9121 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9122 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9126 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9128 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9129 return *xKeySym
!= 0;
9132 #if !USE_CARBON_EVENTS
9133 static RgnHandle mouse_region
= NULL
;
9136 mac_wait_next_event (er
, sleep_time
, dequeue
)
9141 static EventRecord er_buf
= {nullEvent
};
9142 UInt32 target_tick
, current_tick
;
9143 EventMask event_mask
;
9145 if (mouse_region
== NULL
)
9146 mouse_region
= NewRgn ();
9148 event_mask
= everyEvent
;
9149 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
9150 event_mask
-= highLevelEventMask
;
9152 current_tick
= TickCount ();
9153 target_tick
= current_tick
+ sleep_time
;
9155 if (er_buf
.what
== nullEvent
)
9156 while (!WaitNextEvent (event_mask
, &er_buf
,
9157 target_tick
- current_tick
, mouse_region
))
9159 current_tick
= TickCount ();
9160 if (target_tick
<= current_tick
)
9166 er_buf
.what
= nullEvent
;
9169 #endif /* not USE_CARBON_EVENTS */
9171 /* Emacs calls this whenever it wants to read an input event from the
9174 XTread_socket (sd
, expected
, hold_quit
)
9176 struct input_event
*hold_quit
;
9178 struct input_event inev
;
9180 #if USE_CARBON_EVENTS
9182 EventTargetRef toolbox_dispatcher
;
9185 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9187 if (interrupt_input_blocked
)
9189 interrupt_input_pending
= 1;
9193 interrupt_input_pending
= 0;
9196 /* So people can tell when we have read the available input. */
9197 input_signal_count
++;
9199 #if USE_CARBON_EVENTS
9200 toolbox_dispatcher
= GetEventDispatcherTarget ();
9202 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9203 kEventRemoveFromQueue
, &eventRef
))
9204 #else /* !USE_CARBON_EVENTS */
9205 while (mac_wait_next_event (&er
, 0, true))
9206 #endif /* !USE_CARBON_EVENTS */
9210 unsigned long timestamp
;
9212 /* It is necessary to set this (additional) argument slot of an
9213 event to nil because keyboard.c protects incompletely
9214 processed event from being garbage collected by placing them
9215 in the kbd_buffer_gcpro vector. */
9217 inev
.kind
= NO_EVENT
;
9220 #if USE_CARBON_EVENTS
9221 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9223 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9226 #if USE_CARBON_EVENTS
9227 /* Handle new events */
9228 if (!mac_convert_event_ref (eventRef
, &er
))
9230 /* There used to be a handler for the kEventMouseWheelMoved
9231 event here. But as of Mac OS X 10.4, this kind of event
9232 is not directly posted to the main event queue by
9233 two-finger scrolling on the trackpad. Instead, some
9234 private event is posted and it is converted to a wheel
9235 event by the default handler for the application target.
9236 The converted one can be received by a Carbon event
9237 handler installed on a window target. */
9238 read_socket_inev
= &inev
;
9239 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9240 read_socket_inev
= NULL
;
9243 #endif /* USE_CARBON_EVENTS */
9249 WindowPtr window_ptr
;
9250 ControlPartCode part_code
;
9253 #if USE_CARBON_EVENTS
9254 /* This is needed to send mouse events like aqua window
9255 buttons to the correct handler. */
9256 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9257 != eventNotHandledErr
)
9261 if (dpyinfo
->grabbed
&& last_mouse_frame
9262 && FRAME_LIVE_P (last_mouse_frame
))
9264 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9265 part_code
= inContent
;
9269 part_code
= FindWindow (er
.where
, &window_ptr
);
9270 if (tip_window
&& window_ptr
== tip_window
)
9272 HideWindow (tip_window
);
9273 part_code
= FindWindow (er
.where
, &window_ptr
);
9277 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
9283 f
= mac_focus_frame (dpyinfo
);
9284 saved_menu_event_location
= er
.where
;
9285 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9286 XSETFRAME (inev
.frame_or_window
, f
);
9290 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9291 SelectWindow (window_ptr
);
9294 ControlPartCode control_part_code
;
9296 Point mouse_loc
= er
.where
;
9298 ControlKind control_kind
;
9301 f
= mac_window_to_frame (window_ptr
);
9302 /* convert to local coordinates of new window */
9303 SetPortWindowPort (window_ptr
);
9305 GlobalToLocal (&mouse_loc
);
9306 #if TARGET_API_MAC_CARBON
9307 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9308 &control_part_code
);
9311 GetControlKind (ch
, &control_kind
);
9314 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9318 #if USE_CARBON_EVENTS
9319 inev
.code
= mac_get_mouse_btn (eventRef
);
9320 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9322 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9323 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9325 XSETINT (inev
.x
, mouse_loc
.h
);
9326 XSETINT (inev
.y
, mouse_loc
.v
);
9328 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9330 #ifndef USE_TOOLKIT_SCROLL_BARS
9331 /* control_part_code becomes kControlNoPart if
9332 a progress indicator is clicked. */
9333 && control_part_code
!= kControlNoPart
9334 #else /* USE_TOOLKIT_SCROLL_BARS */
9336 && control_kind
.kind
== kControlKindScrollBar
9337 #endif /* MAC_OSX */
9338 #endif /* USE_TOOLKIT_SCROLL_BARS */
9341 struct scroll_bar
*bar
;
9343 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9345 bar
= tracked_scroll_bar
;
9346 #ifndef USE_TOOLKIT_SCROLL_BARS
9347 control_part_code
= kControlIndicatorPart
;
9351 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9352 #ifdef USE_TOOLKIT_SCROLL_BARS
9353 /* Make the "Ctrl-Mouse-2 splits window" work
9354 for toolkit scroll bars. */
9355 if (er
.modifiers
& controlKey
)
9356 x_scroll_bar_handle_click (bar
, control_part_code
,
9358 else if (er
.what
== mouseDown
)
9359 x_scroll_bar_handle_press (bar
, control_part_code
,
9362 x_scroll_bar_handle_release (bar
, &inev
);
9363 #else /* not USE_TOOLKIT_SCROLL_BARS */
9364 x_scroll_bar_handle_click (bar
, control_part_code
,
9366 if (er
.what
== mouseDown
9367 && control_part_code
== kControlIndicatorPart
)
9368 tracked_scroll_bar
= bar
;
9370 tracked_scroll_bar
= NULL
;
9371 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9376 int x
= mouse_loc
.h
;
9377 int y
= mouse_loc
.v
;
9379 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9380 if (EQ (window
, f
->tool_bar_window
))
9382 if (er
.what
== mouseDown
)
9383 handle_tool_bar_click (f
, x
, y
, 1, 0);
9385 handle_tool_bar_click (f
, x
, y
, 0,
9391 XSETFRAME (inev
.frame_or_window
, f
);
9392 inev
.kind
= MOUSE_CLICK_EVENT
;
9396 if (er
.what
== mouseDown
)
9398 dpyinfo
->grabbed
|= (1 << inev
.code
);
9399 last_mouse_frame
= f
;
9400 /* Ignore any mouse motion that happened
9401 before this event; any subsequent
9402 mouse-movement Emacs events should reflect
9403 only motion after the ButtonPress. */
9408 last_tool_bar_item
= -1;
9412 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9413 /* If a button is released though it was not
9414 previously pressed, that would be because
9415 of multi-button emulation. */
9416 dpyinfo
->grabbed
= 0;
9418 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9421 #ifdef USE_TOOLKIT_SCROLL_BARS
9422 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9427 inev
.modifiers
|= down_modifier
;
9430 inev
.modifiers
|= up_modifier
;
9437 #if TARGET_API_MAC_CARBON
9438 DragWindow (window_ptr
, er
.where
, NULL
);
9439 #else /* not TARGET_API_MAC_CARBON */
9440 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9441 #endif /* not TARGET_API_MAC_CARBON */
9442 /* Update the frame parameters. */
9444 struct frame
*f
= mac_window_to_frame (window_ptr
);
9446 if (f
&& !f
->async_iconified
)
9447 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9452 if (TrackGoAway (window_ptr
, er
.where
))
9454 inev
.kind
= DELETE_WINDOW_EVENT
;
9455 XSETFRAME (inev
.frame_or_window
,
9456 mac_window_to_frame (window_ptr
));
9460 /* window resize handling added --ben */
9462 do_grow_window (window_ptr
, &er
);
9465 /* window zoom handling added --ben */
9468 if (TrackBox (window_ptr
, er
.where
, part_code
))
9469 do_zoom_window (window_ptr
, part_code
);
9479 #if USE_CARBON_EVENTS
9480 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9481 != eventNotHandledErr
)
9484 do_window_update ((WindowPtr
) er
.message
);
9489 #if USE_CARBON_EVENTS
9490 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9491 != eventNotHandledErr
)
9494 switch ((er
.message
>> 24) & 0x000000FF)
9496 case suspendResumeMessage
:
9497 if ((er
.message
& resumeFlag
) == 1)
9503 case mouseMovedMessage
:
9504 #if !USE_CARBON_EVENTS
9505 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9506 er
.where
.h
+ 1, er
.where
.v
+ 1);
9508 previous_help_echo_string
= help_echo_string
;
9509 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
9512 if (dpyinfo
->grabbed
&& last_mouse_frame
9513 && FRAME_LIVE_P (last_mouse_frame
))
9514 f
= last_mouse_frame
;
9516 f
= dpyinfo
->x_focus_frame
;
9518 if (dpyinfo
->mouse_face_hidden
)
9520 dpyinfo
->mouse_face_hidden
= 0;
9521 clear_mouse_face (dpyinfo
);
9526 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9527 Point mouse_pos
= er
.where
;
9529 SetPortWindowPort (wp
);
9531 GlobalToLocal (&mouse_pos
);
9533 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9534 #ifdef USE_TOOLKIT_SCROLL_BARS
9535 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9537 #else /* not USE_TOOLKIT_SCROLL_BARS */
9538 x_scroll_bar_note_movement (tracked_scroll_bar
,
9540 - XINT (tracked_scroll_bar
->top
),
9541 er
.when
* (1000 / 60));
9542 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9545 /* Generate SELECT_WINDOW_EVENTs when needed. */
9546 if (mouse_autoselect_window
)
9550 window
= window_from_coordinates (f
,
9555 /* Window will be selected only when it is
9556 not selected now and last mouse movement
9557 event was not in it. Minibuffer window
9558 will be selected iff it is active. */
9559 if (WINDOWP (window
)
9560 && !EQ (window
, last_window
)
9561 && !EQ (window
, selected_window
))
9563 inev
.kind
= SELECT_WINDOW_EVENT
;
9564 inev
.frame_or_window
= window
;
9569 note_mouse_movement (f
, &mouse_pos
);
9573 /* If the contents of the global variable
9574 help_echo_string has changed, generate a
9576 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9584 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9586 #if USE_CARBON_EVENTS
9587 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9588 != eventNotHandledErr
)
9591 if (window_ptr
== tip_window
)
9593 HideWindow (tip_window
);
9597 if (!is_emacs_window (window_ptr
))
9600 if ((er
.modifiers
& activeFlag
) != 0)
9602 /* A window has been activated */
9603 Point mouse_loc
= er
.where
;
9605 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9607 SetPortWindowPort (window_ptr
);
9608 GlobalToLocal (&mouse_loc
);
9609 /* Window-activated event counts as mouse movement,
9610 so update things that depend on mouse position. */
9611 note_mouse_movement (mac_window_to_frame (window_ptr
),
9616 /* A window has been deactivated */
9617 #if USE_TOOLKIT_SCROLL_BARS
9618 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9620 struct input_event event
;
9623 event
.kind
= NO_EVENT
;
9624 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
9625 if (event
.kind
!= NO_EVENT
)
9627 event
.timestamp
= timestamp
;
9628 kbd_buffer_store_event_hold (&event
, hold_quit
);
9633 dpyinfo
->grabbed
= 0;
9635 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9637 f
= mac_window_to_frame (window_ptr
);
9638 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9640 /* If we move outside the frame, then we're
9641 certainly no longer on any text in the
9643 clear_mouse_face (dpyinfo
);
9644 dpyinfo
->mouse_face_mouse_frame
= 0;
9647 /* Generate a nil HELP_EVENT to cancel a help-echo.
9648 Do it only if there's something to cancel.
9649 Otherwise, the startup message is cleared when the
9650 mouse leaves the frame. */
9651 if (any_help_event_p
)
9660 int keycode
= (er
.message
& keyCodeMask
) >> 8;
9663 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9664 /* When using Carbon Events, we need to pass raw keyboard
9665 events to the TSM ourselves. If TSM handles it, it
9666 will pass back noErr, otherwise it will pass back
9667 "eventNotHandledErr" and we can process it
9669 if ((!NILP (Vmac_pass_command_to_system
)
9670 || !(er
.modifiers
& cmdKey
))
9671 && (!NILP (Vmac_pass_control_to_system
)
9672 || !(er
.modifiers
& controlKey
))
9673 && (!NILP (Vmac_command_key_is_meta
)
9674 && NILP (Vmac_option_modifier
)
9675 || !(er
.modifiers
& optionKey
)))
9676 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9677 != eventNotHandledErr
)
9682 if (dpyinfo
->x_focus_frame
== NULL
)
9684 /* Beep if keyboard input occurs when all the frames
9692 static SInt16 last_key_script
= -1;
9693 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
9695 if (last_key_script
!= current_key_script
)
9697 struct input_event event
;
9700 event
.kind
= LANGUAGE_CHANGE_EVENT
;
9702 event
.code
= current_key_script
;
9703 event
.timestamp
= timestamp
;
9704 kbd_buffer_store_event (&event
);
9707 last_key_script
= current_key_script
;
9712 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9714 clear_mouse_face (dpyinfo
);
9715 dpyinfo
->mouse_face_hidden
= 1;
9718 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9720 inev
.code
= 0xff00 | xkeysym
;
9721 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9725 if (er
.modifiers
& (controlKey
|
9726 (NILP (Vmac_command_key_is_meta
) ? optionKey
9729 /* This code comes from Keyboard Resource,
9730 Appendix C of IM - Text. This is necessary
9731 since shift is ignored in KCHR table
9732 translation when option or command is pressed.
9733 It also does not translate correctly
9734 control-shift chars like C-% so mask off shift
9736 int new_modifiers
= er
.modifiers
& 0xe600;
9737 /* mask off option and command */
9738 int new_keycode
= keycode
| new_modifiers
;
9739 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9740 unsigned long some_state
= 0;
9741 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9742 &some_state
) & 0xff;
9744 else if (!NILP (Vmac_option_modifier
)
9745 && (er
.modifiers
& optionKey
))
9747 /* When using the option key as an emacs modifier,
9748 convert the pressed key code back to one
9749 without the Mac option modifier applied. */
9750 int new_modifiers
= er
.modifiers
& ~optionKey
;
9751 int new_keycode
= keycode
| new_modifiers
;
9752 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9753 unsigned long some_state
= 0;
9754 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
9755 &some_state
) & 0xff;
9758 inev
.code
= er
.message
& charCodeMask
;
9759 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
9763 #if USE_CARBON_EVENTS
9764 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9766 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9768 inev
.modifiers
|= (extra_keyboard_modifiers
9769 & (meta_modifier
| alt_modifier
9770 | hyper_modifier
| super_modifier
));
9771 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
9774 case kHighLevelEvent
:
9775 read_socket_inev
= &inev
;
9776 AEProcessAppleEvent (&er
);
9777 read_socket_inev
= NULL
;
9783 #if USE_CARBON_EVENTS
9784 ReleaseEvent (eventRef
);
9787 if (inev
.kind
!= NO_EVENT
)
9789 inev
.timestamp
= timestamp
;
9790 kbd_buffer_store_event_hold (&inev
, hold_quit
);
9795 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
9800 XSETFRAME (frame
, f
);
9806 any_help_event_p
= 1;
9807 gen_help_event (help_echo_string
, frame
, help_echo_window
,
9808 help_echo_object
, help_echo_pos
);
9812 help_echo_string
= Qnil
;
9813 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
9820 /* If the focus was just given to an autoraising frame,
9822 /* ??? This ought to be able to handle more than one such frame. */
9823 if (pending_autoraise_frame
)
9825 x_raise_frame (pending_autoraise_frame
);
9826 pending_autoraise_frame
= 0;
9829 #if !USE_CARBON_EVENTS
9830 /* Check which frames are still visible. We do this here because
9831 there doesn't seem to be any direct notification from the Window
9832 Manager that the visibility of a window has changed (at least,
9833 not in all cases). */
9835 Lisp_Object tail
, frame
;
9837 FOR_EACH_FRAME (tail
, frame
)
9839 struct frame
*f
= XFRAME (frame
);
9841 /* The tooltip has been drawn already. Avoid the
9842 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
9843 if (EQ (frame
, tip_frame
))
9846 if (FRAME_MAC_P (f
))
9847 mac_handle_visibility_change (f
);
9857 /* Need to override CodeWarrior's input function so no conversion is
9858 done on newlines Otherwise compiled functions in .elc files will be
9859 read incorrectly. Defined in ...:MSL C:MSL
9860 Common:Source:buffer_io.c. */
9863 __convert_to_newlines (unsigned char * p
, size_t * n
)
9869 __convert_from_newlines (unsigned char * p
, size_t * n
)
9877 make_mac_terminal_frame (struct frame
*f
)
9882 XSETFRAME (frame
, f
);
9884 f
->output_method
= output_mac
;
9885 f
->output_data
.mac
= (struct mac_output
*)
9886 xmalloc (sizeof (struct mac_output
));
9887 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
9889 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
9891 FRAME_COLS (f
) = 96;
9892 FRAME_LINES (f
) = 4;
9894 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
9895 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
9897 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
9899 f
->output_data
.mac
->cursor_pixel
= 0;
9900 f
->output_data
.mac
->border_pixel
= 0x00ff00;
9901 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
9902 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
9904 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
9905 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
9906 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
9907 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
9908 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
9909 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
9911 FRAME_FONTSET (f
) = -1;
9912 f
->output_data
.mac
->explicit_parent
= 0;
9915 f
->border_width
= 0;
9917 f
->internal_border_width
= 0;
9922 f
->new_text_cols
= 0;
9923 f
->new_text_lines
= 0;
9925 SetRect (&r
, f
->left_pos
, f
->top_pos
,
9926 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
9927 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
9931 if (!(FRAME_MAC_WINDOW (f
) =
9932 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
9933 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
9935 /* so that update events can find this mac_output struct */
9936 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
9942 /* Need to be initialized for unshow_buffer in window.c. */
9943 selected_window
= f
->selected_window
;
9945 Fmodify_frame_parameters (frame
,
9946 Fcons (Fcons (Qfont
,
9947 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
9948 Fmodify_frame_parameters (frame
,
9949 Fcons (Fcons (Qforeground_color
,
9950 build_string ("black")), Qnil
));
9951 Fmodify_frame_parameters (frame
,
9952 Fcons (Fcons (Qbackground_color
,
9953 build_string ("white")), Qnil
));
9958 /***********************************************************************
9960 ***********************************************************************/
9962 int mac_initialized
= 0;
9965 mac_initialize_display_info ()
9967 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9968 GDHandle main_device_handle
;
9970 bzero (dpyinfo
, sizeof (*dpyinfo
));
9973 dpyinfo
->mac_id_name
9974 = (char *) xmalloc (SCHARS (Vinvocation_name
)
9975 + SCHARS (Vsystem_name
)
9977 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
9978 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
9980 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
9981 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
9984 main_device_handle
= LMGetMainDevice();
9986 dpyinfo
->reference_count
= 0;
9987 dpyinfo
->resx
= 75.0;
9988 dpyinfo
->resy
= 75.0;
9989 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
9991 /* HasDepth returns true if it is possible to have a 32 bit display,
9992 but this may not be what is actually used. Mac OSX can do better.
9993 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9994 header for CGGetActiveDisplayList says that the first display returned
9995 is the active one, so we use that. */
9997 CGDirectDisplayID disp_id
[1];
9998 CGDisplayCount disp_count
;
9999 CGDisplayErr error_code
;
10001 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10002 if (error_code
!= 0)
10003 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10005 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10008 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10009 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10010 gdDevType
, dpyinfo
->color_p
))
10013 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10014 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10015 dpyinfo
->grabbed
= 0;
10016 dpyinfo
->root_window
= NULL
;
10017 dpyinfo
->image_cache
= make_image_cache ();
10019 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10020 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10021 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10022 dpyinfo
->mouse_face_window
= Qnil
;
10023 dpyinfo
->mouse_face_overlay
= Qnil
;
10024 dpyinfo
->mouse_face_hidden
= 0;
10029 mac_make_rdb (xrm_option
)
10032 XrmDatabase database
;
10034 database
= xrm_get_preference_database (NULL
);
10036 xrm_merge_string_database (database
, xrm_option
);
10041 struct mac_display_info
*
10042 mac_term_init (display_name
, xrm_option
, resource_name
)
10043 Lisp_Object display_name
;
10045 char *resource_name
;
10047 struct mac_display_info
*dpyinfo
;
10051 if (!mac_initialized
)
10054 mac_initialized
= 1;
10057 if (x_display_list
)
10058 error ("Sorry, this version can only handle one display");
10060 mac_initialize_display_info ();
10062 dpyinfo
= &one_mac_display_info
;
10064 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10066 /* Put this display on the chain. */
10067 dpyinfo
->next
= x_display_list
;
10068 x_display_list
= dpyinfo
;
10070 /* Put it on x_display_name_list. */
10071 x_display_name_list
= Fcons (Fcons (display_name
,
10072 Fcons (Qnil
, dpyinfo
->xrdb
)),
10073 x_display_name_list
);
10074 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10080 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10083 x_delete_display (dpyinfo
)
10084 struct mac_display_info
*dpyinfo
;
10088 /* Discard this display from x_display_name_list and x_display_list.
10089 We can't use Fdelq because that can quit. */
10090 if (! NILP (x_display_name_list
)
10091 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10092 x_display_name_list
= XCDR (x_display_name_list
);
10097 tail
= x_display_name_list
;
10098 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10100 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10102 XSETCDR (tail
, XCDR (XCDR (tail
)));
10105 tail
= XCDR (tail
);
10109 if (x_display_list
== dpyinfo
)
10110 x_display_list
= dpyinfo
->next
;
10113 struct x_display_info
*tail
;
10115 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10116 if (tail
->next
== dpyinfo
)
10117 tail
->next
= tail
->next
->next
;
10120 /* Free the font names in the font table. */
10121 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10122 if (dpyinfo
->font_table
[i
].name
)
10124 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10125 xfree (dpyinfo
->font_table
[i
].full_name
);
10126 xfree (dpyinfo
->font_table
[i
].name
);
10129 if (dpyinfo
->font_table
->font_encoder
)
10130 xfree (dpyinfo
->font_table
->font_encoder
);
10132 xfree (dpyinfo
->font_table
);
10133 xfree (dpyinfo
->mac_id_name
);
10135 if (x_display_list
== 0)
10137 mac_clear_font_name_table ();
10138 bzero (dpyinfo
, sizeof (*dpyinfo
));
10147 extern int inhibit_window_system
;
10148 extern int noninteractive
;
10149 CFBundleRef appsBundle
;
10152 /* No need to test if already -nw*/
10153 if (inhibit_window_system
|| noninteractive
)
10156 appsBundle
= CFBundleGetMainBundle();
10157 if (appsBundle
!= NULL
)
10159 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10160 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10161 /* We found the bundle identifier, now we know we are valid. */
10168 /* MAC_TODO: Have this start the bundled executable */
10170 /* For now, prevent the fatal error by bringing it up in the terminal */
10171 inhibit_window_system
= 1;
10175 MakeMeTheFrontProcess ()
10177 ProcessSerialNumber psn
;
10180 err
= GetCurrentProcess (&psn
);
10182 (void) SetFrontProcess (&psn
);
10185 /***** Code to handle C-g testing *****/
10187 /* Contains the Mac modifier formed from quit_char */
10188 int mac_quit_char_modifiers
= 0;
10189 int mac_quit_char_keycode
;
10190 extern int quit_char
;
10193 mac_determine_quit_char_modifiers()
10195 /* Todo: Determine modifiers from quit_char. */
10196 UInt32 qc_modifiers
= ctrl_modifier
;
10198 /* Map modifiers */
10199 mac_quit_char_modifiers
= 0;
10200 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
10201 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
10202 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
10203 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
10207 init_quit_char_handler ()
10209 /* TODO: Let this support keys other the 'g' */
10210 mac_quit_char_keycode
= 5;
10211 /* Look at <architecture/adb_kb_map.h> for details */
10212 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10214 mac_determine_quit_char_modifiers();
10218 quit_char_comp (EventRef inEvent
, void *inCompData
)
10220 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
10222 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
10226 UInt32 keyModifiers
;
10227 GetEventParameter(inEvent
, kEventParamKeyCode
,
10228 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
10229 if (keyCode
!= mac_quit_char_keycode
)
10231 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
10232 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
10233 if (keyModifiers
!= mac_quit_char_modifiers
)
10240 mac_check_for_quit_char ()
10243 static EMACS_TIME last_check_time
= { 0, 0 };
10244 static EMACS_TIME one_second
= { 1, 0 };
10247 /* If windows are not initialized, return immediately (keep it bouncin'). */
10248 if (!mac_quit_char_modifiers
)
10251 /* Don't check if last check is less than a second ago. */
10252 EMACS_GET_TIME (now
);
10253 EMACS_SUB_TIME (t
, now
, last_check_time
);
10254 if (EMACS_TIME_LT (t
, one_second
))
10256 last_check_time
= now
;
10258 /* Redetermine modifiers because they are based on lisp variables */
10259 mac_determine_quit_char_modifiers ();
10261 /* Fill the queue with events */
10263 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
10264 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
10269 struct input_event e
;
10271 /* Use an input_event to emulate what the interrupt handler does. */
10273 e
.kind
= ASCII_KEYSTROKE_EVENT
;
10274 e
.code
= quit_char
;
10276 e
.modifiers
= NULL
;
10277 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
10278 XSETFRAME (e
.frame_or_window
, mac_focus_frame (&one_mac_display_info
));
10279 /* Remove event from queue to prevent looping. */
10280 RemoveEventFromQueue (GetMainEventQueue (), event
);
10281 ReleaseEvent (event
);
10282 kbd_buffer_store_event (&e
);
10285 #endif /* MAC_OSX */
10293 MenuItemIndex menu_index
;
10295 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10296 &menu
, &menu_index
);
10298 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10299 #if USE_CARBON_EVENTS
10300 EnableMenuCommand (NULL
, kHICommandPreferences
);
10301 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10302 &menu
, &menu_index
);
10305 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10306 InsertMenuItemTextWithCFString (menu
, NULL
,
10307 0, kMenuItemAttrSeparator
, 0);
10308 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10309 0, 0, kHICommandAbout
);
10311 #endif /* USE_CARBON_EVENTS */
10312 #else /* !MAC_OSX */
10313 #if USE_CARBON_EVENTS
10314 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10320 /* Set up use of X before we make the first connection. */
10322 extern frame_parm_handler mac_frame_parm_handlers
[];
10324 static struct redisplay_interface x_redisplay_interface
=
10326 mac_frame_parm_handlers
,
10330 x_clear_end_of_line
,
10332 x_after_update_window_line
,
10333 x_update_window_begin
,
10334 x_update_window_end
,
10337 0, /* flush_display_optional */
10338 x_clear_window_mouse_face
,
10339 x_get_glyph_overhangs
,
10340 x_fix_overlapping_area
,
10341 x_draw_fringe_bitmap
,
10342 0, /* define_fringe_bitmap */
10343 0, /* destroy_fringe_bitmap */
10344 mac_per_char_metric
,
10346 mac_compute_glyph_string_overhangs
,
10347 x_draw_glyph_string
,
10348 mac_define_frame_cursor
,
10349 mac_clear_frame_area
,
10350 mac_draw_window_cursor
,
10351 mac_draw_vertical_window_border
,
10352 mac_shift_glyphs_for_insert
10358 rif
= &x_redisplay_interface
;
10360 clear_frame_hook
= x_clear_frame
;
10361 ins_del_lines_hook
= x_ins_del_lines
;
10362 delete_glyphs_hook
= x_delete_glyphs
;
10363 ring_bell_hook
= XTring_bell
;
10364 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10365 set_terminal_modes_hook
= XTset_terminal_modes
;
10366 update_begin_hook
= x_update_begin
;
10367 update_end_hook
= x_update_end
;
10368 set_terminal_window_hook
= XTset_terminal_window
;
10369 read_socket_hook
= XTread_socket
;
10370 frame_up_to_date_hook
= XTframe_up_to_date
;
10371 mouse_position_hook
= XTmouse_position
;
10372 frame_rehighlight_hook
= XTframe_rehighlight
;
10373 frame_raise_lower_hook
= XTframe_raise_lower
;
10375 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10376 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10377 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10378 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10380 scroll_region_ok
= 1; /* we'll scroll partial frames */
10381 char_ins_del_ok
= 1;
10382 line_ins_del_ok
= 1; /* we'll just blt 'em */
10383 fast_clear_end_of_line
= 1; /* X does this well */
10384 memory_below_frame
= 0; /* we don't remember what scrolls
10388 last_tool_bar_item
= -1;
10389 any_help_event_p
= 0;
10391 /* Try to use interrupt input; if we can't, then start polling. */
10392 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10396 #if TARGET_API_MAC_CARBON
10397 init_required_apple_events ();
10399 #if USE_CARBON_EVENTS
10401 init_service_handler ();
10403 init_quit_char_handler ();
10404 #endif /* MAC_OSX */
10406 init_command_handler ();
10409 #endif /* USE_CARBON_EVENTS */
10412 if (!inhibit_window_system
)
10413 MakeMeTheFrontProcess ();
10424 staticpro (&x_error_message_string
);
10425 x_error_message_string
= Qnil
;
10428 Qmodifier_value
= intern ("modifier-value");
10429 Qalt
= intern ("alt");
10430 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10431 Qhyper
= intern ("hyper");
10432 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10433 Qsuper
= intern ("super");
10434 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10436 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10437 Qabout
= intern ("about"); staticpro (&Qabout
);
10439 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10440 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10441 Qservices
= intern ("services"); staticpro (&Qservices
);
10442 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10443 Qperform
= intern ("perform"); staticpro (&Qperform
);
10447 Fprovide (intern ("mac-carbon"), Qnil
);
10450 staticpro (&Qreverse
);
10451 Qreverse
= intern ("reverse");
10453 staticpro (&x_display_name_list
);
10454 x_display_name_list
= Qnil
;
10456 staticpro (&last_mouse_scroll_bar
);
10457 last_mouse_scroll_bar
= Qnil
;
10459 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10460 staticpro (&Qmac_ready_for_drag_n_drop
);
10462 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10463 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10464 #ifdef USE_TOOLKIT_SCROLL_BARS
10465 Vx_toolkit_scroll_bars
= Qt
;
10467 Vx_toolkit_scroll_bars
= Qnil
;
10470 staticpro (&last_mouse_motion_frame
);
10471 last_mouse_motion_frame
= Qnil
;
10473 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10474 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10475 Otherwise the option key is used. */);
10476 Vmac_command_key_is_meta
= Qt
;
10478 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10479 doc
: /* Modifier to use for the Mac alt/option key. The value can
10480 be alt, hyper, or super for the respective modifier. If the value is
10481 nil then the key will act as the normal Mac option modifier. */);
10482 Vmac_option_modifier
= Qnil
;
10484 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10485 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10486 useful for non-standard keyboard layouts. */);
10487 Vmac_reverse_ctrl_meta
= Qnil
;
10489 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10490 &Vmac_emulate_three_button_mouse
,
10491 doc
: /* t means that when the option-key is held down while pressing the
10492 mouse button, the click will register as mouse-2 and while the
10493 command-key is held down, the click will register as mouse-3.
10494 'reverse means that the option-key will register for mouse-3
10495 and the command-key will register for mouse-2. nil means that
10496 no emulation should be done and the modifiers should be placed
10497 on the mouse-1 event. */);
10498 Vmac_emulate_three_button_mouse
= Qnil
;
10500 #if USE_CARBON_EVENTS
10501 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10502 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10503 the right click will be mouse-3.
10504 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10505 Vmac_wheel_button_is_mouse_2
= Qt
;
10507 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10508 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10509 Toolbox for processing before Emacs sees it. */);
10510 Vmac_pass_command_to_system
= Qt
;
10512 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10513 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10514 Toolbox for processing before Emacs sees it. */);
10515 Vmac_pass_control_to_system
= Qt
;
10519 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10520 doc
: /* If non-nil, allow anti-aliasing.
10521 The text will be rendered using Core Graphics text rendering which
10522 may anti-alias the text. */);
10523 Vmac_use_core_graphics
= Qnil
;
10525 /* Register an entry for `mac-roman' so that it can be used when
10526 creating the terminal frame on Mac OS 9 before loading
10527 term/mac-win.elc. */
10528 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10529 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10530 Each entry should be of the form:
10532 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10534 where CHARSET-NAME is a string used in font names to identify the
10535 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10536 is a coding system corresponding to TEXT-ENCODING. */);
10537 Vmac_charset_info_alist
=
10538 Fcons (list3 (build_string ("mac-roman"),
10539 make_number (smRoman
), Qnil
), Qnil
);
10542 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10543 (do not change this comment) */