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"
90 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
91 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
92 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
93 #define macShiftKey (shiftKey)
94 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
95 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
97 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
100 /* Non-nil means Emacs uses toolkit scroll bars. */
102 Lisp_Object Vx_toolkit_scroll_bars
;
104 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
105 Lisp_Object Vmac_use_core_graphics
;
108 /* Non-zero means that a HELP_EVENT has been generated since Emacs
111 static int any_help_event_p
;
113 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
114 static Lisp_Object last_window
;
116 /* This is a chain of structures for all the X displays currently in
119 struct x_display_info
*x_display_list
;
121 /* This is a list of cons cells, each of the form (NAME
122 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
123 x_display_list and in the same order. NAME is the name of the
124 frame. FONT-LIST-CACHE records previous values returned by
125 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
126 equivalent, which is implemented with a Lisp object, for the
129 Lisp_Object x_display_name_list
;
131 /* This is display since Mac does not support multiple ones. */
132 struct mac_display_info one_mac_display_info
;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the XT functions.
136 It is zero while not inside an update. In that case, the XT
137 functions assume that `selected_frame' is the frame to apply to. */
139 extern struct frame
*updating_frame
;
141 /* This is a frame waiting to be auto-raised, within XTread_socket. */
143 struct frame
*pending_autoraise_frame
;
147 Formerly, we used PointerMotionHintMask (in standard_event_mask)
148 so that we would have to call XQueryPointer after each MotionNotify
149 event to ask for another such event. However, this made mouse tracking
150 slow, and there was a bug that made it eventually stop.
152 Simply asking for MotionNotify all the time seems to work better.
154 In order to avoid asking for motion events and then throwing most
155 of them away or busy-polling the server for mouse positions, we ask
156 the server for pointer motion hints. This means that we get only
157 one event per group of mouse movements. "Groups" are delimited by
158 other kinds of events (focus changes and button clicks, for
159 example), or by XQueryPointer calls; when one of these happens, we
160 get another MotionNotify event the next time the mouse moves. This
161 is at least as efficient as getting motion events when mouse
162 tracking is on, and I suspect only negligibly worse when tracking
165 /* Where the mouse was last time we reported a mouse event. */
167 static Rect last_mouse_glyph
;
169 /* The scroll bar in which the last X motion event occurred.
171 If the last X motion event occurred in a scroll bar, we set this so
172 XTmouse_position can know whether to report a scroll bar motion or
175 If the last X motion event didn't occur in a scroll bar, we set
176 this to Qnil, to tell XTmouse_position to return an ordinary motion
179 static Lisp_Object last_mouse_scroll_bar
;
181 /* This is a hack. We would really prefer that XTmouse_position would
182 return the time associated with the position it returns, but there
183 doesn't seem to be any way to wrest the time-stamp from the server
184 along with the position query. So, we just keep track of the time
185 of the last movement we received, and return that in hopes that
186 it's somewhat accurate. */
188 static Time last_mouse_movement_time
;
190 struct scroll_bar
*tracked_scroll_bar
= NULL
;
192 /* Incremented by XTread_socket whenever it really tries to read
196 static int volatile input_signal_count
;
198 static int input_signal_count
;
201 extern Lisp_Object Vsystem_name
;
203 /* A mask of extra modifier bits to put into every keyboard char. */
205 extern EMACS_INT extra_keyboard_modifiers
;
207 /* The keysyms to use for the various modifiers. */
209 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
211 extern int inhibit_window_system
;
213 #if __MRC__ && !TARGET_API_MAC_CARBON
214 QDGlobals qd
; /* QuickDraw global information structure. */
217 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
219 struct mac_display_info
*mac_display_info_for_display (Display
*);
220 static void x_update_window_end
P_ ((struct window
*, int, int));
221 static int x_io_error_quitter
P_ ((Display
*));
222 int x_catch_errors
P_ ((Display
*));
223 void x_uncatch_errors
P_ ((Display
*, int));
224 void x_lower_frame
P_ ((struct frame
*));
225 void x_scroll_bar_clear
P_ ((struct frame
*));
226 int x_had_errors_p
P_ ((Display
*));
227 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
228 void x_raise_frame
P_ ((struct frame
*));
229 void x_set_window_size
P_ ((struct frame
*, int, int, int));
230 void x_wm_set_window_state
P_ ((struct frame
*, int));
231 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
232 void mac_initialize
P_ ((void));
233 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
234 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
235 static void x_update_end
P_ ((struct frame
*));
236 static void XTframe_up_to_date
P_ ((struct frame
*));
237 static void XTset_terminal_modes
P_ ((void));
238 static void XTreset_terminal_modes
P_ ((void));
239 static void x_clear_frame
P_ ((void));
240 static void frame_highlight
P_ ((struct frame
*));
241 static void frame_unhighlight
P_ ((struct frame
*));
242 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
243 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
244 struct frame
*, struct input_event
*));
245 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
246 EventRecord
*, struct input_event
*));
247 static void XTframe_rehighlight
P_ ((struct frame
*));
248 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
249 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
250 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
251 enum text_cursor_kinds
));
253 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
254 static void x_flush
P_ ((struct frame
*f
));
255 static void x_update_begin
P_ ((struct frame
*));
256 static void x_update_window_begin
P_ ((struct window
*));
257 static void x_after_update_window_line
P_ ((struct glyph_row
*));
258 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
259 enum scroll_bar_part
*,
260 Lisp_Object
*, Lisp_Object
*,
263 static int is_emacs_window
P_ ((WindowPtr
));
265 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
267 /* Defined in macmenu.h. */
268 extern void menubar_selection_callback (FRAME_PTR
, int);
270 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
271 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
272 #define GC_FONT(gc) ((gc)->xgcv.font)
273 #define MAC_WINDOW_NORMAL_GC(w) (((mac_output *) GetWRefCon (w))->normal_gc)
276 /* X display function emulation */
279 XFreePixmap (display
, pixmap
)
280 Display
*display
; /* not used */
283 DisposeGWorld (pixmap
);
287 /* Mac version of XDrawLine. */
290 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
296 SetPortWindowPort (w
);
298 RGBForeColor (GC_FORE_COLOR (gc
));
305 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
314 GetGWorld (&old_port
, &old_gdh
);
317 RGBForeColor (GC_FORE_COLOR (gc
));
319 LockPixels (GetGWorldPixMap (p
));
322 UnlockPixels (GetGWorldPixMap (p
));
324 SetGWorld (old_port
, old_gdh
);
329 mac_erase_rectangle (w
, gc
, x
, y
, width
, height
)
333 unsigned int width
, height
;
337 SetPortWindowPort (w
);
339 RGBBackColor (GC_BACK_COLOR (gc
));
340 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
344 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
348 /* Mac version of XClearArea. */
351 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
355 unsigned int width
, height
;
358 mac_erase_rectangle (w
, MAC_WINDOW_NORMAL_GC (w
), x
, y
, width
, height
);
361 /* Mac version of XClearWindow. */
364 XClearWindow (display
, w
)
368 SetPortWindowPort (w
);
370 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
372 #if TARGET_API_MAC_CARBON
376 GetWindowPortBounds (w
, &r
);
379 #else /* not TARGET_API_MAC_CARBON */
380 EraseRect (&(w
->portRect
));
381 #endif /* not TARGET_API_MAC_CARBON */
385 /* Mac replacement for XCopyArea. */
388 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
392 int x
, y
, width
, height
;
393 unsigned short *bits
;
399 bitmap
.rowBytes
= sizeof(unsigned short);
400 bitmap
.baseAddr
= (char *)bits
;
401 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
403 SetPortWindowPort (w
);
405 RGBForeColor (GC_FORE_COLOR (gc
));
406 RGBBackColor (GC_BACK_COLOR (gc
));
407 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
409 #if TARGET_API_MAC_CARBON
410 LockPortBits (GetWindowPort (w
));
411 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
412 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
413 UnlockPortBits (GetWindowPort (w
));
414 #else /* not TARGET_API_MAC_CARBON */
415 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
416 overlay_p
? srcOr
: srcCopy
, 0);
417 #endif /* not TARGET_API_MAC_CARBON */
419 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
423 /* Mac replacement for XSetClipRectangles. */
426 mac_set_clip_rectangle (display
, w
, r
)
431 SetPortWindowPort (w
);
437 /* Mac replacement for XSetClipMask. */
440 mac_reset_clipping (display
, w
)
446 SetPortWindowPort (w
);
448 SetRect (&r
, -32767, -32767, 32767, 32767);
453 /* Mac replacement for XCreateBitmapFromBitmapData. */
456 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
461 static unsigned char swap_nibble
[16]
462 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
463 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
464 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
465 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
469 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
470 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
471 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
472 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
473 for (i
= 0; i
< h
; i
++)
475 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
476 for (j
= 0; j
< w1
; j
++)
478 /* Bitswap XBM bytes to match how Mac does things. */
479 unsigned char c
= *bits
++;
480 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
481 | (swap_nibble
[(c
>>4) & 0xf]));;
485 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
490 mac_free_bitmap (bitmap
)
493 xfree (bitmap
->baseAddr
);
498 XCreatePixmap (display
, w
, width
, height
, depth
)
499 Display
*display
; /* not used */
501 unsigned int width
, height
;
508 SetPortWindowPort (w
);
510 SetRect (&r
, 0, 0, width
, height
);
511 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
519 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
520 Display
*display
; /* not used */
523 unsigned int width
, height
;
524 unsigned long fg
, bg
;
531 static GC gc
= NULL
; /* not reentrant */
534 gc
= XCreateGC (display
, w
, 0, NULL
);
536 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
540 GetGWorld (&old_port
, &old_gdh
);
541 SetGWorld (pixmap
, NULL
);
542 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
543 XSetForeground (display
, gc
, fg
);
544 XSetBackground (display
, gc
, bg
);
545 RGBForeColor (GC_FORE_COLOR (gc
));
546 RGBBackColor (GC_BACK_COLOR (gc
));
547 LockPixels (GetGWorldPixMap (pixmap
));
548 #if TARGET_API_MAC_CARBON
549 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
550 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
551 #else /* not TARGET_API_MAC_CARBON */
552 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
553 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
554 #endif /* not TARGET_API_MAC_CARBON */
555 UnlockPixels (GetGWorldPixMap (pixmap
));
556 SetGWorld (old_port
, old_gdh
);
557 mac_free_bitmap (&bitmap
);
563 /* Mac replacement for XFillRectangle. */
566 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
571 unsigned int width
, height
;
575 SetPortWindowPort (w
);
577 RGBForeColor (GC_FORE_COLOR (gc
));
578 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
580 PaintRect (&r
); /* using foreground color of gc */
584 #if 0 /* TODO: figure out if we need to do this on Mac. */
586 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
591 unsigned int width
, height
;
597 GetGWorld (&old_port
, &old_gdh
);
599 RGBForeColor (GC_FORE_COLOR (gc
));
600 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
602 LockPixels (GetGWorldPixMap (p
));
603 PaintRect (&r
); /* using foreground color of gc */
604 UnlockPixels (GetGWorldPixMap (p
));
606 SetGWorld (old_port
, old_gdh
);
611 /* Mac replacement for XDrawRectangle: dest is a window. */
614 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
619 unsigned int width
, height
;
623 SetPortWindowPort (w
);
625 RGBForeColor (GC_FORE_COLOR (gc
));
626 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
628 FrameRect (&r
); /* using foreground color of gc */
632 #if 0 /* TODO: figure out if we need to do this on Mac. */
633 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
636 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
641 unsigned int width
, height
;
647 GetGWorld (&old_port
, &old_gdh
);
649 RGBForeColor (GC_FORE_COLOR (gc
));
650 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
652 LockPixels (GetGWorldPixMap (p
));
653 FrameRect (&r
); /* using foreground color of gc */
654 UnlockPixels (GetGWorldPixMap (p
));
656 SetGWorld (old_port
, old_gdh
);
663 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
664 ConstUniCharArrayPtr text
;
665 UniCharCount text_length
;
667 ATSUTextLayout
*text_layout
;
670 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
672 if (saved_text_layout
== NULL
)
674 UniCharCount lengths
[] = {kATSUToTextEnd
};
675 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
676 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
677 static ATSLineLayoutOptions line_layout
=
678 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
679 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
681 kATSLineIsDisplayOnly
684 ATSUAttributeValuePtr values
[] = {&line_layout
};
686 err
= ATSUCreateTextLayoutWithTextPtr (text
,
687 kATSUFromTextBeginning
,
693 err
= ATSUSetLayoutControls (saved_text_layout
,
694 sizeof (tags
) / sizeof (tags
[0]),
695 tags
, sizes
, values
);
696 /* XXX: Should we do this? */
698 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
702 err
= ATSUSetRunStyle (saved_text_layout
, style
,
703 kATSUFromTextBeginning
, kATSUToTextEnd
);
705 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
706 kATSUFromTextBeginning
,
712 *text_layout
= saved_text_layout
;
718 mac_invert_rectangle (display
, w
, x
, y
, width
, height
)
722 unsigned int width
, height
;
726 SetPortWindowPort (w
);
728 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
735 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
742 int nchars
, mode
, bytes_per_char
;
744 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
745 UInt32 textFlags
, savedFlags
;
746 if (!NILP(Vmac_use_core_graphics
)) {
747 textFlags
= kQDUseCGTextRendering
;
748 savedFlags
= SwapQDTextFlags(textFlags
);
752 SetPortWindowPort (w
);
754 RGBForeColor (GC_FORE_COLOR (gc
));
756 RGBBackColor (GC_BACK_COLOR (gc
));
759 if (GC_FONT (gc
)->mac_style
)
762 ATSUTextLayout text_layout
;
764 xassert (bytes_per_char
== 2);
766 #ifndef WORDS_BIG_ENDIAN
769 Unichar
*text
= (Unichar
*)buf
;
771 for (i
= 0; i
< nchars
; i
++)
772 text
[i
] = buf
[2*i
] << 8 | buf
[2*i
+1];
775 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
777 GC_FONT (gc
)->mac_style
,
782 if (NILP (Vmac_use_core_graphics
))
786 ATSUDrawText (text_layout
,
787 kATSUFromTextBeginning
, kATSUToTextEnd
,
788 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
794 CGContextRef context
;
796 RgnHandle region
= NewRgn ();
798 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
799 ByteCount sizes
[] = {sizeof (CGContextRef
)};
800 ATSUAttributeValuePtr values
[] = {&context
};
803 QDBeginCGContext (port
, &context
);
804 GetPortBounds (port
, &rect
);
805 port_height
= rect
.bottom
- rect
.top
;
807 GetRegionBounds (region
, &rect
);
808 /* XXX: This is not correct if the clip region is not a
810 CGContextClipToRect (context
,
811 CGRectMake (rect
.left
,
812 port_height
- rect
.bottom
,
813 rect
.right
- rect
.left
,
814 rect
.bottom
- rect
.top
));
816 CGContextSetRGBFillColor
818 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
819 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
820 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
822 err
= ATSUSetLayoutControls (text_layout
,
823 sizeof (tags
) / sizeof (tags
[0]),
824 tags
, sizes
, values
);
826 ATSUDrawText (text_layout
,
827 kATSUFromTextBeginning
, kATSUToTextEnd
,
828 Long2Fix (x
), Long2Fix (port_height
- y
));
829 ATSUClearLayoutControls (text_layout
,
830 sizeof (tags
) / sizeof (tags
[0]),
832 CGContextSynchronize (context
);
833 QDEndCGContext (port
, &context
);
841 TextFont (GC_FONT (gc
)->mac_fontnum
);
842 TextSize (GC_FONT (gc
)->mac_fontsize
);
843 TextFace (GC_FONT (gc
)->mac_fontface
);
847 DrawText (buf
, 0, nchars
* bytes_per_char
);
853 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
854 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
855 if (!NILP(Vmac_use_core_graphics
))
856 SwapQDTextFlags(savedFlags
);
861 /* Mac replacement for XDrawString. */
864 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
872 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
876 /* Mac replacement for XDrawString16. */
879 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
887 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
892 /* Mac replacement for XDrawImageString. */
895 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
903 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
907 /* Mac replacement for XDrawString16. */
910 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
918 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
923 /* Mac replacement for XCopyArea: dest must be window. */
926 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
933 unsigned int width
, height
;
938 SetPortWindowPort (dest
);
940 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
941 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
943 ForeColor (blackColor
);
944 BackColor (whiteColor
);
946 LockPixels (GetGWorldPixMap (src
));
947 #if TARGET_API_MAC_CARBON
948 LockPortBits (GetWindowPort (dest
));
949 CopyBits (GetPortBitMapForCopyBits (src
),
950 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
951 &src_r
, &dest_r
, srcCopy
, 0);
952 UnlockPortBits (GetWindowPort (dest
));
953 #else /* not TARGET_API_MAC_CARBON */
954 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
955 &src_r
, &dest_r
, srcCopy
, 0);
956 #endif /* not TARGET_API_MAC_CARBON */
957 UnlockPixels (GetGWorldPixMap (src
));
959 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest
)));
964 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
965 width
, height
, dest_x
, dest_y
)
971 unsigned int width
, height
;
976 SetPortWindowPort (dest
);
978 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
979 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
981 ForeColor (blackColor
);
982 BackColor (whiteColor
);
984 LockPixels (GetGWorldPixMap (src
));
985 LockPixels (GetGWorldPixMap (mask
));
986 #if TARGET_API_MAC_CARBON
987 LockPortBits (GetWindowPort (dest
));
988 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
989 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
990 &src_r
, &src_r
, &dest_r
);
991 UnlockPortBits (GetWindowPort (dest
));
992 #else /* not TARGET_API_MAC_CARBON */
993 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
994 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
995 #endif /* not TARGET_API_MAC_CARBON */
996 UnlockPixels (GetGWorldPixMap (mask
));
997 UnlockPixels (GetGWorldPixMap (src
));
999 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (dest
)));
1003 /* Mac replacement for XCopyArea: used only for scrolling. */
1006 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1011 unsigned int width
, height
;
1014 #if TARGET_API_MAC_CARBON
1016 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1018 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1019 ScrollWindowRect (w
, &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1020 kScrollWindowNoOptions
, dummy
);
1022 #else /* not TARGET_API_MAC_CARBON */
1027 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1028 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1030 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1031 color mapping in CopyBits. Otherwise, it will be slow. */
1032 ForeColor (blackColor
);
1033 BackColor (whiteColor
);
1034 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1036 RGBBackColor (GC_BACK_COLOR (MAC_WINDOW_NORMAL_GC (w
)));
1037 #endif /* not TARGET_API_MAC_CARBON */
1041 #if 0 /* TODO: figure out if we need to do this on Mac. */
1042 /* Mac replacement for XCopyArea: dest must be Pixmap. */
1045 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
1051 unsigned int width
, height
;
1058 GetGWorld (&old_port
, &old_gdh
);
1059 SetGWorld (dest
, NULL
);
1060 ForeColor (blackColor
);
1061 BackColor (whiteColor
);
1063 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1064 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1066 LockPixels (GetGWorldPixMap (src
));
1067 LockPixels (GetGWorldPixMap (dest
));
1068 #if TARGET_API_MAC_CARBON
1069 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
1070 &src_r
, &dest_r
, srcCopy
, 0);
1071 #else /* not TARGET_API_MAC_CARBON */
1072 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
1073 &src_r
, &dest_r
, srcCopy
, 0);
1074 #endif /* not TARGET_API_MAC_CARBON */
1075 UnlockPixels (GetGWorldPixMap (dest
));
1076 UnlockPixels (GetGWorldPixMap (src
));
1078 SetGWorld (old_port
, old_gdh
);
1083 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1084 width
, height
, dest_x
, dest_y
)
1086 Pixmap src
, mask
, dest
;
1089 unsigned int width
, height
;
1096 GetGWorld (&old_port
, &old_gdh
);
1097 SetGWorld (dest
, NULL
);
1098 ForeColor (blackColor
);
1099 BackColor (whiteColor
);
1101 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1102 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1104 LockPixels (GetGWorldPixMap (src
));
1105 LockPixels (GetGWorldPixMap (mask
));
1106 LockPixels (GetGWorldPixMap (dest
));
1107 #if TARGET_API_MAC_CARBON
1108 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1109 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1110 #else /* not TARGET_API_MAC_CARBON */
1111 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1112 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1113 #endif /* not TARGET_API_MAC_CARBON */
1114 UnlockPixels (GetGWorldPixMap (dest
));
1115 UnlockPixels (GetGWorldPixMap (mask
));
1116 UnlockPixels (GetGWorldPixMap (src
));
1118 SetGWorld (old_port
, old_gdh
);
1123 /* Mac replacement for XChangeGC. */
1126 XChangeGC (display
, gc
, mask
, xgcv
)
1132 if (mask
& GCForeground
)
1133 XSetForeground (display
, gc
, xgcv
->foreground
);
1134 if (mask
& GCBackground
)
1135 XSetBackground (display
, gc
, xgcv
->background
);
1137 XSetFont (display
, gc
, xgcv
->font
);
1141 /* Mac replacement for XCreateGC. */
1144 XCreateGC (display
, window
, mask
, xgcv
)
1150 GC gc
= xmalloc (sizeof (*gc
));
1154 bzero (gc
, sizeof (*gc
));
1155 XChangeGC (display
, gc
, mask
, xgcv
);
1162 /* Used in xfaces.c. */
1165 XFreeGC (display
, gc
)
1173 /* Mac replacement for XGetGCValues. */
1176 XGetGCValues (display
, gc
, mask
, xgcv
)
1182 if (mask
& GCForeground
)
1183 xgcv
->foreground
= gc
->xgcv
.foreground
;
1184 if (mask
& GCBackground
)
1185 xgcv
->background
= gc
->xgcv
.background
;
1187 xgcv
->font
= gc
->xgcv
.font
;
1191 /* Mac replacement for XSetForeground. */
1194 XSetForeground (display
, gc
, color
)
1197 unsigned long color
;
1199 if (gc
->xgcv
.foreground
!= color
)
1201 gc
->xgcv
.foreground
= color
;
1202 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1203 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1204 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1209 /* Mac replacement for XSetBackground. */
1212 XSetBackground (display
, gc
, color
)
1215 unsigned long color
;
1217 if (gc
->xgcv
.background
!= color
)
1219 gc
->xgcv
.background
= color
;
1220 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1221 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1222 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1227 /* Mac replacement for XSetFont. */
1230 XSetFont (display
, gc
, font
)
1235 gc
->xgcv
.font
= font
;
1239 /* Mac replacement for XSetWindowBackground. */
1242 XSetWindowBackground (display
, w
, color
)
1245 unsigned long color
;
1247 #if !TARGET_API_MAC_CARBON
1248 AuxWinHandle aw_handle
;
1249 CTabHandle ctab_handle
;
1250 ColorSpecPtr ct_table
;
1255 bg_color
.red
= RED16_FROM_ULONG (color
);
1256 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1257 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1259 #if TARGET_API_MAC_CARBON
1260 SetWindowContentColor (w
, &bg_color
);
1262 if (GetAuxWin (w
, &aw_handle
))
1264 ctab_handle
= (*aw_handle
)->awCTable
;
1265 HandToHand ((Handle
*) &ctab_handle
);
1266 ct_table
= (*ctab_handle
)->ctTable
;
1267 ct_size
= (*ctab_handle
)->ctSize
;
1268 while (ct_size
> -1)
1270 if (ct_table
->value
== 0)
1272 ct_table
->rgb
= bg_color
;
1273 CTabChanged (ctab_handle
);
1274 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1282 /* x_sync is a no-op on Mac. */
1290 /* Flush display of frame F, or of all frames if F is null. */
1296 #if TARGET_API_MAC_CARBON
1299 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1301 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1307 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1308 Calls to XFlush should be unnecessary because the X output buffer
1309 is flushed automatically as needed by calls to XPending,
1310 XNextEvent, or XWindowEvent according to the XFlush man page.
1311 XTread_socket calls XPending. Removing XFlush improves
1314 #define XFlush(DISPLAY) (void) 0
1317 /* Return the struct mac_display_info corresponding to DPY. There's
1320 struct mac_display_info
*
1321 mac_display_info_for_display (dpy
)
1324 return &one_mac_display_info
;
1329 /***********************************************************************
1330 Starting and ending an update
1331 ***********************************************************************/
1333 /* Start an update of frame F. This function is installed as a hook
1334 for update_begin, i.e. it is called when update_begin is called.
1335 This function is called prior to calls to x_update_window_begin for
1336 each window being updated. */
1342 #if TARGET_API_MAC_CARBON
1343 /* During update of a frame, availability of input events is
1344 periodically checked with ReceiveNextEvent if
1345 redisplay-dont-pause is nil. That normally flushes window buffer
1346 changes for every check, and thus screen update looks waving even
1347 if no input is available. So we disable screen updates during
1348 update of a frame. */
1350 DisableScreenUpdates ();
1356 /* Start update of window W. Set the global variable updated_window
1357 to the window being updated and set output_cursor to the cursor
1361 x_update_window_begin (w
)
1364 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1365 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1368 set_output_cursor (&w
->cursor
);
1372 if (f
== display_info
->mouse_face_mouse_frame
)
1374 /* Don't do highlighting for mouse motion during the update. */
1375 display_info
->mouse_face_defer
= 1;
1377 /* If F needs to be redrawn, simply forget about any prior mouse
1379 if (FRAME_GARBAGED_P (f
))
1380 display_info
->mouse_face_window
= Qnil
;
1382 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1383 their mouse_face_p flag set, which means that they are always
1384 unequal to rows in a desired matrix which never have that
1385 flag set. So, rows containing mouse-face glyphs are never
1386 scrolled, and we don't have to switch the mouse highlight off
1387 here to prevent it from being scrolled. */
1389 /* Can we tell that this update does not affect the window
1390 where the mouse highlight is? If so, no need to turn off.
1391 Likewise, don't do anything if the frame is garbaged;
1392 in that case, the frame's current matrix that we would use
1393 is all wrong, and we will redisplay that line anyway. */
1394 if (!NILP (display_info
->mouse_face_window
)
1395 && w
== XWINDOW (display_info
->mouse_face_window
))
1399 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1400 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1403 if (i
< w
->desired_matrix
->nrows
)
1404 clear_mouse_face (display_info
);
1413 /* Draw a vertical window border from (x,y0) to (x,y1) */
1416 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1420 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1423 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1425 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1428 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1429 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1432 /* End update of window W (which is equal to updated_window).
1434 Draw vertical borders between horizontally adjacent windows, and
1435 display W's cursor if CURSOR_ON_P is non-zero.
1437 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1438 glyphs in mouse-face were overwritten. In that case we have to
1439 make sure that the mouse-highlight is properly redrawn.
1441 W may be a menu bar pseudo-window in case we don't have X toolkit
1442 support. Such windows don't have a cursor, so don't display it
1446 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1448 int cursor_on_p
, mouse_face_overwritten_p
;
1450 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1452 if (!w
->pseudo_window_p
)
1457 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1459 output_cursor
.x
, output_cursor
.y
);
1461 if (draw_window_fringes (w
, 1))
1462 x_draw_vertical_border (w
);
1467 /* If a row with mouse-face was overwritten, arrange for
1468 XTframe_up_to_date to redisplay the mouse highlight. */
1469 if (mouse_face_overwritten_p
)
1471 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1472 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1473 dpyinfo
->mouse_face_window
= Qnil
;
1476 updated_window
= NULL
;
1480 /* End update of frame F. This function is installed as a hook in
1487 /* Mouse highlight may be displayed again. */
1488 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1491 #if TARGET_API_MAC_CARBON
1492 EnableScreenUpdates ();
1494 XFlush (FRAME_MAC_DISPLAY (f
));
1499 /* This function is called from various places in xdisp.c whenever a
1500 complete update has been performed. The global variable
1501 updated_window is not available here. */
1504 XTframe_up_to_date (f
)
1507 if (FRAME_MAC_P (f
))
1509 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1511 if (dpyinfo
->mouse_face_deferred_gc
1512 || f
== dpyinfo
->mouse_face_mouse_frame
)
1515 if (dpyinfo
->mouse_face_mouse_frame
)
1516 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1517 dpyinfo
->mouse_face_mouse_x
,
1518 dpyinfo
->mouse_face_mouse_y
);
1519 dpyinfo
->mouse_face_deferred_gc
= 0;
1526 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1527 arrow bitmaps, or clear the fringes if no bitmaps are required
1528 before DESIRED_ROW is made current. The window being updated is
1529 found in updated_window. This function is called from
1530 update_window_line only if it is known that there are differences
1531 between bitmaps to be drawn between current row and DESIRED_ROW. */
1534 x_after_update_window_line (desired_row
)
1535 struct glyph_row
*desired_row
;
1537 struct window
*w
= updated_window
;
1543 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1544 desired_row
->redraw_fringe_bitmaps_p
= 1;
1546 /* When a window has disappeared, make sure that no rest of
1547 full-width rows stays visible in the internal border. Could
1548 check here if updated_window is the leftmost/rightmost window,
1549 but I guess it's not worth doing since vertically split windows
1550 are almost never used, internal border is rarely set, and the
1551 overhead is very small. */
1552 if (windows_or_buffers_changed
1553 && desired_row
->full_width_p
1554 && (f
= XFRAME (w
->frame
),
1555 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1557 && (height
= desired_row
->visible_height
,
1560 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1562 /* Internal border is drawn below the tool bar. */
1563 if (WINDOWP (f
->tool_bar_window
)
1564 && w
== XWINDOW (f
->tool_bar_window
))
1568 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1569 0, y
, width
, height
, 0);
1570 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1571 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1578 /* Draw the bitmap WHICH in one of the left or right fringes of
1579 window W. ROW is the glyph row for which to display the bitmap; it
1580 determines the vertical position at which the bitmap has to be
1584 x_draw_fringe_bitmap (w
, row
, p
)
1586 struct glyph_row
*row
;
1587 struct draw_fringe_bitmap_params
*p
;
1589 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1590 Display
*display
= FRAME_MAC_DISPLAY (f
);
1591 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1592 GC gc
= f
->output_data
.mac
->normal_gc
;
1593 struct face
*face
= p
->face
;
1596 /* Must clip because of partially visible lines. */
1597 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1600 /* Adjust position of "bottom aligned" bitmap on partially
1601 visible last row. */
1603 int oldVH
= row
->visible_height
;
1604 row
->visible_height
= p
->h
;
1605 row
->y
-= rowY
- p
->y
;
1606 x_clip_to_row (w
, row
, -1, gc
);
1608 row
->visible_height
= oldVH
;
1611 x_clip_to_row (w
, row
, -1, gc
);
1613 if (p
->bx
>= 0 && !p
->overlay_p
)
1615 #if 0 /* MAC_TODO: stipple */
1616 /* In case the same realized face is used for fringes and
1617 for something displayed in the text (e.g. face `region' on
1618 mono-displays, the fill style may have been changed to
1619 FillSolid in x_draw_glyph_string_background. */
1621 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1623 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1626 mac_erase_rectangle (window
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1628 #if 0 /* MAC_TODO: stipple */
1630 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1636 unsigned short *bits
= p
->bits
+ p
->dh
;
1639 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1640 XSetForeground (display
, face
->gc
,
1642 ? (p
->overlay_p
? face
->background
1643 : f
->output_data
.mac
->cursor_pixel
)
1644 : face
->foreground
));
1645 mac_draw_bitmap (display
, window
, face
->gc
, p
->x
, p
->y
,
1646 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1647 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1650 mac_reset_clipping (display
, window
);
1655 /* This is called when starting Emacs and when restarting after
1656 suspend. When starting Emacs, no window is mapped. And nothing
1657 must be done to Emacs's own window if it is suspended (though that
1661 XTset_terminal_modes ()
1665 /* This is called when exiting or suspending Emacs. Exiting will make
1666 the windows go away, and suspending requires no action. */
1669 XTreset_terminal_modes ()
1675 /***********************************************************************
1677 ***********************************************************************/
1679 /* Function prototypes of this page. */
1681 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1682 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1685 /* Return a pointer to per-char metric information in FONT of a
1686 character pointed by B which is a pointer to an XChar2b. */
1688 #define PER_CHAR_METRIC(font, b) \
1690 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1691 + (((font)->min_byte1 || (font)->max_byte1) \
1692 ? (((b)->byte1 - (font)->min_byte1) \
1693 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1695 : &((font)->max_bounds))
1698 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1699 is not contained in the font. */
1701 static INLINE XCharStruct
*
1702 x_per_char_metric (font
, char2b
)
1706 /* The result metric information. */
1707 XCharStruct
*pcm
= NULL
;
1709 xassert (font
&& char2b
);
1712 if (font
->mac_style
)
1714 if (char2b
->byte1
>= font
->min_byte1
1715 && char2b
->byte1
<= font
->max_byte1
1716 && char2b
->byte2
>= font
->min_char_or_byte2
1717 && char2b
->byte2
<= font
->max_char_or_byte2
)
1719 pcm
= (font
->per_char
1720 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1721 * (char2b
->byte1
- font
->min_byte1
))
1722 + (char2b
->byte2
- font
->min_char_or_byte2
));
1725 if (pcm
&& !pcm
->valid_p
)
1728 ATSUTextLayout text_layout
;
1731 ATSTrapezoid glyph_bounds
;
1734 c
= (char2b
->byte1
<< 8) + char2b
->byte2
;
1736 err
= atsu_get_text_layout_with_text_ptr (&c
, 1,
1740 err
= ATSUMeasureTextImage (text_layout
,
1741 kATSUFromTextBeginning
, kATSUToTextEnd
,
1742 0, 0, &char_bounds
);
1745 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1746 kATSUFromTextBeginning
, kATSUToTextEnd
,
1747 kATSUseFractionalOrigins
, 1,
1748 &glyph_bounds
, NULL
);
1754 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1755 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1757 char_width
= Fix2Long (glyph_bounds
.upperRight
.x
1758 - glyph_bounds
.upperLeft
.x
);
1759 STORE_XCHARSTRUCT (*pcm
, char_width
, char_bounds
);
1766 if (font
->per_char
!= NULL
)
1768 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1770 /* min_char_or_byte2 specifies the linear character index
1771 corresponding to the first element of the per_char array,
1772 max_char_or_byte2 is the index of the last character. A
1773 character with non-zero CHAR2B->byte1 is not in the font.
1774 A character with byte2 less than min_char_or_byte2 or
1775 greater max_char_or_byte2 is not in the font. */
1776 if (char2b
->byte1
== 0
1777 && char2b
->byte2
>= font
->min_char_or_byte2
1778 && char2b
->byte2
<= font
->max_char_or_byte2
)
1779 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1783 /* If either min_byte1 or max_byte1 are nonzero, both
1784 min_char_or_byte2 and max_char_or_byte2 are less than
1785 256, and the 2-byte character index values corresponding
1786 to the per_char array element N (counting from 0) are:
1788 byte1 = N/D + min_byte1
1789 byte2 = N\D + min_char_or_byte2
1793 D = max_char_or_byte2 - min_char_or_byte2 + 1
1794 / = integer division
1795 \ = integer modulus */
1796 if (char2b
->byte1
>= font
->min_byte1
1797 && char2b
->byte1
<= font
->max_byte1
1798 && char2b
->byte2
>= font
->min_char_or_byte2
1799 && char2b
->byte2
<= font
->max_char_or_byte2
)
1801 pcm
= (font
->per_char
1802 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1803 * (char2b
->byte1
- font
->min_byte1
))
1804 + (char2b
->byte2
- font
->min_char_or_byte2
));
1810 /* If the per_char pointer is null, all glyphs between the first
1811 and last character indexes inclusive have the same
1812 information, as given by both min_bounds and max_bounds. */
1813 if (char2b
->byte2
>= font
->min_char_or_byte2
1814 && char2b
->byte2
<= font
->max_char_or_byte2
)
1815 pcm
= &font
->max_bounds
;
1821 return ((pcm
== NULL
1822 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1829 static XCharStruct
*
1830 mac_per_char_metric (font
, char2b
, font_type
)
1835 return x_per_char_metric (font
, char2b
);
1839 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1840 the two-byte form of C. Encoding is returned in *CHAR2B. */
1843 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1846 struct font_info
*font_info
;
1849 int charset
= CHAR_CHARSET (c
);
1850 XFontStruct
*font
= font_info
->font
;
1852 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1853 This may be either a program in a special encoder language or a
1855 if (font_info
->font_encoder
)
1857 /* It's a program. */
1858 struct ccl_program
*ccl
= font_info
->font_encoder
;
1860 check_ccl_update (ccl
);
1861 if (CHARSET_DIMENSION (charset
) == 1)
1863 ccl
->reg
[0] = charset
;
1864 ccl
->reg
[1] = char2b
->byte2
;
1869 ccl
->reg
[0] = charset
;
1870 ccl
->reg
[1] = char2b
->byte1
;
1871 ccl
->reg
[2] = char2b
->byte2
;
1874 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1876 /* We assume that MSBs are appropriately set/reset by CCL
1878 if (font
->max_byte1
== 0) /* 1-byte font */
1879 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1881 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1883 else if (font_info
->encoding
[charset
])
1885 /* Fixed encoding scheme. See fontset.h for the meaning of the
1886 encoding numbers. */
1887 int enc
= font_info
->encoding
[charset
];
1889 if ((enc
== 1 || enc
== 2)
1890 && CHARSET_DIMENSION (charset
) == 2)
1891 char2b
->byte1
|= 0x80;
1893 if (enc
== 1 || enc
== 3)
1894 char2b
->byte2
|= 0x80;
1900 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1901 char2b
->byte1
= sjis1
;
1902 char2b
->byte2
= sjis2
;
1907 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1909 return FONT_TYPE_UNKNOWN
;
1914 /***********************************************************************
1916 ***********************************************************************/
1920 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1921 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1922 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1924 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1925 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1926 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1927 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1928 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
1929 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1930 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1931 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1932 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1933 unsigned long *, double, int));*/
1934 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1935 double, int, unsigned long));
1936 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1937 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1938 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1939 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1940 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1941 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1943 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1944 int, int, int, int, int, int,
1946 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1947 int, int, int, Rect
*));
1950 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1954 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1959 struct glyph_string
*s
;
1961 if (s
->font
== FRAME_FONT (s
->f
)
1962 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1963 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1965 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1968 /* Cursor on non-default face: must merge. */
1972 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1973 xgcv
.foreground
= s
->face
->background
;
1975 /* If the glyph would be invisible, try a different foreground. */
1976 if (xgcv
.foreground
== xgcv
.background
)
1977 xgcv
.foreground
= s
->face
->foreground
;
1978 if (xgcv
.foreground
== xgcv
.background
)
1979 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1980 if (xgcv
.foreground
== xgcv
.background
)
1981 xgcv
.foreground
= s
->face
->foreground
;
1983 /* Make sure the cursor is distinct from text in this face. */
1984 if (xgcv
.background
== s
->face
->background
1985 && xgcv
.foreground
== s
->face
->foreground
)
1987 xgcv
.background
= s
->face
->foreground
;
1988 xgcv
.foreground
= s
->face
->background
;
1991 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1992 xgcv
.font
= s
->font
;
1993 mask
= GCForeground
| GCBackground
| GCFont
;
1995 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1996 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1999 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2000 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2002 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2007 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2010 x_set_mouse_face_gc (s
)
2011 struct glyph_string
*s
;
2016 /* What face has to be used last for the mouse face? */
2017 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2018 face
= FACE_FROM_ID (s
->f
, face_id
);
2020 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2022 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2023 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2025 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2026 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2027 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2029 /* If font in this face is same as S->font, use it. */
2030 if (s
->font
== s
->face
->font
)
2031 s
->gc
= s
->face
->gc
;
2034 /* Otherwise construct scratch_cursor_gc with values from FACE
2039 xgcv
.background
= s
->face
->background
;
2040 xgcv
.foreground
= s
->face
->foreground
;
2041 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2042 xgcv
.font
= s
->font
;
2043 mask
= GCForeground
| GCBackground
| GCFont
;
2045 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2046 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2049 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2050 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2052 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2055 xassert (s
->gc
!= 0);
2059 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2060 Faces to use in the mode line have already been computed when the
2061 matrix was built, so there isn't much to do, here. */
2064 x_set_mode_line_face_gc (s
)
2065 struct glyph_string
*s
;
2067 s
->gc
= s
->face
->gc
;
2071 /* Set S->gc of glyph string S for drawing that glyph string. Set
2072 S->stippled_p to a non-zero value if the face of S has a stipple
2076 x_set_glyph_string_gc (s
)
2077 struct glyph_string
*s
;
2079 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2081 if (s
->hl
== DRAW_NORMAL_TEXT
)
2083 s
->gc
= s
->face
->gc
;
2084 s
->stippled_p
= s
->face
->stipple
!= 0;
2086 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2088 x_set_mode_line_face_gc (s
);
2089 s
->stippled_p
= s
->face
->stipple
!= 0;
2091 else if (s
->hl
== DRAW_CURSOR
)
2093 x_set_cursor_gc (s
);
2096 else if (s
->hl
== DRAW_MOUSE_FACE
)
2098 x_set_mouse_face_gc (s
);
2099 s
->stippled_p
= s
->face
->stipple
!= 0;
2101 else if (s
->hl
== DRAW_IMAGE_RAISED
2102 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2104 s
->gc
= s
->face
->gc
;
2105 s
->stippled_p
= s
->face
->stipple
!= 0;
2109 s
->gc
= s
->face
->gc
;
2110 s
->stippled_p
= s
->face
->stipple
!= 0;
2113 /* GC must have been set. */
2114 xassert (s
->gc
!= 0);
2118 /* Set clipping for output of glyph string S. S may be part of a mode
2119 line or menu if we don't have X toolkit support. */
2122 x_set_glyph_string_clipping (s
)
2123 struct glyph_string
*s
;
2126 get_glyph_string_clip_rect (s
, &r
);
2127 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2132 Compute left and right overhang of glyph string S. If S is a glyph
2133 string for a composition, assume overhangs don't exist. */
2136 mac_compute_glyph_string_overhangs (s
)
2137 struct glyph_string
*s
;
2140 && s
->first_glyph
->type
== CHAR_GLYPH
)
2143 MacFontStruct
*font
= s
->font
;
2146 if (font
->mac_style
)
2149 ATSUTextLayout text_layout
;
2153 SetRect (&r
, 0, 0, 0, 0);
2154 buf
= xmalloc (sizeof (UniChar
) * s
->nchars
);
2157 for (i
= 0; i
< s
->nchars
; i
++)
2158 buf
[i
] = (s
->char2b
[i
].byte1
<< 8) + s
->char2b
[i
].byte2
;
2160 err
= atsu_get_text_layout_with_text_ptr (buf
, s
->nchars
,
2164 err
= ATSUMeasureTextImage (text_layout
,
2165 kATSUFromTextBeginning
,
2174 TextFont (font
->mac_fontnum
);
2175 TextSize (font
->mac_fontsize
);
2176 TextFace (font
->mac_fontface
);
2179 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2183 char *buf
= xmalloc (s
->nchars
);
2186 SetRect (&r
, 0, 0, 0, 0);
2189 for (i
= 0; i
< s
->nchars
; ++i
)
2190 buf
[i
] = s
->char2b
[i
].byte2
;
2191 QDTextBounds (s
->nchars
, buf
, &r
);
2199 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2200 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2205 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2208 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2209 struct glyph_string
*s
;
2212 mac_erase_rectangle (s
->window
, s
->gc
, x
, y
, w
, h
);
2216 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2217 on Mac OS X because:
2218 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2219 into an offscreen graphics world first. So performance gain
2220 cannot be expected.)
2221 - It lowers rendering quality.
2222 - Some fonts leave garbage on cursor movement. */
2224 /* Draw the background of glyph_string S. If S->background_filled_p
2225 is non-zero don't draw it. FORCE_P non-zero means draw the
2226 background even if it wouldn't be drawn normally. This is used
2227 when a string preceding S draws into the background of S, or S
2228 contains the first component of a composition. */
2231 x_draw_glyph_string_background (s
, force_p
)
2232 struct glyph_string
*s
;
2235 /* Nothing to do if background has already been drawn or if it
2236 shouldn't be drawn in the first place. */
2237 if (!s
->background_filled_p
)
2239 int box_line_width
= max (s
->face
->box_line_width
, 0);
2241 #if 0 /* MAC_TODO: stipple */
2244 /* Fill background with a stipple pattern. */
2245 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2246 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2247 s
->y
+ box_line_width
,
2248 s
->background_width
,
2249 s
->height
- 2 * box_line_width
);
2250 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2251 s
->background_filled_p
= 1;
2255 #if defined (MAC_OS8) && !USE_ATSUI
2256 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2257 || s
->font_not_found_p
2258 || s
->extends_to_end_of_line_p
2262 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2263 s
->background_width
,
2264 s
->height
- 2 * box_line_width
);
2265 s
->background_filled_p
= 1;
2271 /* Draw the foreground of glyph string S. */
2274 x_draw_glyph_string_foreground (s
)
2275 struct glyph_string
*s
;
2279 /* If first glyph of S has a left box line, start drawing the text
2280 of S to the right of that box line. */
2281 if (s
->face
->box
!= FACE_NO_BOX
2282 && s
->first_glyph
->left_box_line_p
)
2283 x
= s
->x
+ abs (s
->face
->box_line_width
);
2287 /* Draw characters of S as rectangles if S's font could not be
2289 if (s
->font_not_found_p
)
2291 for (i
= 0; i
< s
->nchars
; ++i
)
2293 struct glyph
*g
= s
->first_glyph
+ i
;
2294 mac_draw_rectangle (s
->display
, s
->window
,
2295 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2297 x
+= g
->pixel_width
;
2302 char *char1b
= (char *) s
->char2b
;
2303 int boff
= s
->font_info
->baseline_offset
;
2305 if (s
->font_info
->vertical_centering
)
2306 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2308 /* If we can use 8-bit functions, condense S->char2b. */
2311 && GC_FONT (s
->gc
)->mac_style
== NULL
2314 for (i
= 0; i
< s
->nchars
; ++i
)
2315 char1b
[i
] = s
->char2b
[i
].byte2
;
2317 #if defined (MAC_OS8) && !USE_ATSUI
2318 /* Draw text with XDrawString if background has already been
2319 filled. Otherwise, use XDrawImageString. (Note that
2320 XDrawImageString is usually faster than XDrawString.) Always
2321 use XDrawImageString when drawing the cursor so that there is
2322 no chance that characters under a box cursor are invisible. */
2324 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2327 /* Draw characters with 16-bit or 8-bit functions. */
2330 || GC_FONT (s
->gc
)->mac_style
2333 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2334 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2336 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2337 s
->ybase
- boff
, char1b
, s
->nchars
);
2339 #if defined (MAC_OS8) && !USE_ATSUI
2343 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2344 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2346 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2347 s
->ybase
- boff
, char1b
, s
->nchars
);
2353 /* Draw the foreground of composite glyph string S. */
2356 x_draw_composite_glyph_string_foreground (s
)
2357 struct glyph_string
*s
;
2361 /* If first glyph of S has a left box line, start drawing the text
2362 of S to the right of that box line. */
2363 if (s
->face
->box
!= FACE_NO_BOX
2364 && s
->first_glyph
->left_box_line_p
)
2365 x
= s
->x
+ abs (s
->face
->box_line_width
);
2369 /* S is a glyph string for a composition. S->gidx is the index of
2370 the first character drawn for glyphs of this composition.
2371 S->gidx == 0 means we are drawing the very first character of
2372 this composition. */
2374 /* Draw a rectangle for the composition if the font for the very
2375 first character of the composition could not be loaded. */
2376 if (s
->font_not_found_p
)
2379 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2380 s
->width
- 1, s
->height
- 1);
2384 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2385 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2386 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2387 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2393 #ifdef USE_X_TOOLKIT
2395 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2398 /* Return the frame on which widget WIDGET is used.. Abort if frame
2399 cannot be determined. */
2401 static struct frame
*
2402 x_frame_of_widget (widget
)
2405 struct x_display_info
*dpyinfo
;
2409 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2411 /* Find the top-level shell of the widget. Note that this function
2412 can be called when the widget is not yet realized, so XtWindow
2413 (widget) == 0. That's the reason we can't simply use
2414 x_any_window_to_frame. */
2415 while (!XtIsTopLevelShell (widget
))
2416 widget
= XtParent (widget
);
2418 /* Look for a frame with that top-level widget. Allocate the color
2419 on that frame to get the right gamma correction value. */
2420 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2421 if (GC_FRAMEP (XCAR (tail
))
2422 && (f
= XFRAME (XCAR (tail
)),
2423 (f
->output_data
.nothing
!= 1
2424 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2425 && f
->output_data
.x
->widget
== widget
)
2432 /* Allocate the color COLOR->pixel on the screen and display of
2433 widget WIDGET in colormap CMAP. If an exact match cannot be
2434 allocated, try the nearest color available. Value is non-zero
2435 if successful. This is called from lwlib. */
2438 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2443 struct frame
*f
= x_frame_of_widget (widget
);
2444 return x_alloc_nearest_color (f
, cmap
, color
);
2448 #endif /* USE_X_TOOLKIT */
2450 #if 0 /* MAC_TODO */
2452 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2453 CMAP. If an exact match can't be allocated, try the nearest color
2454 available. Value is non-zero if successful. Set *COLOR to the
2458 x_alloc_nearest_color (f
, cmap
, color
)
2463 Display
*display
= FRAME_X_DISPLAY (f
);
2464 Screen
*screen
= FRAME_X_SCREEN (f
);
2467 gamma_correct (f
, color
);
2468 rc
= XAllocColor (display
, cmap
, color
);
2471 /* If we got to this point, the colormap is full, so we're going
2472 to try to get the next closest color. The algorithm used is
2473 a least-squares matching, which is what X uses for closest
2474 color matching with StaticColor visuals. */
2476 unsigned long nearest_delta
= ~0;
2477 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2478 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2480 for (i
= 0; i
< ncells
; ++i
)
2482 XQueryColors (display
, cmap
, cells
, ncells
);
2484 for (nearest
= i
= 0; i
< ncells
; ++i
)
2486 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2487 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2488 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2489 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2491 if (delta
< nearest_delta
)
2494 nearest_delta
= delta
;
2498 color
->red
= cells
[nearest
].red
;
2499 color
->green
= cells
[nearest
].green
;
2500 color
->blue
= cells
[nearest
].blue
;
2501 rc
= XAllocColor (display
, cmap
, color
);
2504 #ifdef DEBUG_X_COLORS
2506 register_color (color
->pixel
);
2507 #endif /* DEBUG_X_COLORS */
2513 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2514 It's necessary to do this instead of just using PIXEL directly to
2515 get color reference counts right. */
2518 x_copy_color (f
, pixel
)
2520 unsigned long pixel
;
2524 color
.pixel
= pixel
;
2526 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2527 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2529 #ifdef DEBUG_X_COLORS
2530 register_color (pixel
);
2536 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2537 It's necessary to do this instead of just using PIXEL directly to
2538 get color reference counts right. */
2541 x_copy_dpy_color (dpy
, cmap
, pixel
)
2544 unsigned long pixel
;
2548 color
.pixel
= pixel
;
2550 XQueryColor (dpy
, cmap
, &color
);
2551 XAllocColor (dpy
, cmap
, &color
);
2553 #ifdef DEBUG_X_COLORS
2554 register_color (pixel
);
2559 #endif /* MAC_TODO */
2562 /* Brightness beyond which a color won't have its highlight brightness
2565 Nominally, highlight colors for `3d' faces are calculated by
2566 brightening an object's color by a constant scale factor, but this
2567 doesn't yield good results for dark colors, so for colors who's
2568 brightness is less than this value (on a scale of 0-255) have to
2569 use an additional additive factor.
2571 The value here is set so that the default menu-bar/mode-line color
2572 (grey75) will not have its highlights changed at all. */
2573 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2576 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2577 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2578 If this produces the same color as COLOR, try a color where all RGB
2579 values have DELTA added. Return the allocated color in *COLOR.
2580 DISPLAY is the X display, CMAP is the colormap to operate on.
2581 Value is non-zero if successful. */
2584 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2586 unsigned long *color
;
2593 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2596 /* Change RGB values by specified FACTOR. Avoid overflow! */
2597 xassert (factor
>= 0);
2598 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2599 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2600 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2602 /* Calculate brightness of COLOR. */
2603 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2604 + BLUE_FROM_ULONG (*color
)) / 6;
2606 /* We only boost colors that are darker than
2607 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2608 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2609 /* Make an additive adjustment to NEW, because it's dark enough so
2610 that scaling by FACTOR alone isn't enough. */
2612 /* How far below the limit this color is (0 - 1, 1 being darker). */
2613 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2614 /* The additive adjustment. */
2615 int min_delta
= delta
* dimness
* factor
/ 2;
2618 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2619 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2620 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2622 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2623 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2624 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2628 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2629 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2630 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2632 /* MAC_TODO: Map to palette and retry with delta if same? */
2633 /* MAC_TODO: Free colors (if using palette)? */
2644 /* Set up the foreground color for drawing relief lines of glyph
2645 string S. RELIEF is a pointer to a struct relief containing the GC
2646 with which lines will be drawn. Use a color that is FACTOR or
2647 DELTA lighter or darker than the relief's background which is found
2648 in S->f->output_data.x->relief_background. If such a color cannot
2649 be allocated, use DEFAULT_PIXEL, instead. */
2652 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2654 struct relief
*relief
;
2657 unsigned long default_pixel
;
2660 struct mac_output
*di
= f
->output_data
.mac
;
2661 unsigned long mask
= GCForeground
;
2662 unsigned long pixel
;
2663 unsigned long background
= di
->relief_background
;
2664 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2666 /* MAC_TODO: Free colors (if using palette)? */
2668 /* Allocate new color. */
2669 xgcv
.foreground
= default_pixel
;
2671 if (dpyinfo
->n_planes
!= 1
2672 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2674 relief
->allocated_p
= 1;
2675 xgcv
.foreground
= relief
->pixel
= pixel
;
2678 if (relief
->gc
== 0)
2680 #if 0 /* MAC_TODO: stipple */
2681 xgcv
.stipple
= dpyinfo
->gray
;
2684 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2687 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2691 /* Set up colors for the relief lines around glyph string S. */
2694 x_setup_relief_colors (s
)
2695 struct glyph_string
*s
;
2697 struct mac_output
*di
= s
->f
->output_data
.mac
;
2698 unsigned long color
;
2700 if (s
->face
->use_box_color_for_shadows_p
)
2701 color
= s
->face
->box_color
;
2702 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2704 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2705 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2710 /* Get the background color of the face. */
2711 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2712 color
= xgcv
.background
;
2715 if (di
->white_relief
.gc
== 0
2716 || color
!= di
->relief_background
)
2718 di
->relief_background
= color
;
2719 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2720 WHITE_PIX_DEFAULT (s
->f
));
2721 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2722 BLACK_PIX_DEFAULT (s
->f
));
2727 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2728 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2729 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2730 relief. LEFT_P non-zero means draw a relief on the left side of
2731 the rectangle. RIGHT_P non-zero means draw a relief on the right
2732 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2736 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2737 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2739 int left_x
, top_y
, right_x
, bottom_y
, width
;
2740 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2743 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2744 Window window
= FRAME_MAC_WINDOW (f
);
2749 gc
= f
->output_data
.mac
->white_relief
.gc
;
2751 gc
= f
->output_data
.mac
->black_relief
.gc
;
2752 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2756 for (i
= 0; i
< width
; ++i
)
2757 XDrawLine (dpy
, window
, gc
,
2758 left_x
+ i
* left_p
, top_y
+ i
,
2759 right_x
- i
* right_p
, top_y
+ i
);
2763 for (i
= 0; i
< width
; ++i
)
2764 XDrawLine (dpy
, window
, gc
,
2765 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2767 mac_reset_clipping (dpy
, window
);
2769 gc
= f
->output_data
.mac
->black_relief
.gc
;
2771 gc
= f
->output_data
.mac
->white_relief
.gc
;
2772 mac_set_clip_rectangle (dpy
, window
,
2777 for (i
= 0; i
< width
; ++i
)
2778 XDrawLine (dpy
, window
, gc
,
2779 left_x
+ i
* left_p
, bottom_y
- i
,
2780 right_x
- i
* right_p
, bottom_y
- i
);
2784 for (i
= 0; i
< width
; ++i
)
2785 XDrawLine (dpy
, window
, gc
,
2786 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2788 mac_reset_clipping (dpy
, window
);
2792 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2793 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2794 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2795 left side of the rectangle. RIGHT_P non-zero means draw a line
2796 on the right side of the rectangle. CLIP_RECT is the clipping
2797 rectangle to use when drawing. */
2800 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2801 left_p
, right_p
, clip_rect
)
2802 struct glyph_string
*s
;
2803 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2808 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2809 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2810 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2813 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2814 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2818 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2819 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2822 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2823 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2827 XFillRectangle (s
->display
, s
->window
, s
->gc
,
2828 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2830 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2831 mac_reset_clipping (s
->display
, s
->window
);
2835 /* Draw a box around glyph string S. */
2838 x_draw_glyph_string_box (s
)
2839 struct glyph_string
*s
;
2841 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2842 int left_p
, right_p
;
2843 struct glyph
*last_glyph
;
2846 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2847 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2848 : window_box_right (s
->w
, s
->area
));
2850 /* The glyph that may have a right box line. */
2851 last_glyph
= (s
->cmp
|| s
->img
2853 : s
->first_glyph
+ s
->nchars
- 1);
2855 width
= abs (s
->face
->box_line_width
);
2856 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2858 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2860 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2862 bottom_y
= top_y
+ s
->height
- 1;
2864 left_p
= (s
->first_glyph
->left_box_line_p
2865 || (s
->hl
== DRAW_MOUSE_FACE
2867 || s
->prev
->hl
!= s
->hl
)));
2868 right_p
= (last_glyph
->right_box_line_p
2869 || (s
->hl
== DRAW_MOUSE_FACE
2871 || s
->next
->hl
!= s
->hl
)));
2873 get_glyph_string_clip_rect (s
, &clip_rect
);
2875 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2876 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2877 left_p
, right_p
, &clip_rect
);
2880 x_setup_relief_colors (s
);
2881 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2882 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2887 /* Draw foreground of image glyph string S. */
2890 x_draw_image_foreground (s
)
2891 struct glyph_string
*s
;
2894 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2896 /* If first glyph of S has a left box line, start drawing it to the
2897 right of that line. */
2898 if (s
->face
->box
!= FACE_NO_BOX
2899 && s
->first_glyph
->left_box_line_p
2901 x
+= abs (s
->face
->box_line_width
);
2903 /* If there is a margin around the image, adjust x- and y-position
2905 if (s
->slice
.x
== 0)
2906 x
+= s
->img
->hmargin
;
2907 if (s
->slice
.y
== 0)
2908 y
+= s
->img
->vmargin
;
2912 x_set_glyph_string_clipping (s
);
2915 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2916 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2917 s
->slice
.width
, s
->slice
.height
, x
, y
);
2920 mac_copy_area (s
->display
, s
->img
->pixmap
,
2921 s
->window
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2922 s
->slice
.width
, s
->slice
.height
, x
, y
);
2924 /* When the image has a mask, we can expect that at
2925 least part of a mouse highlight or a block cursor will
2926 be visible. If the image doesn't have a mask, make
2927 a block cursor visible by drawing a rectangle around
2928 the image. I believe it's looking better if we do
2929 nothing here for mouse-face. */
2930 if (s
->hl
== DRAW_CURSOR
)
2932 int r
= s
->img
->relief
;
2934 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2936 s
->slice
.width
+ r
*2 - 1,
2937 s
->slice
.height
+ r
*2 - 1);
2942 /* Draw a rectangle if image could not be loaded. */
2943 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2944 s
->slice
.width
- 1, s
->slice
.height
- 1);
2948 /* Draw a relief around the image glyph string S. */
2951 x_draw_image_relief (s
)
2952 struct glyph_string
*s
;
2954 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2957 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2959 /* If first glyph of S has a left box line, start drawing it to the
2960 right of that line. */
2961 if (s
->face
->box
!= FACE_NO_BOX
2962 && s
->first_glyph
->left_box_line_p
2964 x
+= abs (s
->face
->box_line_width
);
2966 /* If there is a margin around the image, adjust x- and y-position
2968 if (s
->slice
.x
== 0)
2969 x
+= s
->img
->hmargin
;
2970 if (s
->slice
.y
== 0)
2971 y
+= s
->img
->vmargin
;
2973 if (s
->hl
== DRAW_IMAGE_SUNKEN
2974 || s
->hl
== DRAW_IMAGE_RAISED
)
2976 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2977 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2981 thick
= abs (s
->img
->relief
);
2982 raised_p
= s
->img
->relief
> 0;
2987 x1
= x
+ s
->slice
.width
+ thick
- 1;
2988 y1
= y
+ s
->slice
.height
+ thick
- 1;
2990 x_setup_relief_colors (s
);
2991 get_glyph_string_clip_rect (s
, &r
);
2992 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2994 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2996 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3001 #if 0 /* TODO: figure out if we need to do this on Mac. */
3002 /* Draw the foreground of image glyph string S to PIXMAP. */
3005 x_draw_image_foreground_1 (s
, pixmap
)
3006 struct glyph_string
*s
;
3010 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3012 /* If first glyph of S has a left box line, start drawing it to the
3013 right of that line. */
3014 if (s
->face
->box
!= FACE_NO_BOX
3015 && s
->first_glyph
->left_box_line_p
3017 x
+= abs (s
->face
->box_line_width
);
3019 /* If there is a margin around the image, adjust x- and y-position
3021 if (s
->slice
.x
== 0)
3022 x
+= s
->img
->hmargin
;
3023 if (s
->slice
.y
== 0)
3024 y
+= s
->img
->vmargin
;
3029 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
3030 s
->img
->mask
, pixmap
, s
->gc
,
3031 s
->slice
.x
, s
->slice
.y
,
3032 s
->slice
.width
, s
->slice
.height
,
3036 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
3037 s
->slice
.x
, s
->slice
.y
,
3038 s
->slice
.width
, s
->slice
.height
,
3041 /* When the image has a mask, we can expect that at
3042 least part of a mouse highlight or a block cursor will
3043 be visible. If the image doesn't have a mask, make
3044 a block cursor visible by drawing a rectangle around
3045 the image. I believe it's looking better if we do
3046 nothing here for mouse-face. */
3047 if (s
->hl
== DRAW_CURSOR
)
3049 int r
= s
->img
->relief
;
3051 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
3052 s
->slice
.width
+ r
*2 - 1,
3053 s
->slice
.height
+ r
*2 - 1);
3058 /* Draw a rectangle if image could not be loaded. */
3059 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
3060 s
->slice
.width
- 1, s
->slice
.height
- 1);
3065 /* Draw part of the background of glyph string S. X, Y, W, and H
3066 give the rectangle to draw. */
3069 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3070 struct glyph_string
*s
;
3073 #if 0 /* MAC_TODO: stipple */
3076 /* Fill background with a stipple pattern. */
3077 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3078 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3079 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3082 #endif /* MAC_TODO */
3083 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3087 /* Draw image glyph string S.
3090 s->x +-------------------------
3093 | +-------------------------
3096 | | +-------------------
3102 x_draw_image_glyph_string (s
)
3103 struct glyph_string
*s
;
3106 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3107 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3111 height
= s
->height
- 2 * box_line_vwidth
;
3114 /* Fill background with face under the image. Do it only if row is
3115 taller than image or if image has a clip mask to reduce
3117 s
->stippled_p
= s
->face
->stipple
!= 0;
3118 if (height
> s
->slice
.height
3122 || s
->img
->pixmap
== 0
3123 || s
->width
!= s
->background_width
)
3126 if (s
->first_glyph
->left_box_line_p
3128 x
+= box_line_hwidth
;
3131 if (s
->slice
.y
== 0)
3132 y
+= box_line_vwidth
;
3134 #if 0 /* TODO: figure out if we need to do this on Mac. */
3137 /* Create a pixmap as large as the glyph string. Fill it
3138 with the background color. Copy the image to it, using
3139 its mask. Copy the temporary pixmap to the display. */
3140 int depth
= one_mac_display_info
.n_planes
;
3142 /* Create a pixmap as large as the glyph string. */
3143 pixmap
= XCreatePixmap (s
->display
, s
->window
,
3144 s
->background_width
,
3147 /* Fill the pixmap with the background color/stipple. */
3148 #if 0 /* TODO: stipple */
3151 /* Fill background with a stipple pattern. */
3152 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3153 XFillRectangle (s
->display
, pixmap
, s
->gc
,
3154 0, 0, s
->background_width
, s
->height
);
3155 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3161 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
3163 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
3164 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
3165 0, 0, s
->background_width
,
3167 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3172 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3174 s
->background_filled_p
= 1;
3177 /* Draw the foreground. */
3178 #if 0 /* TODO: figure out if we need to do this on Mac. */
3181 x_draw_image_foreground_1 (s
, pixmap
);
3182 x_set_glyph_string_clipping (s
);
3183 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
3184 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
3185 mac_reset_clipping (s
->display
, s
->window
);
3186 XFreePixmap (s
->display
, pixmap
);
3190 x_draw_image_foreground (s
);
3192 /* If we must draw a relief around the image, do it. */
3194 || s
->hl
== DRAW_IMAGE_RAISED
3195 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3196 x_draw_image_relief (s
);
3200 /* Draw stretch glyph string S. */
3203 x_draw_stretch_glyph_string (s
)
3204 struct glyph_string
*s
;
3206 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3207 s
->stippled_p
= s
->face
->stipple
!= 0;
3209 if (s
->hl
== DRAW_CURSOR
3210 && !x_stretch_cursor_p
)
3212 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3213 as wide as the stretch glyph. */
3214 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3217 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3219 /* Clear rest using the GC of the original non-cursor face. */
3220 if (width
< s
->background_width
)
3222 int x
= s
->x
+ width
, y
= s
->y
;
3223 int w
= s
->background_width
- width
, h
= s
->height
;
3227 if (s
->row
->mouse_face_p
3228 && cursor_in_mouse_face_p (s
->w
))
3230 x_set_mouse_face_gc (s
);
3236 get_glyph_string_clip_rect (s
, &r
);
3237 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
3239 #if 0 /* MAC_TODO: stipple */
3240 if (s
->face
->stipple
)
3242 /* Fill background with a stipple pattern. */
3243 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3244 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3245 XSetFillStyle (s
->display
, gc
, FillSolid
);
3248 #endif /* MAC_TODO */
3249 mac_erase_rectangle (s
->window
, gc
, x
, y
, w
, h
);
3251 mac_reset_clipping (s
->display
, s
->window
);
3254 else if (!s
->background_filled_p
)
3255 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3258 s
->background_filled_p
= 1;
3262 /* Draw glyph string S. */
3265 x_draw_glyph_string (s
)
3266 struct glyph_string
*s
;
3268 int relief_drawn_p
= 0;
3270 /* If S draws into the background of its successor that does not
3271 draw a cursor, draw the background of the successor first so that
3272 S can draw into it. This makes S->next use XDrawString instead
3273 of XDrawImageString. */
3274 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3275 && s
->next
->hl
!= DRAW_CURSOR
)
3277 xassert (s
->next
->img
== NULL
);
3278 x_set_glyph_string_gc (s
->next
);
3279 x_set_glyph_string_clipping (s
->next
);
3280 x_draw_glyph_string_background (s
->next
, 1);
3283 /* Set up S->gc, set clipping and draw S. */
3284 x_set_glyph_string_gc (s
);
3286 /* Draw relief (if any) in advance for char/composition so that the
3287 glyph string can be drawn over it. */
3288 if (!s
->for_overlaps
3289 && s
->face
->box
!= FACE_NO_BOX
3290 && (s
->first_glyph
->type
== CHAR_GLYPH
3291 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3294 x_set_glyph_string_clipping (s
);
3295 x_draw_glyph_string_background (s
, 1);
3296 x_draw_glyph_string_box (s
);
3297 x_set_glyph_string_clipping (s
);
3301 x_set_glyph_string_clipping (s
);
3303 switch (s
->first_glyph
->type
)
3306 x_draw_image_glyph_string (s
);
3310 x_draw_stretch_glyph_string (s
);
3314 if (s
->for_overlaps
)
3315 s
->background_filled_p
= 1;
3317 x_draw_glyph_string_background (s
, 0);
3318 x_draw_glyph_string_foreground (s
);
3321 case COMPOSITE_GLYPH
:
3322 if (s
->for_overlaps
|| s
->gidx
> 0)
3323 s
->background_filled_p
= 1;
3325 x_draw_glyph_string_background (s
, 1);
3326 x_draw_composite_glyph_string_foreground (s
);
3333 if (!s
->for_overlaps
)
3335 /* Draw underline. */
3336 if (s
->face
->underline_p
)
3338 unsigned long h
= 1;
3339 unsigned long dy
= s
->height
- h
;
3341 if (s
->face
->underline_defaulted_p
)
3342 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3347 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3348 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3349 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3351 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3355 /* Draw overline. */
3356 if (s
->face
->overline_p
)
3358 unsigned long dy
= 0, h
= 1;
3360 if (s
->face
->overline_color_defaulted_p
)
3361 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3366 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3367 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3368 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3370 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3374 /* Draw strike-through. */
3375 if (s
->face
->strike_through_p
)
3377 unsigned long h
= 1;
3378 unsigned long dy
= (s
->height
- h
) / 2;
3380 if (s
->face
->strike_through_color_defaulted_p
)
3381 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3386 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3387 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3388 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3390 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3394 /* Draw relief if not yet drawn. */
3395 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3396 x_draw_glyph_string_box (s
);
3399 /* Reset clipping. */
3400 mac_reset_clipping (s
->display
, s
->window
);
3403 /* Shift display to make room for inserted glyphs. */
3406 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3408 int x
, y
, width
, height
, shift_by
;
3410 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3411 f
->output_data
.mac
->normal_gc
,
3412 x
, y
, width
, height
,
3416 /* Delete N glyphs at the nominal cursor position. Not implemented
3427 /* Clear entire frame. If updating_frame is non-null, clear that
3428 frame. Otherwise clear the selected frame. */
3438 f
= SELECTED_FRAME ();
3440 /* Clearing the frame will erase any cursor, so mark them all as no
3442 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3443 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3444 output_cursor
.x
= -1;
3446 /* We don't set the output cursor here because there will always
3447 follow an explicit cursor_to. */
3449 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3451 /* We have to clear the scroll bars, too. If we have changed
3452 colors or something like that, then they should be notified. */
3453 x_scroll_bar_clear (f
);
3455 XFlush (FRAME_MAC_DISPLAY (f
));
3461 /* Invert the middle quarter of the frame for .15 sec. */
3463 /* We use the select system call to do the waiting, so we have to make
3464 sure it's available. If it isn't, we just won't do visual bells. */
3466 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3469 /* Subtract the `struct timeval' values X and Y, storing the result in
3470 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3473 timeval_subtract (result
, x
, y
)
3474 struct timeval
*result
, x
, y
;
3476 /* Perform the carry for the later subtraction by updating y. This
3477 is safer because on some systems the tv_sec member is unsigned. */
3478 if (x
.tv_usec
< y
.tv_usec
)
3480 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3481 y
.tv_usec
-= 1000000 * nsec
;
3485 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3487 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3488 y
.tv_usec
+= 1000000 * nsec
;
3492 /* Compute the time remaining to wait. tv_usec is certainly
3494 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3495 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3497 /* Return indication of whether the result should be considered
3499 return x
.tv_sec
< y
.tv_sec
;
3506 /* Get the height not including a menu bar widget. */
3507 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3508 /* Height of each line to flash. */
3509 int flash_height
= FRAME_LINE_HEIGHT (f
);
3510 /* These will be the left and right margins of the rectangles. */
3511 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3512 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3516 /* Don't flash the area between a scroll bar and the frame
3517 edge it is next to. */
3518 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3520 case vertical_scroll_bar_left
:
3521 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3524 case vertical_scroll_bar_right
:
3525 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3532 width
= flash_right
- flash_left
;
3536 /* If window is tall, flash top and bottom line. */
3537 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3539 mac_invert_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3541 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3542 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3543 width
, flash_height
);
3544 mac_invert_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3546 (height
- flash_height
3547 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3548 width
, flash_height
);
3551 /* If it is short, flash it all. */
3552 mac_invert_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3553 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3554 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3559 struct timeval wakeup
;
3561 EMACS_GET_TIME (wakeup
);
3563 /* Compute time to wait until, propagating carry from usecs. */
3564 wakeup
.tv_usec
+= 150000;
3565 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3566 wakeup
.tv_usec
%= 1000000;
3568 /* Keep waiting until past the time wakeup or any input gets
3570 while (! detect_input_pending ())
3572 struct timeval current
;
3573 struct timeval timeout
;
3575 EMACS_GET_TIME (current
);
3577 /* Break if result would be negative. */
3578 if (timeval_subtract (¤t
, wakeup
, current
))
3581 /* How long `select' should wait. */
3583 timeout
.tv_usec
= 10000;
3585 /* Try to wait that long--but we might wake up sooner. */
3586 select (0, NULL
, NULL
, NULL
, &timeout
);
3590 /* If window is tall, flash top and bottom line. */
3591 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3593 mac_invert_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3595 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3596 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3597 width
, flash_height
);
3598 mac_invert_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3600 (height
- flash_height
3601 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3602 width
, flash_height
);
3605 /* If it is short, flash it all. */
3606 mac_invert_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3607 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3608 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3615 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3618 /* Make audible bell. */
3623 struct frame
*f
= SELECTED_FRAME ();
3625 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3633 XFlush (FRAME_MAC_DISPLAY (f
));
3639 /* Specify how many text lines, from the top of the window,
3640 should be affected by insert-lines and delete-lines operations.
3641 This, and those operations, are used only within an update
3642 that is bounded by calls to x_update_begin and x_update_end. */
3645 XTset_terminal_window (n
)
3648 /* This function intentionally left blank. */
3653 /***********************************************************************
3655 ***********************************************************************/
3657 /* Perform an insert-lines or delete-lines operation, inserting N
3658 lines or deleting -N lines at vertical position VPOS. */
3661 x_ins_del_lines (vpos
, n
)
3668 /* Scroll part of the display as described by RUN. */
3671 x_scroll_run (w
, run
)
3675 struct frame
*f
= XFRAME (w
->frame
);
3676 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3678 /* Get frame-relative bounding box of the text display area of W,
3679 without mode lines. Include in this box the left and right
3681 window_box (w
, -1, &x
, &y
, &width
, &height
);
3683 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3684 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3685 bottom_y
= y
+ height
;
3689 /* Scrolling up. Make sure we don't copy part of the mode
3690 line at the bottom. */
3691 if (from_y
+ run
->height
> bottom_y
)
3692 height
= bottom_y
- from_y
;
3694 height
= run
->height
;
3698 /* Scolling down. Make sure we don't copy over the mode line.
3700 if (to_y
+ run
->height
> bottom_y
)
3701 height
= bottom_y
- to_y
;
3703 height
= run
->height
;
3708 /* Cursor off. Will be switched on again in x_update_window_end. */
3712 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3713 f
->output_data
.mac
->normal_gc
,
3723 /***********************************************************************
3725 ***********************************************************************/
3733 ControlRef root_control
;
3736 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3738 ActivateControl (root_control
);
3740 x_update_cursor (f
, 1);
3744 frame_unhighlight (f
)
3748 ControlRef root_control
;
3751 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3753 DeactivateControl (root_control
);
3755 x_update_cursor (f
, 1);
3758 /* The focus has changed. Update the frames as necessary to reflect
3759 the new situation. Note that we can't change the selected frame
3760 here, because the Lisp code we are interrupting might become confused.
3761 Each event gets marked with the frame in which it occurred, so the
3762 Lisp code can tell when the switch took place by examining the events. */
3765 x_new_focus_frame (dpyinfo
, frame
)
3766 struct x_display_info
*dpyinfo
;
3767 struct frame
*frame
;
3769 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3771 if (frame
!= dpyinfo
->x_focus_frame
)
3773 /* Set this before calling other routines, so that they see
3774 the correct value of x_focus_frame. */
3775 dpyinfo
->x_focus_frame
= frame
;
3777 if (old_focus
&& old_focus
->auto_lower
)
3778 x_lower_frame (old_focus
);
3781 selected_frame
= frame
;
3782 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3784 Fselect_window (selected_frame
->selected_window
, Qnil
);
3785 choose_minibuf_frame ();
3788 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3789 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3791 pending_autoraise_frame
= 0;
3794 x_frame_rehighlight (dpyinfo
);
3797 /* Handle FocusIn and FocusOut state changes for FRAME.
3798 If FRAME has focus and there exists more than one frame, puts
3799 a FOCUS_IN_EVENT into *BUFP. */
3802 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3804 struct mac_display_info
*dpyinfo
;
3805 struct frame
*frame
;
3806 struct input_event
*bufp
;
3808 if (type
== activeFlag
)
3810 if (dpyinfo
->x_focus_event_frame
!= frame
)
3812 x_new_focus_frame (dpyinfo
, frame
);
3813 dpyinfo
->x_focus_event_frame
= frame
;
3815 /* Don't stop displaying the initial startup message
3816 for a switch-frame event we don't need. */
3817 if (GC_NILP (Vterminal_frame
)
3818 && GC_CONSP (Vframe_list
)
3819 && !GC_NILP (XCDR (Vframe_list
)))
3821 bufp
->kind
= FOCUS_IN_EVENT
;
3822 XSETFRAME (bufp
->frame_or_window
, frame
);
3828 if (dpyinfo
->x_focus_event_frame
== frame
)
3830 dpyinfo
->x_focus_event_frame
= 0;
3831 x_new_focus_frame (dpyinfo
, 0);
3836 /* The focus may have changed. Figure out if it is a real focus change,
3837 by checking both FocusIn/Out and Enter/LeaveNotify events.
3839 Returns FOCUS_IN_EVENT event in *BUFP. */
3842 x_detect_focus_change (dpyinfo
, event
, bufp
)
3843 struct mac_display_info
*dpyinfo
;
3845 struct input_event
*bufp
;
3847 struct frame
*frame
;
3849 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3853 /* On Mac, this is only called from focus events, so no switch needed. */
3854 mac_focus_changed ((event
->modifiers
& activeFlag
),
3855 dpyinfo
, frame
, bufp
);
3859 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3862 x_mouse_leave (dpyinfo
)
3863 struct x_display_info
*dpyinfo
;
3865 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3868 /* The focus has changed, or we have redirected a frame's focus to
3869 another frame (this happens when a frame uses a surrogate
3870 mini-buffer frame). Shift the highlight as appropriate.
3872 The FRAME argument doesn't necessarily have anything to do with which
3873 frame is being highlighted or un-highlighted; we only use it to find
3874 the appropriate X display info. */
3877 XTframe_rehighlight (frame
)
3878 struct frame
*frame
;
3880 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3884 x_frame_rehighlight (dpyinfo
)
3885 struct x_display_info
*dpyinfo
;
3887 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3889 if (dpyinfo
->x_focus_frame
)
3891 dpyinfo
->x_highlight_frame
3892 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3893 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3894 : dpyinfo
->x_focus_frame
);
3895 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3897 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3898 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3902 dpyinfo
->x_highlight_frame
= 0;
3904 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3907 frame_unhighlight (old_highlight
);
3908 if (dpyinfo
->x_highlight_frame
)
3909 frame_highlight (dpyinfo
->x_highlight_frame
);
3915 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3917 #if 0 /* MAC_TODO */
3918 /* Initialize mode_switch_bit and modifier_meaning. */
3920 x_find_modifier_meanings (dpyinfo
)
3921 struct x_display_info
*dpyinfo
;
3923 int min_code
, max_code
;
3926 XModifierKeymap
*mods
;
3928 dpyinfo
->meta_mod_mask
= 0;
3929 dpyinfo
->shift_lock_mask
= 0;
3930 dpyinfo
->alt_mod_mask
= 0;
3931 dpyinfo
->super_mod_mask
= 0;
3932 dpyinfo
->hyper_mod_mask
= 0;
3935 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3937 min_code
= dpyinfo
->display
->min_keycode
;
3938 max_code
= dpyinfo
->display
->max_keycode
;
3941 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3942 min_code
, max_code
- min_code
+ 1,
3944 mods
= XGetModifierMapping (dpyinfo
->display
);
3946 /* Scan the modifier table to see which modifier bits the Meta and
3947 Alt keysyms are on. */
3949 int row
, col
; /* The row and column in the modifier table. */
3951 for (row
= 3; row
< 8; row
++)
3952 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3955 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3957 /* Zeroes are used for filler. Skip them. */
3961 /* Are any of this keycode's keysyms a meta key? */
3965 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3967 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3973 dpyinfo
->meta_mod_mask
|= (1 << row
);
3978 dpyinfo
->alt_mod_mask
|= (1 << row
);
3983 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3988 dpyinfo
->super_mod_mask
|= (1 << row
);
3992 /* Ignore this if it's not on the lock modifier. */
3993 if ((1 << row
) == LockMask
)
3994 dpyinfo
->shift_lock_mask
= LockMask
;
4002 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4003 if (! dpyinfo
->meta_mod_mask
)
4005 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
4006 dpyinfo
->alt_mod_mask
= 0;
4009 /* If some keys are both alt and meta,
4010 make them just meta, not alt. */
4011 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4013 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4016 XFree ((char *) syms
);
4017 XFreeModifiermap (mods
);
4020 #endif /* MAC_TODO */
4022 /* Convert between the modifier bits X uses and the modifier bits
4026 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4027 struct x_display_info
*dpyinfo
;
4028 unsigned short state
;
4030 return (((state
& shiftKey
) ? shift_modifier
: 0)
4031 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4032 | ((state
& cmdKey
) ? meta_modifier
: 0)
4033 | ((state
& optionKey
) ? alt_modifier
: 0));
4036 #if 0 /* MAC_TODO */
4037 static unsigned short
4038 x_emacs_to_x_modifiers (dpyinfo
, state
)
4039 struct x_display_info
*dpyinfo
;
4042 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4043 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4044 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4045 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4046 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4047 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4049 #endif /* MAC_TODO */
4051 /* Convert a keysym to its name. */
4054 x_get_keysym_name (keysym
)
4061 value
= XKeysymToString (keysym
);
4072 /* Function to report a mouse movement to the mainstream Emacs code.
4073 The input handler calls this.
4075 We have received a mouse movement event, which is given in *event.
4076 If the mouse is over a different glyph than it was last time, tell
4077 the mainstream emacs code by setting mouse_moved. If not, ask for
4078 another motion event, so we can check again the next time it moves. */
4080 static Point last_mouse_motion_position
;
4081 static Lisp_Object last_mouse_motion_frame
;
4084 note_mouse_movement (frame
, pos
)
4088 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4089 #if TARGET_API_MAC_CARBON
4093 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4094 last_mouse_motion_position
= *pos
;
4095 XSETFRAME (last_mouse_motion_frame
, frame
);
4097 #if TARGET_API_MAC_CARBON
4098 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4100 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4103 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4104 /* This case corresponds to LeaveNotify in X11. */
4106 /* If we move outside the frame, then we're certainly no
4107 longer on any text in the frame. */
4108 clear_mouse_face (dpyinfo
);
4109 dpyinfo
->mouse_face_mouse_frame
= 0;
4110 if (!dpyinfo
->grabbed
)
4111 rif
->define_frame_cursor (frame
,
4112 frame
->output_data
.mac
->nontext_cursor
);
4115 /* Has the mouse moved off the glyph it was on at the last sighting? */
4116 else if (pos
->h
< last_mouse_glyph
.left
4117 || pos
->h
>= last_mouse_glyph
.right
4118 || pos
->v
< last_mouse_glyph
.top
4119 || pos
->v
>= last_mouse_glyph
.bottom
)
4121 frame
->mouse_moved
= 1;
4122 last_mouse_scroll_bar
= Qnil
;
4123 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4128 /************************************************************************
4130 ************************************************************************/
4132 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
4135 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4138 redo_mouse_highlight ()
4140 if (!NILP (last_mouse_motion_frame
)
4141 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4142 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4143 last_mouse_motion_position
.h
,
4144 last_mouse_motion_position
.v
);
4148 /* Try to determine frame pixel position and size of the glyph under
4149 frame pixel coordinates X/Y on frame F . Return the position and
4150 size in *RECT. Value is non-zero if we could compute these
4154 glyph_rect (f
, x
, y
, rect
)
4161 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
4165 struct window
*w
= XWINDOW (window
);
4166 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
4167 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
4169 for (; r
< end
&& r
->enabled_p
; ++r
)
4170 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
4172 /* Found the row at y. */
4173 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
4174 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
4177 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
4178 rect
->bottom
= rect
->top
+ r
->height
;
4182 /* x is to the left of the first glyph in the row. */
4183 /* Shouldn't this be a pixel value?
4184 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
4186 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
4187 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
4191 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
4192 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
4194 /* x is on a glyph. */
4195 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4196 rect
->right
= rect
->left
+ g
->pixel_width
;
4200 /* x is to the right of the last glyph in the row. */
4201 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
4202 /* Shouldn't this be a pixel value?
4203 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
4205 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
4210 /* The y is not on any row. */
4214 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4216 /* Record the position of the mouse in last_mouse_glyph. */
4218 remember_mouse_glyph (f1
, gx
, gy
)
4222 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
4224 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
4225 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
4227 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
4228 round down even for negative values. */
4234 /* This was the original code from XTmouse_position, but it seems
4235 to give the position of the glyph diagonally next to the one
4236 the mouse is over. */
4237 gx
= (gx
+ width
- 1) / width
* width
;
4238 gy
= (gy
+ height
- 1) / height
* height
;
4240 gx
= gx
/ width
* width
;
4241 gy
= gy
/ height
* height
;
4244 last_mouse_glyph
.left
= gx
;
4245 last_mouse_glyph
.top
= gy
;
4246 last_mouse_glyph
.right
= gx
+ width
;
4247 last_mouse_glyph
.bottom
= gy
+ height
;
4252 static struct frame
*
4253 mac_focus_frame (dpyinfo
)
4254 struct mac_display_info
*dpyinfo
;
4256 if (dpyinfo
->x_focus_frame
)
4257 return dpyinfo
->x_focus_frame
;
4259 /* Mac version may get events, such as a menu bar click, even when
4260 all the frames are invisible. In this case, we regard the
4261 event came to the selected frame. */
4262 return SELECTED_FRAME ();
4266 /* Return the current position of the mouse.
4267 *fp should be a frame which indicates which display to ask about.
4269 If the mouse movement started in a scroll bar, set *fp, *bar_window,
4270 and *part to the frame, window, and scroll bar part that the mouse
4271 is over. Set *x and *y to the portion and whole of the mouse's
4272 position on the scroll bar.
4274 If the mouse movement started elsewhere, set *fp to the frame the
4275 mouse is on, *bar_window to nil, and *x and *y to the character cell
4278 Set *time to the server time-stamp for the time at which the mouse
4279 was at this position.
4281 Don't store anything if we don't have a valid set of values to report.
4283 This clears the mouse_moved flag, so we can wait for the next mouse
4287 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4290 Lisp_Object
*bar_window
;
4291 enum scroll_bar_part
*part
;
4293 unsigned long *time
;
4296 int ignore1
, ignore2
;
4297 struct frame
*f
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4298 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
4299 Lisp_Object frame
, tail
;
4303 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4304 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4307 /* Clear the mouse-moved flag for every frame on this display. */
4308 FOR_EACH_FRAME (tail
, frame
)
4309 XFRAME (frame
)->mouse_moved
= 0;
4311 last_mouse_scroll_bar
= Qnil
;
4313 SetPortWindowPort (wp
);
4315 GetMouse (&mouse_pos
);
4317 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
4318 &last_mouse_glyph
, insist
);
4321 *part
= scroll_bar_handle
;
4323 XSETINT (*x
, mouse_pos
.h
);
4324 XSETINT (*y
, mouse_pos
.v
);
4325 *time
= last_mouse_movement_time
;
4332 /************************************************************************
4334 ************************************************************************/
4336 #ifdef USE_TOOLKIT_SCROLL_BARS
4338 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4339 static OSStatus install_scroll_bar_timer
P_ ((void));
4340 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4341 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4342 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4343 struct input_event
*));
4344 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4346 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4348 struct input_event
*));
4349 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4350 struct input_event
*));
4351 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4352 Point
, struct input_event
*));
4353 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4356 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4358 static int last_scroll_bar_part
;
4360 static EventLoopTimerRef scroll_bar_timer
;
4362 static int scroll_bar_timer_event_posted_p
;
4364 #define SCROLL_BAR_FIRST_DELAY 0.5
4365 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4368 scroll_bar_timer_callback (timer
, data
)
4369 EventLoopTimerRef timer
;
4372 EventRef event
= NULL
;
4375 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4376 kEventAttributeNone
, &event
);
4381 GetMouse (&mouse_pos
);
4382 LocalToGlobal (&mouse_pos
);
4383 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4384 sizeof (Point
), &mouse_pos
);
4388 UInt32 modifiers
= GetCurrentKeyModifiers ();
4390 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4391 sizeof (UInt32
), &modifiers
);
4394 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4395 kEventPriorityStandard
);
4397 scroll_bar_timer_event_posted_p
= 1;
4400 ReleaseEvent (event
);
4404 install_scroll_bar_timer ()
4406 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4408 if (scroll_bar_timer_callbackUPP
== NULL
)
4409 scroll_bar_timer_callbackUPP
=
4410 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4412 if (scroll_bar_timer
== NULL
)
4413 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4414 kEventDurationForever as delays. */
4416 InstallEventLoopTimer (GetCurrentEventLoop (),
4417 kEventDurationForever
, kEventDurationForever
,
4418 scroll_bar_timer_callbackUPP
, NULL
,
4423 set_scroll_bar_timer (delay
)
4424 EventTimerInterval delay
;
4426 if (scroll_bar_timer
== NULL
)
4427 install_scroll_bar_timer ();
4429 scroll_bar_timer_event_posted_p
= 0;
4431 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4435 control_part_code_to_scroll_bar_part (part_code
)
4436 ControlPartCode part_code
;
4440 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4441 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4442 case kControlPageUpPart
: return scroll_bar_above_handle
;
4443 case kControlPageDownPart
: return scroll_bar_below_handle
;
4444 case kControlIndicatorPart
: return scroll_bar_handle
;
4451 construct_scroll_bar_click (bar
, part
, bufp
)
4452 struct scroll_bar
*bar
;
4454 struct input_event
*bufp
;
4456 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4457 bufp
->frame_or_window
= bar
->window
;
4461 XSETINT (bufp
->x
, 0);
4462 XSETINT (bufp
->y
, 0);
4463 bufp
->modifiers
= 0;
4467 get_control_part_bounds (ch
, part_code
, rect
)
4469 ControlPartCode part_code
;
4472 RgnHandle region
= NewRgn ();
4475 err
= GetControlRegion (ch
, part_code
, region
);
4477 GetRegionBounds (region
, rect
);
4478 DisposeRgn (region
);
4484 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4485 struct scroll_bar
*bar
;
4486 ControlPartCode part_code
;
4487 struct input_event
*bufp
;
4489 int part
= control_part_code_to_scroll_bar_part (part_code
);
4494 if (part
!= scroll_bar_handle
)
4496 construct_scroll_bar_click (bar
, part
, bufp
);
4497 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4498 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4501 last_scroll_bar_part
= part
;
4502 bar
->dragging
= Qnil
;
4503 tracked_scroll_bar
= bar
;
4507 x_scroll_bar_handle_release (bar
, bufp
)
4508 struct scroll_bar
*bar
;
4509 struct input_event
*bufp
;
4511 if (last_scroll_bar_part
!= scroll_bar_handle
4512 || !GC_NILP (bar
->dragging
))
4513 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4515 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4516 set_scroll_bar_timer (kEventDurationForever
);
4518 last_scroll_bar_part
= -1;
4519 bar
->dragging
= Qnil
;
4520 tracked_scroll_bar
= NULL
;
4524 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4526 struct scroll_bar
*bar
;
4528 struct input_event
*bufp
;
4530 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4532 if (last_scroll_bar_part
== scroll_bar_handle
)
4537 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4538 kControlIndicatorPart
, &r
);
4540 if (GC_NILP (bar
->dragging
))
4541 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4543 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4544 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4545 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4550 if (top
> top_range
)
4553 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4554 XSETINT (bufp
->x
, top
);
4555 XSETINT (bufp
->y
, top_range
);
4559 ControlPartCode part_code
;
4560 int unhilite_p
= 0, part
;
4562 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4566 part
= control_part_code_to_scroll_bar_part (part_code
);
4568 switch (last_scroll_bar_part
)
4570 case scroll_bar_above_handle
:
4571 case scroll_bar_below_handle
:
4572 if (part
!= scroll_bar_above_handle
4573 && part
!= scroll_bar_below_handle
)
4577 case scroll_bar_up_arrow
:
4578 case scroll_bar_down_arrow
:
4579 if (part
!= scroll_bar_up_arrow
4580 && part
!= scroll_bar_down_arrow
)
4587 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4588 else if (part
!= last_scroll_bar_part
4589 || scroll_bar_timer_event_posted_p
)
4591 construct_scroll_bar_click (bar
, part
, bufp
);
4592 last_scroll_bar_part
= part
;
4593 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4594 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4599 /* Set the thumb size and position of scroll bar BAR. We are currently
4600 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4603 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4604 struct scroll_bar
*bar
;
4605 int portion
, position
, whole
;
4607 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4609 int value
, viewsize
, maximum
;
4611 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4612 value
= 0, viewsize
= 1, maximum
= 0;
4617 maximum
= max (0, whole
- portion
);
4622 SetControl32BitMinimum (ch
, 0);
4623 SetControl32BitMaximum (ch
, maximum
);
4624 SetControl32BitValue (ch
, value
);
4625 SetControlViewSize (ch
, viewsize
);
4630 #endif /* USE_TOOLKIT_SCROLL_BARS */
4634 /************************************************************************
4635 Scroll bars, general
4636 ************************************************************************/
4638 /* Create a scroll bar and return the scroll bar vector for it. W is
4639 the Emacs window on which to create the scroll bar. TOP, LEFT,
4640 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4643 static struct scroll_bar
*
4644 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4646 int top
, left
, width
, height
, disp_top
, disp_height
;
4648 struct frame
*f
= XFRAME (w
->frame
);
4649 struct scroll_bar
*bar
4650 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4658 r
.right
= left
+ width
;
4659 r
.bottom
= disp_top
+ disp_height
;
4661 #if TARGET_API_MAC_CARBON
4662 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4663 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4665 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4666 0, 0, 0, scrollBarProc
, (long) bar
);
4668 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4670 XSETWINDOW (bar
->window
, w
);
4671 XSETINT (bar
->top
, top
);
4672 XSETINT (bar
->left
, left
);
4673 XSETINT (bar
->width
, width
);
4674 XSETINT (bar
->height
, height
);
4675 XSETINT (bar
->start
, 0);
4676 XSETINT (bar
->end
, 0);
4677 bar
->dragging
= Qnil
;
4678 #ifdef USE_TOOLKIT_SCROLL_BARS
4679 bar
->track_top
= Qnil
;
4680 bar
->track_height
= Qnil
;
4683 /* Add bar to its frame's list of scroll bars. */
4684 bar
->next
= FRAME_SCROLL_BARS (f
);
4686 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4687 if (!NILP (bar
->next
))
4688 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4695 /* Draw BAR's handle in the proper position.
4697 If the handle is already drawn from START to END, don't bother
4698 redrawing it, unless REBUILD is non-zero; in that case, always
4699 redraw it. (REBUILD is handy for drawing the handle after expose
4702 Normally, we want to constrain the start and end of the handle to
4703 fit inside its rectangle, but if the user is dragging the scroll
4704 bar handle, we want to let them drag it down all the way, so that
4705 the bar's top is as far down as it goes; otherwise, there's no way
4706 to move to the very end of the buffer. */
4708 #ifndef USE_TOOLKIT_SCROLL_BARS
4711 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4712 struct scroll_bar
*bar
;
4716 int dragging
= ! NILP (bar
->dragging
);
4717 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4718 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4719 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4720 int length
= end
- start
;
4722 /* If the display is already accurate, do nothing. */
4724 && start
== XINT (bar
->start
)
4725 && end
== XINT (bar
->end
))
4730 /* Make sure the values are reasonable, and try to preserve the
4731 distance between start and end. */
4734 else if (start
> top_range
)
4736 end
= start
+ length
;
4740 else if (end
> top_range
&& ! dragging
)
4743 /* Store the adjusted setting in the scroll bar. */
4744 XSETINT (bar
->start
, start
);
4745 XSETINT (bar
->end
, end
);
4747 /* Clip the end position, just for display. */
4748 if (end
> top_range
)
4751 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4752 top positions, to make sure the handle is always at least that
4753 many pixels tall. */
4754 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4756 SetControlMinimum (ch
, 0);
4757 /* Don't inadvertently activate deactivated scroll bars */
4758 if (GetControlMaximum (ch
) != -1)
4759 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4761 SetControlValue (ch
, start
);
4762 #if TARGET_API_MAC_CARBON
4763 SetControlViewSize (ch
, end
- start
);
4769 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4771 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4775 x_scroll_bar_remove (bar
)
4776 struct scroll_bar
*bar
;
4778 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4782 /* Destroy the Mac scroll bar control */
4783 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4785 /* Disassociate this scroll bar from its window. */
4786 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4792 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4793 that we are displaying PORTION characters out of a total of WHOLE
4794 characters, starting at POSITION. If WINDOW has no scroll bar,
4798 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4800 int portion
, whole
, position
;
4802 struct frame
*f
= XFRAME (w
->frame
);
4803 struct scroll_bar
*bar
;
4804 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4805 int window_y
, window_height
;
4807 /* Get window dimensions. */
4808 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4810 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4811 height
= window_height
;
4813 /* Compute the left edge of the scroll bar area. */
4814 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4816 /* Compute the width of the scroll bar which might be less than
4817 the width of the area reserved for the scroll bar. */
4818 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4819 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4823 /* Compute the left edge of the scroll bar. */
4824 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4827 sb_left
= left
+ width
- sb_width
;
4829 /* Adjustments according to Inside Macintosh to make it look nice */
4831 disp_height
= height
;
4837 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4843 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4846 /* Does the scroll bar exist yet? */
4847 if (NILP (w
->vertical_scroll_bar
))
4850 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4851 left
, top
, width
, height
, 0);
4853 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4855 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4859 /* It may just need to be moved and resized. */
4862 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4863 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4867 /* If already correctly positioned, do nothing. */
4868 if (!(XINT (bar
->left
) == sb_left
4869 && XINT (bar
->top
) == top
4870 && XINT (bar
->width
) == sb_width
4871 && XINT (bar
->height
) == height
))
4873 /* Since toolkit scroll bars are smaller than the space reserved
4874 for them on the frame, we have to clear "under" them. */
4875 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4876 left
, top
, width
, height
, 0);
4879 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4880 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4881 sb_left
- 1, top
, 1, height
, 0);
4885 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4886 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4888 if (sb_width
< disp_height
)
4891 /* Remember new settings. */
4892 XSETINT (bar
->left
, sb_left
);
4893 XSETINT (bar
->top
, top
);
4894 XSETINT (bar
->width
, sb_width
);
4895 XSETINT (bar
->height
, height
);
4896 #ifdef USE_TOOLKIT_SCROLL_BARS
4897 bar
->track_top
= Qnil
;
4898 bar
->track_height
= Qnil
;
4905 #ifdef USE_TOOLKIT_SCROLL_BARS
4906 if (NILP (bar
->track_top
))
4908 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4913 SetControl32BitMinimum (ch
, 0);
4914 SetControl32BitMaximum (ch
, 1);
4915 SetControlViewSize (ch
, 1);
4917 /* Move the scroll bar thumb to the top. */
4918 SetControl32BitValue (ch
, 0);
4919 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4921 /* Move the scroll bar thumb to the bottom. */
4922 SetControl32BitValue (ch
, 1);
4923 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4925 UnionRect (&r0
, &r1
, &r0
);
4926 XSETINT (bar
->track_top
, r0
.top
);
4927 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4932 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4933 #else /* not USE_TOOLKIT_SCROLL_BARS */
4934 /* Set the scroll bar's current state, unless we're currently being
4936 if (NILP (bar
->dragging
))
4938 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4941 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4944 int start
= ((double) position
* top_range
) / whole
;
4945 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4946 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4949 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4953 /* The following three hooks are used when we're doing a thorough
4954 redisplay of the frame. We don't explicitly know which scroll bars
4955 are going to be deleted, because keeping track of when windows go
4956 away is a real pain - "Can you say set-window-configuration, boys
4957 and girls?" Instead, we just assert at the beginning of redisplay
4958 that *all* scroll bars are to be removed, and then save a scroll bar
4959 from the fiery pit when we actually redisplay its window. */
4961 /* Arrange for all scroll bars on FRAME to be removed at the next call
4962 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4963 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4966 XTcondemn_scroll_bars (frame
)
4969 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4970 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4973 bar
= FRAME_SCROLL_BARS (frame
);
4974 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4975 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4976 XSCROLL_BAR (bar
)->prev
= Qnil
;
4977 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4978 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4979 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4984 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4985 Note that WINDOW isn't necessarily condemned at all. */
4988 XTredeem_scroll_bar (window
)
4989 struct window
*window
;
4991 struct scroll_bar
*bar
;
4994 /* We can't redeem this window's scroll bar if it doesn't have one. */
4995 if (NILP (window
->vertical_scroll_bar
))
4998 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
5000 /* Unlink it from the condemned list. */
5001 f
= XFRAME (WINDOW_FRAME (window
));
5002 if (NILP (bar
->prev
))
5004 /* If the prev pointer is nil, it must be the first in one of
5006 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
5007 /* It's not condemned. Everything's fine. */
5009 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
5010 window
->vertical_scroll_bar
))
5011 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
5013 /* If its prev pointer is nil, it must be at the front of
5014 one or the other! */
5018 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
5020 if (! NILP (bar
->next
))
5021 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
5023 bar
->next
= FRAME_SCROLL_BARS (f
);
5025 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
5026 if (! NILP (bar
->next
))
5027 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
5030 /* Remove all scroll bars on FRAME that haven't been saved since the
5031 last call to `*condemn_scroll_bars_hook'. */
5034 XTjudge_scroll_bars (f
)
5037 Lisp_Object bar
, next
;
5039 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
5041 /* Clear out the condemned list now so we won't try to process any
5042 more events on the hapless scroll bars. */
5043 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
5045 for (; ! NILP (bar
); bar
= next
)
5047 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
5049 x_scroll_bar_remove (b
);
5052 b
->next
= b
->prev
= Qnil
;
5055 /* Now there should be no references to the condemned scroll bars,
5056 and they should get garbage-collected. */
5060 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
5061 is set to something other than NO_EVENT, it is enqueued.
5063 This may be called from a signal handler, so we have to ignore GC
5067 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
5068 struct scroll_bar
*bar
;
5069 ControlPartCode part_code
;
5071 struct input_event
*bufp
;
5073 int win_y
, top_range
;
5075 if (! GC_WINDOWP (bar
->window
))
5078 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5079 bufp
->frame_or_window
= bar
->window
;
5082 bar
->dragging
= Qnil
;
5086 case kControlUpButtonPart
:
5087 bufp
->part
= scroll_bar_up_arrow
;
5089 case kControlDownButtonPart
:
5090 bufp
->part
= scroll_bar_down_arrow
;
5092 case kControlPageUpPart
:
5093 bufp
->part
= scroll_bar_above_handle
;
5095 case kControlPageDownPart
:
5096 bufp
->part
= scroll_bar_below_handle
;
5098 #if TARGET_API_MAC_CARBON
5101 case kControlIndicatorPart
:
5103 if (er
->what
== mouseDown
)
5104 bar
->dragging
= make_number (0);
5105 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5106 bufp
->part
= scroll_bar_handle
;
5110 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5111 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5113 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5117 if (! NILP (bar
->dragging
))
5118 win_y
-= XINT (bar
->dragging
);
5122 if (win_y
> top_range
)
5125 XSETINT (bufp
->x
, win_y
);
5126 XSETINT (bufp
->y
, top_range
);
5129 #ifndef USE_TOOLKIT_SCROLL_BARS
5131 /* Handle some mouse motion while someone is dragging the scroll bar.
5133 This may be called from a signal handler, so we have to ignore GC
5137 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5138 struct scroll_bar
*bar
;
5142 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5144 last_mouse_movement_time
= t
;
5147 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5149 /* If we're dragging the bar, display it. */
5150 if (! GC_NILP (bar
->dragging
))
5152 /* Where should the handle be now? */
5153 int new_start
= y_pos
- 24;
5155 if (new_start
!= XINT (bar
->start
))
5157 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5159 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5164 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5166 /* Return information to the user about the current position of the mouse
5167 on the scroll bar. */
5170 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5172 Lisp_Object
*bar_window
;
5173 enum scroll_bar_part
*part
;
5175 unsigned long *time
;
5177 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5178 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5179 #if TARGET_API_MAC_CARBON
5180 WindowPtr wp
= GetControlOwner (ch
);
5182 WindowPtr wp
= (*ch
)->contrlOwner
;
5185 struct frame
*f
= mac_window_to_frame (wp
);
5186 int win_y
, top_range
;
5188 SetPortWindowPort (wp
);
5190 GetMouse (&mouse_pos
);
5192 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5193 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5195 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5199 if (! NILP (bar
->dragging
))
5200 win_y
-= XINT (bar
->dragging
);
5204 if (win_y
> top_range
)
5208 *bar_window
= bar
->window
;
5210 if (! NILP (bar
->dragging
))
5211 *part
= scroll_bar_handle
;
5212 else if (win_y
< XINT (bar
->start
))
5213 *part
= scroll_bar_above_handle
;
5214 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5215 *part
= scroll_bar_handle
;
5217 *part
= scroll_bar_below_handle
;
5219 XSETINT (*x
, win_y
);
5220 XSETINT (*y
, top_range
);
5223 last_mouse_scroll_bar
= Qnil
;
5225 *time
= last_mouse_movement_time
;
5229 /* The screen has been cleared so we may have changed foreground or
5230 background colors, and the scroll bars may need to be redrawn.
5231 Clear out the scroll bars, and ask for expose events, so we can
5235 x_scroll_bar_clear (f
)
5238 XTcondemn_scroll_bars (f
);
5239 XTjudge_scroll_bars (f
);
5243 /***********************************************************************
5245 ***********************************************************************/
5247 /* Set clipping for output in glyph row ROW. W is the window in which
5248 we operate. GC is the graphics context to set clipping in.
5250 ROW may be a text row or, e.g., a mode line. Text rows must be
5251 clipped to the interior of the window dedicated to text display,
5252 mode lines must be clipped to the whole window. */
5255 x_clip_to_row (w
, row
, area
, gc
)
5257 struct glyph_row
*row
;
5261 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5263 int window_x
, window_y
, window_width
;
5265 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5267 clip_rect
.left
= window_x
;
5268 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5269 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5270 clip_rect
.right
= clip_rect
.left
+ window_width
;
5271 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5273 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
5277 /* Draw a hollow box cursor on window W in glyph row ROW. */
5280 x_draw_hollow_cursor (w
, row
)
5282 struct glyph_row
*row
;
5284 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5285 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5286 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5289 struct glyph
*cursor_glyph
;
5292 /* Get the glyph the cursor is on. If we can't tell because
5293 the current matrix is invalid or such, give up. */
5294 cursor_glyph
= get_phys_cursor_glyph (w
);
5295 if (cursor_glyph
== NULL
)
5298 /* Compute frame-relative coordinates for phys cursor. */
5299 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5300 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5301 wd
= w
->phys_cursor_width
;
5303 /* The foreground of cursor_gc is typically the same as the normal
5304 background color, which can cause the cursor box to be invisible. */
5305 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5306 if (dpyinfo
->scratch_cursor_gc
)
5307 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5309 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5310 GCForeground
, &xgcv
);
5311 gc
= dpyinfo
->scratch_cursor_gc
;
5313 /* Set clipping, draw the rectangle, and reset clipping again. */
5314 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5315 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
5316 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5320 /* Draw a bar cursor on window W in glyph row ROW.
5322 Implementation note: One would like to draw a bar cursor with an
5323 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5324 Unfortunately, I didn't find a font yet that has this property set.
5328 x_draw_bar_cursor (w
, row
, width
, kind
)
5330 struct glyph_row
*row
;
5332 enum text_cursor_kinds kind
;
5334 struct frame
*f
= XFRAME (w
->frame
);
5335 struct glyph
*cursor_glyph
;
5337 /* If cursor is out of bounds, don't draw garbage. This can happen
5338 in mini-buffer windows when switching between echo area glyphs
5340 cursor_glyph
= get_phys_cursor_glyph (w
);
5341 if (cursor_glyph
== NULL
)
5344 /* If on an image, draw like a normal cursor. That's usually better
5345 visible than drawing a bar, esp. if the image is large so that
5346 the bar might not be in the window. */
5347 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5349 struct glyph_row
*row
;
5350 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5351 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5355 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5356 Window window
= FRAME_MAC_WINDOW (f
);
5357 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5358 unsigned long mask
= GCForeground
| GCBackground
;
5359 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5362 /* If the glyph's background equals the color we normally draw
5363 the bar cursor in, the bar cursor in its normal color is
5364 invisible. Use the glyph's foreground color instead in this
5365 case, on the assumption that the glyph's colors are chosen so
5366 that the glyph is legible. */
5367 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5368 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5370 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5373 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5376 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5377 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5381 width
= FRAME_CURSOR_WIDTH (f
);
5382 width
= min (cursor_glyph
->pixel_width
, width
);
5384 w
->phys_cursor_width
= width
;
5385 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5387 if (kind
== BAR_CURSOR
)
5388 XFillRectangle (dpy
, window
, gc
,
5389 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5390 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5391 width
, row
->height
);
5393 XFillRectangle (dpy
, window
, gc
,
5394 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5395 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5396 row
->height
- width
),
5397 cursor_glyph
->pixel_width
,
5400 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
5405 /* RIF: Define cursor CURSOR on frame F. */
5408 mac_define_frame_cursor (f
, cursor
)
5412 SetThemeCursor (cursor
);
5416 /* RIF: Clear area on frame F. */
5419 mac_clear_frame_area (f
, x
, y
, width
, height
)
5421 int x
, y
, width
, height
;
5423 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
5424 x
, y
, width
, height
, 0);
5428 /* RIF: Draw cursor on window W. */
5431 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5433 struct glyph_row
*glyph_row
;
5435 int cursor_type
, cursor_width
;
5440 w
->phys_cursor_type
= cursor_type
;
5441 w
->phys_cursor_on_p
= 1;
5443 if (glyph_row
->exact_window_width_line_p
5444 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5446 glyph_row
->cursor_in_fringe_p
= 1;
5447 draw_fringe_bitmap (w
, glyph_row
, 0);
5450 switch (cursor_type
)
5452 case HOLLOW_BOX_CURSOR
:
5453 x_draw_hollow_cursor (w
, glyph_row
);
5456 case FILLED_BOX_CURSOR
:
5457 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5461 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5465 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5469 w
->phys_cursor_width
= 0;
5481 #if 0 /* MAC_TODO: no icon support yet. */
5483 x_bitmap_icon (f
, icon
)
5489 if (FRAME_W32_WINDOW (f
) == 0)
5493 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5494 else if (STRINGP (icon
))
5495 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5496 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5497 else if (SYMBOLP (icon
))
5501 if (EQ (icon
, intern ("application")))
5502 name
= (LPCTSTR
) IDI_APPLICATION
;
5503 else if (EQ (icon
, intern ("hand")))
5504 name
= (LPCTSTR
) IDI_HAND
;
5505 else if (EQ (icon
, intern ("question")))
5506 name
= (LPCTSTR
) IDI_QUESTION
;
5507 else if (EQ (icon
, intern ("exclamation")))
5508 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5509 else if (EQ (icon
, intern ("asterisk")))
5510 name
= (LPCTSTR
) IDI_ASTERISK
;
5511 else if (EQ (icon
, intern ("winlogo")))
5512 name
= (LPCTSTR
) IDI_WINLOGO
;
5516 hicon
= LoadIcon (NULL
, name
);
5524 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5529 #endif /* MAC_TODO */
5531 /************************************************************************
5533 ************************************************************************/
5535 /* Display Error Handling functions not used on W32. Listing them here
5536 helps diff stay in step when comparing w32term.c with xterm.c.
5538 x_error_catcher (display, error)
5539 x_catch_errors (dpy)
5540 x_catch_errors_unwind (old_val)
5541 x_check_errors (dpy, format)
5542 x_had_errors_p (dpy)
5543 x_clear_errors (dpy)
5544 x_uncatch_errors (dpy, count)
5546 x_connection_signal (signalnum)
5547 x_connection_closed (dpy, error_message)
5548 x_error_quitter (display, error)
5549 x_error_handler (display, error)
5550 x_io_error_quitter (display)
5555 /* Changing the font of the frame. */
5557 /* Give frame F the font named FONTNAME as its default font, and
5558 return the full name of that font. FONTNAME may be a wildcard
5559 pattern; in that case, we choose some font that fits the pattern.
5560 The return value shows which font we chose. */
5563 x_new_font (f
, fontname
)
5565 register char *fontname
;
5567 struct font_info
*fontp
5568 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5573 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5574 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5575 FRAME_FONTSET (f
) = -1;
5577 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5578 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5579 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5581 compute_fringe_widths (f
, 1);
5583 /* Compute the scroll bar width in character columns. */
5584 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5586 int wid
= FRAME_COLUMN_WIDTH (f
);
5587 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5588 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5592 int wid
= FRAME_COLUMN_WIDTH (f
);
5593 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5596 /* Now make the frame display the given font. */
5597 if (FRAME_MAC_WINDOW (f
) != 0)
5599 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5601 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5603 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5606 /* Don't change the size of a tip frame; there's no point in
5607 doing it because it's done in Fx_show_tip, and it leads to
5608 problems because the tip frame has no widget. */
5609 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5610 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5613 return build_string (fontp
->full_name
);
5616 /* Give frame F the fontset named FONTSETNAME as its default font, and
5617 return the full name of that fontset. FONTSETNAME may be a wildcard
5618 pattern; in that case, we choose some fontset that fits the pattern.
5619 The return value shows which fontset we chose. */
5622 x_new_fontset (f
, fontsetname
)
5626 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5632 if (FRAME_FONTSET (f
) == fontset
)
5633 /* This fontset is already set in frame F. There's nothing more
5635 return fontset_name (fontset
);
5637 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5639 if (!STRINGP (result
))
5640 /* Can't load ASCII font. */
5643 /* Since x_new_font doesn't update any fontset information, do it now. */
5644 FRAME_FONTSET (f
) = fontset
;
5646 return build_string (fontsetname
);
5650 /***********************************************************************
5651 TODO: W32 Input Methods
5652 ***********************************************************************/
5653 /* Listing missing functions from xterm.c helps diff stay in step.
5655 xim_destroy_callback (xim, client_data, call_data)
5656 xim_open_dpy (dpyinfo, resource_name)
5658 xim_instantiate_callback (display, client_data, call_data)
5659 xim_initialize (dpyinfo, resource_name)
5660 xim_close_dpy (dpyinfo)
5666 mac_get_window_bounds (f
, inner
, outer
)
5668 Rect
*inner
, *outer
;
5670 #if TARGET_API_MAC_CARBON
5671 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5672 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5673 #else /* not TARGET_API_MAC_CARBON */
5674 RgnHandle region
= NewRgn ();
5676 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5677 *inner
= (*region
)->rgnBBox
;
5678 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5679 *outer
= (*region
)->rgnBBox
;
5680 DisposeRgn (region
);
5681 #endif /* not TARGET_API_MAC_CARBON */
5686 /* Calculate the absolute position in frame F
5687 from its current recorded position values and gravity. */
5690 x_calc_absolute_position (f
)
5693 int width_diff
= 0, height_diff
= 0;
5694 int flags
= f
->size_hint_flags
;
5697 /* We have nothing to do if the current position
5698 is already for the top-left corner. */
5699 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5702 /* Find the offsets of the outside upper-left corner of
5703 the inner window, with respect to the outer window. */
5704 mac_get_window_bounds (f
, &inner
, &outer
);
5706 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5707 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5709 /* Treat negative positions as relative to the leftmost bottommost
5710 position that fits on the screen. */
5711 if (flags
& XNegative
)
5712 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5714 - FRAME_PIXEL_WIDTH (f
)
5717 if (flags
& YNegative
)
5718 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5720 - FRAME_PIXEL_HEIGHT (f
)
5723 /* The left_pos and top_pos
5724 are now relative to the top and left screen edges,
5725 so the flags should correspond. */
5726 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5729 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5730 to really change the position, and 0 when calling from
5731 x_make_frame_visible (in that case, XOFF and YOFF are the current
5732 position values). It is -1 when calling from x_set_frame_parameters,
5733 which means, do adjust for borders but don't change the gravity. */
5736 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5738 register int xoff
, yoff
;
5741 if (change_gravity
> 0)
5745 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5747 f
->size_hint_flags
|= XNegative
;
5749 f
->size_hint_flags
|= YNegative
;
5750 f
->win_gravity
= NorthWestGravity
;
5752 x_calc_absolute_position (f
);
5755 x_wm_set_size_hint (f
, (long) 0, 0);
5757 #if TARGET_API_MAC_CARBON
5758 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5759 /* If the title bar is completely outside the screen, adjust the
5761 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5762 kWindowConstrainMoveRegardlessOfFit
5763 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5764 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5767 Rect inner
, outer
, screen_rect
, dummy
;
5768 RgnHandle region
= NewRgn ();
5770 mac_get_window_bounds (f
, &inner
, &outer
);
5771 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5772 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5773 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5774 f
->top_pos
+ f
->y_pixels_diff
, false);
5776 /* If the title bar is completely outside the screen, adjust the
5777 position. The variable `outer' holds the title bar rectangle.
5778 The variable `inner' holds slightly smaller one than `outer',
5779 so that the calculation of overlapping may not become too
5781 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5782 outer
= (*region
)->rgnBBox
;
5783 DisposeRgn (region
);
5785 InsetRect (&inner
, 8, 8);
5786 screen_rect
= qd
.screenBits
.bounds
;
5787 screen_rect
.top
+= GetMBarHeight ();
5789 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5791 if (inner
.right
<= screen_rect
.left
)
5792 f
->left_pos
= screen_rect
.left
;
5793 else if (inner
.left
>= screen_rect
.right
)
5794 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5796 if (inner
.bottom
<= screen_rect
.top
)
5797 f
->top_pos
= screen_rect
.top
;
5798 else if (inner
.top
>= screen_rect
.bottom
)
5799 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5801 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5802 f
->top_pos
+ f
->y_pixels_diff
, false);
5810 /* Call this to change the size of frame F's x-window.
5811 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5812 for this size change and subsequent size changes.
5813 Otherwise we leave the window gravity unchanged. */
5816 x_set_window_size (f
, change_gravity
, cols
, rows
)
5821 int pixelwidth
, pixelheight
;
5825 check_frame_size (f
, &rows
, &cols
);
5826 f
->scroll_bar_actual_width
5827 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5829 compute_fringe_widths (f
, 0);
5831 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5832 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5834 f
->win_gravity
= NorthWestGravity
;
5835 x_wm_set_size_hint (f
, (long) 0, 0);
5837 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5838 #if TARGET_API_MAC_CARBON
5839 if (f
->output_data
.mac
->hourglass_control
)
5840 MoveControl (f
->output_data
.mac
->hourglass_control
,
5841 pixelwidth
- HOURGLASS_WIDTH
, 0);
5844 /* Now, strictly speaking, we can't be sure that this is accurate,
5845 but the window manager will get around to dealing with the size
5846 change request eventually, and we'll hear how it went when the
5847 ConfigureNotify event gets here.
5849 We could just not bother storing any of this information here,
5850 and let the ConfigureNotify event set everything up, but that
5851 might be kind of confusing to the Lisp code, since size changes
5852 wouldn't be reported in the frame parameters until some random
5853 point in the future when the ConfigureNotify event arrives.
5855 We pass 1 for DELAY since we can't run Lisp code inside of
5857 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5858 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5859 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5861 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5862 receive in the ConfigureNotify event; if we get what we asked
5863 for, then the event won't cause the screen to become garbaged, so
5864 we have to make sure to do it here. */
5865 SET_FRAME_GARBAGED (f
);
5867 XFlush (FRAME_X_DISPLAY (f
));
5869 /* If cursor was outside the new size, mark it as off. */
5870 mark_window_cursors_off (XWINDOW (f
->root_window
));
5872 /* Clear out any recollection of where the mouse highlighting was,
5873 since it might be in a place that's outside the new frame size.
5874 Actually checking whether it is outside is a pain in the neck,
5875 so don't try--just let the highlighting be done afresh with new size. */
5876 cancel_mouse_face (f
);
5881 /* Mouse warping. */
5883 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5886 x_set_mouse_position (f
, x
, y
)
5892 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5893 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5895 if (pix_x
< 0) pix_x
= 0;
5896 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5898 if (pix_y
< 0) pix_y
= 0;
5899 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5901 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5905 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5909 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5912 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5913 0, 0, 0, 0, pix_x
, pix_y
);
5918 /* focus shifting, raising and lowering. */
5921 x_focus_on_frame (f
)
5924 #if 0 /* This proves to be unpleasant. */
5928 /* I don't think that the ICCCM allows programs to do things like this
5929 without the interaction of the window manager. Whatever you end up
5930 doing with this code, do it to x_unfocus_frame too. */
5931 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5932 RevertToPointerRoot
, CurrentTime
);
5942 /* Raise frame F. */
5948 if (f
->async_visible
)
5951 SelectWindow (FRAME_MAC_WINDOW (f
));
5956 /* Lower frame F. */
5962 if (f
->async_visible
)
5965 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5971 XTframe_raise_lower (f
, raise_flag
)
5981 /* Change of visibility. */
5984 mac_handle_visibility_change (f
)
5987 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5988 int visible
= 0, iconified
= 0;
5989 struct input_event buf
;
5991 if (IsWindowVisible (wp
))
5992 if (IsWindowCollapsed (wp
))
5997 if (!f
->async_visible
&& visible
)
6001 /* wait_reading_process_output will notice this and update
6002 the frame's display structures. If we were made
6003 invisible, we should not set garbaged, because that stops
6004 redrawing on Update events. */
6005 SET_FRAME_GARBAGED (f
);
6008 buf
.kind
= DEICONIFY_EVENT
;
6009 XSETFRAME (buf
.frame_or_window
, f
);
6010 kbd_buffer_store_event (&buf
);
6012 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
6013 /* Force a redisplay sooner or later to update the
6014 frame titles in case this is the second frame. */
6015 record_asynch_buffer_change ();
6017 else if (f
->async_visible
&& !visible
)
6021 buf
.kind
= ICONIFY_EVENT
;
6022 XSETFRAME (buf
.frame_or_window
, f
);
6023 kbd_buffer_store_event (&buf
);
6026 f
->async_visible
= visible
;
6027 f
->async_iconified
= iconified
;
6030 /* This tries to wait until the frame is really visible.
6031 However, if the window manager asks the user where to position
6032 the frame, this will return before the user finishes doing that.
6033 The frame will not actually be visible at that time,
6034 but it will become visible later when the window manager
6035 finishes with it. */
6038 x_make_frame_visible (f
)
6042 int original_top
, original_left
;
6046 if (! FRAME_VISIBLE_P (f
))
6048 /* We test FRAME_GARBAGED_P here to make sure we don't
6049 call x_set_offset a second time
6050 if we get to x_make_frame_visible a second time
6051 before the window gets really visible. */
6052 if (! FRAME_ICONIFIED_P (f
)
6053 && ! f
->output_data
.mac
->asked_for_visible
)
6054 #if TARGET_API_MAC_CARBON
6055 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
6057 struct frame
*sf
= SELECTED_FRAME ();
6058 if (!FRAME_MAC_P (sf
))
6059 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
6060 kWindowCenterOnMainScreen
);
6062 RepositionWindow (FRAME_MAC_WINDOW (f
),
6063 FRAME_MAC_WINDOW (sf
),
6064 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
6065 kWindowCascadeStartAtParentWindowScreen
6067 kWindowCascadeOnParentWindowScreen
6070 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6074 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6076 f
->output_data
.mac
->asked_for_visible
= 1;
6078 SelectWindow (FRAME_MAC_WINDOW (f
));
6079 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6080 ShowWindow (FRAME_MAC_WINDOW (f
));
6083 XFlush (FRAME_MAC_DISPLAY (f
));
6085 /* Synchronize to ensure Emacs knows the frame is visible
6086 before we do anything else. We do this loop with input not blocked
6087 so that incoming events are handled. */
6092 /* This must come after we set COUNT. */
6095 XSETFRAME (frame
, f
);
6097 /* Wait until the frame is visible. Process X events until a
6098 MapNotify event has been seen, or until we think we won't get a
6099 MapNotify at all.. */
6100 for (count
= input_signal_count
+ 10;
6101 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6103 /* Force processing of queued events. */
6106 /* Machines that do polling rather than SIGIO have been
6107 observed to go into a busy-wait here. So we'll fake an
6108 alarm signal to let the handler know that there's something
6109 to be read. We used to raise a real alarm, but it seems
6110 that the handler isn't always enabled here. This is
6112 if (input_polling_used ())
6114 /* It could be confusing if a real alarm arrives while
6115 processing the fake one. Turn it off and let the
6116 handler reset it. */
6117 extern void poll_for_input_1
P_ ((void));
6118 int old_poll_suppress_count
= poll_suppress_count
;
6119 poll_suppress_count
= 1;
6120 poll_for_input_1 ();
6121 poll_suppress_count
= old_poll_suppress_count
;
6124 /* See if a MapNotify event has been processed. */
6125 FRAME_SAMPLE_VISIBILITY (f
);
6130 /* Change from mapped state to withdrawn state. */
6132 /* Make the frame visible (mapped and not iconified). */
6135 x_make_frame_invisible (f
)
6138 /* A deactivate event does not occur when the last visible frame is
6139 made invisible. So if we clear the highlight here, it will not
6140 be rehighlighted when it is made visible. */
6142 /* Don't keep the highlight on an invisible frame. */
6143 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6144 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6149 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6150 that the current position of the window is user-specified, rather than
6151 program-specified, so that when the window is mapped again, it will be
6152 placed at the same location, without forcing the user to position it
6153 by hand again (they have already done that once for this window.) */
6154 x_wm_set_size_hint (f
, (long) 0, 1);
6156 HideWindow (FRAME_MAC_WINDOW (f
));
6160 #if !USE_CARBON_EVENTS
6161 mac_handle_visibility_change (f
);
6165 /* Change window state from mapped to iconified. */
6173 /* A deactivate event does not occur when the last visible frame is
6174 iconified. So if we clear the highlight here, it will not be
6175 rehighlighted when it is deiconified. */
6177 /* Don't keep the highlight on an invisible frame. */
6178 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6179 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6182 if (f
->async_iconified
)
6187 FRAME_SAMPLE_VISIBILITY (f
);
6189 if (! FRAME_VISIBLE_P (f
))
6190 ShowWindow (FRAME_MAC_WINDOW (f
));
6192 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6197 error ("Can't notify window manager of iconification");
6199 #if !USE_CARBON_EVENTS
6200 mac_handle_visibility_change (f
);
6205 /* Free X resources of frame F. */
6208 x_free_frame_resources (f
)
6211 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6212 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6216 if (wp
!= tip_window
)
6217 remove_window_handler (wp
);
6220 if (wp
== tip_window
)
6221 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6222 closed' event. So we reset tip_window here. */
6225 free_frame_menubar (f
);
6227 if (FRAME_FACE_CACHE (f
))
6228 free_frame_faces (f
);
6232 if (FRAME_SIZE_HINTS (f
))
6233 xfree (FRAME_SIZE_HINTS (f
));
6235 xfree (f
->output_data
.mac
);
6236 f
->output_data
.mac
= NULL
;
6238 if (f
== dpyinfo
->x_focus_frame
)
6239 dpyinfo
->x_focus_frame
= 0;
6240 if (f
== dpyinfo
->x_focus_event_frame
)
6241 dpyinfo
->x_focus_event_frame
= 0;
6242 if (f
== dpyinfo
->x_highlight_frame
)
6243 dpyinfo
->x_highlight_frame
= 0;
6245 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6247 dpyinfo
->mouse_face_beg_row
6248 = dpyinfo
->mouse_face_beg_col
= -1;
6249 dpyinfo
->mouse_face_end_row
6250 = dpyinfo
->mouse_face_end_col
= -1;
6251 dpyinfo
->mouse_face_window
= Qnil
;
6252 dpyinfo
->mouse_face_deferred_gc
= 0;
6253 dpyinfo
->mouse_face_mouse_frame
= 0;
6260 /* Destroy the X window of frame F. */
6263 x_destroy_window (f
)
6266 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6268 x_free_frame_resources (f
);
6270 dpyinfo
->reference_count
--;
6274 /* Setting window manager hints. */
6276 /* Set the normal size hints for the window manager, for frame F.
6277 FLAGS is the flags word to use--or 0 meaning preserve the flags
6278 that the window now has.
6279 If USER_POSITION is nonzero, we set the USPosition
6280 flag (this is useful when FLAGS is 0). */
6282 x_wm_set_size_hint (f
, flags
, user_position
)
6287 int base_width
, base_height
, width_inc
, height_inc
;
6288 int min_rows
= 0, min_cols
= 0;
6289 XSizeHints
*size_hints
;
6291 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6292 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6293 width_inc
= FRAME_COLUMN_WIDTH (f
);
6294 height_inc
= FRAME_LINE_HEIGHT (f
);
6296 check_frame_size (f
, &min_rows
, &min_cols
);
6298 size_hints
= FRAME_SIZE_HINTS (f
);
6299 if (size_hints
== NULL
)
6301 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6302 bzero (size_hints
, sizeof (XSizeHints
));
6305 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6306 size_hints
->width_inc
= width_inc
;
6307 size_hints
->height_inc
= height_inc
;
6308 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6309 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6310 size_hints
->base_width
= base_width
;
6311 size_hints
->base_height
= base_height
;
6314 size_hints
->flags
= flags
;
6315 else if (user_position
)
6317 size_hints
->flags
&= ~ PPosition
;
6318 size_hints
->flags
|= USPosition
;
6322 #if 0 /* MAC_TODO: hide application instead of iconify? */
6323 /* Used for IconicState or NormalState */
6326 x_wm_set_window_state (f
, state
)
6330 #ifdef USE_X_TOOLKIT
6333 XtSetArg (al
[0], XtNinitialState
, state
);
6334 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6335 #else /* not USE_X_TOOLKIT */
6336 Window window
= FRAME_X_WINDOW (f
);
6338 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6339 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6341 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6342 #endif /* not USE_X_TOOLKIT */
6346 x_wm_set_icon_pixmap (f
, pixmap_id
)
6352 #ifndef USE_X_TOOLKIT
6353 Window window
= FRAME_X_WINDOW (f
);
6358 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6359 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6363 /* It seems there is no way to turn off use of an icon pixmap.
6364 The following line does it, only if no icon has yet been created,
6365 for some window managers. But with mwm it crashes.
6366 Some people say it should clear the IconPixmapHint bit in this case,
6367 but that doesn't work, and the X consortium said it isn't the
6368 right thing at all. Since there is no way to win,
6369 best to explicitly give up. */
6371 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6377 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6381 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6382 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6385 #else /* not USE_X_TOOLKIT */
6387 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6388 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6390 #endif /* not USE_X_TOOLKIT */
6393 #endif /* MAC_TODO */
6396 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6400 #if 0 /* MAC_TODO: no icons on Mac */
6401 #ifdef USE_X_TOOLKIT
6402 Window window
= XtWindow (f
->output_data
.x
->widget
);
6404 Window window
= FRAME_X_WINDOW (f
);
6407 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6408 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6409 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6411 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6412 #endif /* MAC_TODO */
6416 /***********************************************************************
6418 ***********************************************************************/
6420 /* An XLFD pattern is divided into blocks delimited by '*'. This
6421 structure holds information for each block. */
6422 struct xlfdpat_block
6424 /* Length of the pattern string in this block. Non-zero except for
6425 the first and the last blocks. */
6428 /* Pattern string except the last character in this block. The last
6429 character is replaced with NUL in order to use it as a
6431 unsigned char *pattern
;
6433 /* Last character of the pattern string. Must not be '?'. */
6434 unsigned char last_char
;
6436 /* One of the tables for the Boyer-Moore string search. It
6437 specifies the number of positions to proceed for each character
6438 with which the match fails. */
6441 /* The skip value for the last character in the above `skip' is
6442 assigned to `infinity' in order to simplify a loop condition.
6443 The original value is saved here. */
6449 /* Normalized pattern string. "Normalized" means that capital
6450 letters are lowered, blocks are not empty except the first and
6451 the last ones, and trailing '?'s in a block that is not the last
6452 one are moved to the next one. The last character in each block
6453 is replaced with NUL. */
6456 /* Number of characters except '*'s and trailing '?'s in the
6457 normalized pattern string. */
6460 /* Number of trailing '?'s in the normalized pattern string. */
6461 int trailing_anychars
;
6463 /* Number of blocks and information for each block. The latter is
6464 NULL if the pattern is exact (no '*' or '?' in it). */
6466 struct xlfdpat_block
*blocks
;
6470 xlfdpat_destroy (pat
)
6471 struct xlfdpat
*pat
;
6478 xfree (pat
->blocks
);
6485 static struct xlfdpat
*
6486 xlfdpat_create (pattern
)
6489 struct xlfdpat
*pat
;
6490 int nblocks
, i
, skip
;
6491 unsigned char last_char
, *p
, *q
, *anychar_head
;
6492 struct xlfdpat_block
*blk
;
6494 pat
= xmalloc (sizeof (struct xlfdpat
));
6498 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6499 if (pat
->buf
== NULL
)
6502 /* Normalize the pattern string and store it to `pat->buf'. */
6504 anychar_head
= NULL
;
6507 for (p
= pattern
; *p
; p
++)
6509 unsigned char c
= *p
;
6512 if (last_char
== '*')
6513 /* ...a** -> ...a* */
6517 if (last_char
== '?')
6518 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6519 /* ...*??* -> ...*?? */
6522 /* ...a??* -> ...a*?? */
6524 *anychar_head
++ = '*';
6531 if (last_char
!= '?')
6535 /* On Mac OS X 10.3, tolower also converts non-ASCII
6536 characters for some locales. */
6540 *q
++ = last_char
= c
;
6544 pat
->nblocks
= nblocks
;
6545 if (last_char
!= '?')
6546 pat
->trailing_anychars
= 0;
6549 pat
->trailing_anychars
= q
- anychar_head
;
6552 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6554 if (anychar_head
== NULL
&& nblocks
== 1)
6556 /* The pattern is exact. */
6561 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6562 if (pat
->blocks
== NULL
)
6565 /* Divide the normalized pattern into blocks. */
6567 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6572 blk
->len
= p
- blk
->pattern
;
6576 blk
->len
= q
- blk
->pattern
;
6578 /* Setup a table for the Boyer-Moore string search. */
6579 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6582 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6583 blk
->pattern
[blk
->len
- 1] = '\0';
6585 for (skip
= 1; skip
< blk
->len
; skip
++)
6586 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6589 for (i
= 0; i
< 256; i
++)
6590 blk
->skip
[i
] = skip
;
6592 p
= blk
->pattern
+ (blk
->len
- skip
);
6594 blk
->skip
[*p
++] = skip
;
6596 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6602 xlfdpat_destroy (pat
);
6607 xlfdpat_exact_p (pat
)
6608 struct xlfdpat
*pat
;
6610 return pat
->blocks
== NULL
;
6613 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6614 that the pattern in *BLK matches with its prefix. Return NULL
6615 there is no such strings. STRING must be lowered in advance. */
6618 xlfdpat_block_match_1 (blk
, string
, start_max
)
6619 struct xlfdpat_block
*blk
;
6620 unsigned char *string
;
6623 int start
, infinity
;
6624 unsigned char *p
, *s
;
6626 xassert (blk
->len
> 0);
6627 xassert (start_max
+ blk
->len
<= strlen (string
));
6628 xassert (blk
->last_char
!= '?');
6630 /* See the comments in the function `boyer_moore' (search.c) for the
6631 use of `infinity'. */
6632 infinity
= start_max
+ blk
->len
+ 1;
6633 blk
->skip
[blk
->last_char
] = infinity
;
6638 /* Check the last character of the pattern. */
6639 s
= string
+ blk
->len
- 1;
6642 start
+= blk
->skip
[*(s
+ start
)];
6644 while (start
<= start_max
);
6646 if (start
< infinity
)
6647 /* Couldn't find the last character. */
6650 /* No less than `infinity' means we could find the last
6651 character at `s[start - infinity]'. */
6654 /* Check the remaining characters. We prefer making no-'?'
6655 cases faster because the use of '?' is really rare. */
6660 while (*p
++ == *s
++)
6663 while (*(p
- 1) == '?');
6665 if (*(p
- 1) == '\0')
6667 return string
+ start
;
6670 start
+= blk
->last_char_skip
;
6672 while (start
<= start_max
);
6677 #define xlfdpat_block_match(b, s, m) \
6678 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6679 : xlfdpat_block_match_1 (b, s, m))
6681 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6682 matches with STRING. STRING must be lowered in advance. */
6685 xlfdpat_match (pat
, string
)
6686 struct xlfdpat
*pat
;
6687 unsigned char *string
;
6689 int str_len
, nblocks
, i
, start_max
;
6690 struct xlfdpat_block
*blk
;
6693 xassert (pat
->nblocks
> 0);
6695 if (xlfdpat_exact_p (pat
))
6696 return strcmp (pat
->buf
, string
) == 0;
6698 /* The number of the characters in the string must not be smaller
6699 than that in the pattern. */
6700 str_len
= strlen (string
);
6701 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6704 /* Chop off the trailing '?'s. */
6705 str_len
-= pat
->trailing_anychars
;
6707 /* The last block. When it is non-empty, it must match at the end
6709 nblocks
= pat
->nblocks
;
6710 blk
= pat
->blocks
+ (nblocks
- 1);
6712 /* The last block is also the first one. */
6713 return (str_len
== blk
->len
6714 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6715 else if (blk
->len
!= 0)
6716 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6719 /* The first block. When it is non-empty, it must match at the
6720 beginning of the string. */
6724 s
= xlfdpat_block_match (blk
, string
, 0);
6727 string
= s
+ blk
->len
;
6730 /* The rest of the blocks. */
6731 start_max
= str_len
- pat
->nchars
;
6732 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6734 s
= xlfdpat_block_match (blk
, string
, start_max
);
6737 start_max
-= s
- string
;
6738 string
= s
+ blk
->len
;
6745 /***********************************************************************
6747 ***********************************************************************/
6749 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6752 x_get_font_info (f
, font_idx
)
6756 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6759 /* the global font name table */
6760 static char **font_name_table
= NULL
;
6761 static int font_name_table_size
= 0;
6762 static int font_name_count
= 0;
6765 static Lisp_Object atsu_font_id_hash
;
6768 /* Alist linking character set strings to Mac text encoding and Emacs
6770 static Lisp_Object Vmac_charset_info_alist
;
6773 create_text_encoding_info_alist ()
6775 Lisp_Object result
= Qnil
, rest
;
6777 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6779 Lisp_Object charset_info
= XCAR (rest
);
6780 Lisp_Object charset
, coding_system
, text_encoding
;
6781 Lisp_Object existing_info
;
6783 if (!(CONSP (charset_info
)
6784 && STRINGP (charset
= XCAR (charset_info
))
6785 && CONSP (XCDR (charset_info
))
6786 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6787 && CONSP (XCDR (XCDR (charset_info
)))
6788 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6791 existing_info
= assq_no_quit (text_encoding
, result
);
6792 if (NILP (existing_info
))
6793 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6796 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6797 XSETCDR (XCDR (existing_info
),
6798 Fcons (charset
, XCDR (XCDR (existing_info
))));
6806 decode_mac_font_name (name
, size
, coding_system
)
6809 Lisp_Object coding_system
;
6811 struct coding_system coding
;
6814 for (p
= name
; *p
; p
++)
6815 if (!isascii (*p
) || iscntrl (*p
))
6819 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6822 setup_coding_system (coding_system
, &coding
);
6823 coding
.src_multibyte
= 0;
6824 coding
.dst_multibyte
= 1;
6825 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6826 coding
.composing
= COMPOSITION_DISABLED
;
6827 buf
= (char *) alloca (size
);
6829 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6830 bcopy (buf
, name
, coding
.produced
);
6831 name
[coding
.produced
] = '\0';
6836 mac_to_x_fontname (name
, size
, style
, charset
)
6844 char xf
[256], *result
;
6847 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6851 strcpy(foundry
, "Apple");
6852 strcpy(family
, name
);
6855 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6856 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6857 size
, size
* 10, size
? 75 : 0, size
? 75 : 0, size
* 10, charset
);
6859 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6860 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6861 for (p
= result
; *p
; p
++)
6862 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6863 for some locales. */
6870 /* Convert an X font spec to the corresponding mac font name, which
6871 can then be passed to GetFNum after conversion to a Pascal string.
6872 For ordinary Mac fonts, this should just be their names, like
6873 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6874 collection contain their charset designation in their names, like
6875 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6876 names are handled accordingly. */
6878 x_font_name_to_mac_font_name (xf
, mf
, mf_decoded
, style
, cs
)
6879 char *xf
, *mf
, *mf_decoded
;
6885 char weight
[20], slant
[2], *p
;
6886 Lisp_Object charset_info
, coding_system
= Qnil
;
6887 struct coding_system coding
;
6891 if (sscanf (xf
, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6892 foundry
, family
, weight
, slant
, cs
) != 5 &&
6893 sscanf (xf
, "-%31[^-]-%255[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6894 foundry
, family
, weight
, slant
, cs
) != 5)
6898 if (strcmp (weight
, "bold") == 0)
6903 charset_info
= Fassoc (build_string (cs
), Vmac_charset_info_alist
);
6904 if (!NILP (charset_info
))
6906 strcpy (mf_decoded
, family
);
6907 coding_system
= Fcar (Fcdr (Fcdr (charset_info
)));
6910 sprintf (mf_decoded
, "%s-%s-%s", foundry
, family
, cs
);
6912 for (p
= mf_decoded
; *p
; p
++)
6913 if (!isascii (*p
) || iscntrl (*p
))
6917 || NILP (coding_system
) || NILP (Fcoding_system_p (coding_system
)))
6918 strcpy (mf
, mf_decoded
);
6921 setup_coding_system (coding_system
, &coding
);
6922 coding
.src_multibyte
= 1;
6923 coding
.dst_multibyte
= 0;
6924 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6925 encode_coding (&coding
, mf_decoded
, mf
,
6926 strlen (mf_decoded
), sizeof (Str255
) - 1);
6927 mf
[coding
.produced
] = '\0';
6933 add_font_name_table_entry (char *font_name
)
6935 if (font_name_table_size
== 0)
6937 font_name_table_size
= 256;
6938 font_name_table
= (char **)
6939 xmalloc (font_name_table_size
* sizeof (char *));
6941 else if (font_name_count
+ 1 >= font_name_table_size
)
6943 font_name_table_size
*= 2;
6944 font_name_table
= (char **)
6945 xrealloc (font_name_table
,
6946 font_name_table_size
* sizeof (char *));
6949 font_name_table
[font_name_count
++] = font_name
;
6952 /* Sets up the table font_name_table to contain the list of all fonts
6953 in the system the first time the table is used so that the Resource
6954 Manager need not be accessed every time this information is
6958 init_font_name_table ()
6960 #if TARGET_API_MAC_CARBON
6961 FMFontFamilyIterator ffi
;
6962 FMFontFamilyInstanceIterator ffii
;
6964 Lisp_Object text_encoding_info_alist
;
6965 struct gcpro gcpro1
;
6967 text_encoding_info_alist
= create_text_encoding_info_alist ();
6970 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6971 text_encoding_info_alist
)))
6974 ItemCount nfonts
, i
;
6975 ATSUFontID
*font_ids
= NULL
;
6976 Ptr name
, prev_name
= NULL
;
6980 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6981 make_float (DEFAULT_REHASH_SIZE
),
6982 make_float (DEFAULT_REHASH_THRESHOLD
),
6984 err
= ATSUFontCount (&nfonts
);
6986 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6988 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6990 for (i
= 0; i
< nfonts
; i
++)
6992 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6993 kFontMacintoshPlatform
, kFontNoScript
,
6994 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6997 name
= xmalloc (name_len
+ 1);
7000 name
[name_len
] = '\0';
7001 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
7002 kFontMacintoshPlatform
, kFontNoScript
,
7003 kFontNoLanguage
, name_len
, name
,
7007 && (prev_name
== NULL
7008 || strcmp (name
, prev_name
) != 0))
7010 static char *cs
= "iso10646-1";
7012 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7014 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7016 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7018 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
7019 italic
| bold
, cs
));
7020 Fputhash (Fdowncase (make_unibyte_string (name
, name_len
)),
7021 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
7035 /* Create a dummy instance iterator here to avoid creating and
7036 destroying it in the loop. */
7037 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7039 /* Create an iterator to enumerate the font families. */
7040 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7043 FMDisposeFontFamilyInstanceIterator (&ffii
);
7047 GCPRO1 (text_encoding_info_alist
);
7049 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7055 TextEncoding encoding
;
7056 TextEncodingBase sc
;
7057 Lisp_Object text_encoding_info
;
7059 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7065 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7067 sc
= GetTextEncodingBase (encoding
);
7068 text_encoding_info
= assq_no_quit (make_number (sc
),
7069 text_encoding_info_alist
);
7070 if (!NILP (text_encoding_info
))
7071 decode_mac_font_name (name
, sizeof (name
),
7072 XCAR (XCDR (text_encoding_info
)));
7074 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7075 text_encoding_info_alist
);
7077 /* Point the instance iterator at the current font family. */
7078 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7081 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7084 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7086 if (size
> 0 || style
== normal
)
7087 for (; !NILP (rest
); rest
= XCDR (rest
))
7089 char *cs
= SDATA (XCAR (rest
));
7093 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7095 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7097 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7099 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7105 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7114 /* Dispose of the iterators. */
7115 FMDisposeFontFamilyIterator (&ffi
);
7116 FMDisposeFontFamilyInstanceIterator (&ffii
);
7117 #else /* !TARGET_API_MAC_CARBON */
7119 SInt16 fontnum
, old_fontnum
;
7120 int num_mac_fonts
= CountResources('FOND');
7122 Handle font_handle
, font_handle_2
;
7123 short id
, scriptcode
;
7126 struct FontAssoc
*fat
;
7127 struct AsscEntry
*assc_entry
;
7128 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7129 struct gcpro gcpro1
;
7131 GetPort (&port
); /* save the current font number used */
7132 old_fontnum
= port
->txFont
;
7134 text_encoding_info_alist
= create_text_encoding_info_alist ();
7136 GCPRO1 (text_encoding_info_alist
);
7138 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7140 font_handle
= GetIndResource ('FOND', i
);
7144 GetResInfo (font_handle
, &id
, &type
, name
);
7145 GetFNum (name
, &fontnum
);
7151 scriptcode
= FontToScript (fontnum
);
7152 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7153 text_encoding_info_alist
);
7154 if (!NILP (text_encoding_info
))
7155 decode_mac_font_name (name
, sizeof (name
),
7156 XCAR (XCDR (text_encoding_info
)));
7158 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7159 text_encoding_info_alist
);
7162 HLock (font_handle
);
7164 if (GetResourceSizeOnDisk (font_handle
)
7165 >= sizeof (struct FamRec
))
7167 fat
= (struct FontAssoc
*) (*font_handle
7168 + sizeof (struct FamRec
));
7170 = (struct AsscEntry
*) (*font_handle
7171 + sizeof (struct FamRec
)
7172 + sizeof (struct FontAssoc
));
7174 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7176 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7178 for (; !NILP (rest
); rest
= XCDR (rest
))
7180 char *cs
= SDATA (XCAR (rest
));
7182 add_font_name_table_entry (mac_to_x_fontname (name
,
7183 assc_entry
->fontSize
,
7184 assc_entry
->fontStyle
,
7190 HUnlock (font_handle
);
7191 font_handle_2
= GetNextFOND (font_handle
);
7192 ReleaseResource (font_handle
);
7193 font_handle
= font_handle_2
;
7195 while (ResError () == noErr
&& font_handle
);
7200 TextFont (old_fontnum
);
7201 #endif /* !TARGET_API_MAC_CARBON */
7206 mac_clear_font_name_table ()
7210 for (i
= 0; i
< font_name_count
; i
++)
7211 xfree (font_name_table
[i
]);
7212 xfree (font_name_table
);
7213 font_name_table
= NULL
;
7214 font_name_table_size
= font_name_count
= 0;
7218 enum xlfd_scalable_field_index
7220 XLFD_SCL_PIXEL_SIZE
,
7221 XLFD_SCL_POINT_SIZE
,
7226 static int xlfd_scalable_fields
[] =
7235 mac_do_list_fonts (pattern
, maxnames
)
7240 Lisp_Object font_list
= Qnil
;
7241 struct xlfdpat
*pat
;
7243 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7246 if (font_name_table
== NULL
) /* Initialize when first used. */
7247 init_font_name_table ();
7249 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7252 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7253 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7254 fonts are scaled according to the specified size. */
7257 field
= xlfd_scalable_fields
;
7265 if ('0' <= *ptr
&& *ptr
<= '9')
7267 *val
= *ptr
++ - '0';
7268 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7269 *val
= *val
* 10 + *ptr
++ - '0';
7276 ptr
= strchr (ptr
, '-');
7279 while (ptr
&& i
< 14);
7281 if (i
== 14 && ptr
== NULL
)
7283 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7284 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7285 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7286 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7288 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7289 scl_val
[XLFD_SCL_POINT_SIZE
] =
7290 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7291 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7293 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7294 scl_val
[XLFD_SCL_AVGWIDTH
] =
7295 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7296 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7300 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7302 pat
= xlfdpat_create (pattern
);
7306 exact
= xlfdpat_exact_p (pat
);
7308 for (i
= 0; i
< font_name_count
; i
++)
7310 if (xlfdpat_match (pat
, font_name_table
[i
]))
7312 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7313 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7316 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7317 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7319 int former_len
= ptr
- font_name_table
[i
];
7321 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7324 memcpy (scaled
, font_name_table
[i
], former_len
);
7325 sprintf (scaled
+ former_len
,
7326 "-%d-%d-75-75-m-%d-%s",
7327 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7328 scl_val
[XLFD_SCL_POINT_SIZE
],
7329 scl_val
[XLFD_SCL_AVGWIDTH
],
7330 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7332 if (xlfdpat_match (pat
, scaled
))
7334 font_list
= Fcons (build_string (scaled
), font_list
);
7336 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7344 xlfdpat_destroy (pat
);
7349 /* Return a list of names of available fonts matching PATTERN on frame F.
7351 Frame F null means we have not yet created any frame on Mac, and
7352 consult the first display in x_display_list. MAXNAMES sets a limit
7353 on how many fonts to match. */
7356 x_list_fonts (f
, pattern
, size
, maxnames
)
7358 Lisp_Object pattern
;
7361 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7362 struct mac_display_info
*dpyinfo
7363 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7365 xassert (size
<= 0);
7367 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7368 if (NILP (patterns
))
7369 patterns
= Fcons (pattern
, Qnil
);
7371 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7373 pattern
= XCAR (patterns
);
7375 if (!STRINGP (pattern
))
7378 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7379 key
= Fcons (pattern
, make_number (maxnames
));
7381 list
= Fassoc (key
, tem
);
7384 list
= Fcdr_safe (list
);
7385 /* We have a cashed list. Don't have to get the list again. */
7390 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7393 /* MAC_TODO: add code for matching outline fonts here */
7395 /* Now store the result in the cache. */
7396 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7397 Fcons (Fcons (key
, list
),
7398 XCAR (XCDR (dpyinfo
->name_list_element
))));
7401 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7410 /* Check that FONT is valid on frame F. It is if it can be found in F's
7414 x_check_font (f
, font
)
7419 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7421 xassert (font
!= NULL
);
7423 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7424 if (dpyinfo
->font_table
[i
].name
7425 && font
== dpyinfo
->font_table
[i
].font
)
7428 xassert (i
< dpyinfo
->n_fonts
);
7431 #endif /* GLYPH_DEBUG != 0 */
7433 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7434 Note: There are (broken) X fonts out there with invalid XFontStruct
7435 min_bounds contents. For example, handa@etl.go.jp reports that
7436 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7437 have font->min_bounds.width == 0. */
7440 x_font_min_bounds (font
, w
, h
)
7441 MacFontStruct
*font
;
7444 *h
= FONT_HEIGHT (font
);
7445 *w
= font
->min_bounds
.width
;
7449 /* Compute the smallest character width and smallest font height over
7450 all fonts available on frame F. Set the members smallest_char_width
7451 and smallest_font_height in F's x_display_info structure to
7452 the values computed. Value is non-zero if smallest_font_height or
7453 smallest_char_width become smaller than they were before. */
7456 x_compute_min_glyph_bounds (f
)
7460 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7461 MacFontStruct
*font
;
7462 int old_width
= dpyinfo
->smallest_char_width
;
7463 int old_height
= dpyinfo
->smallest_font_height
;
7465 dpyinfo
->smallest_font_height
= 100000;
7466 dpyinfo
->smallest_char_width
= 100000;
7468 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7469 if (dpyinfo
->font_table
[i
].name
)
7471 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7474 font
= (MacFontStruct
*) fontp
->font
;
7475 xassert (font
!= (MacFontStruct
*) ~0);
7476 x_font_min_bounds (font
, &w
, &h
);
7478 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7479 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7482 xassert (dpyinfo
->smallest_char_width
> 0
7483 && dpyinfo
->smallest_font_height
> 0);
7485 return (dpyinfo
->n_fonts
== 1
7486 || dpyinfo
->smallest_char_width
< old_width
7487 || dpyinfo
->smallest_font_height
< old_height
);
7491 /* Determine whether given string is a fully-specified XLFD: all 14
7492 fields are present, none is '*'. */
7495 is_fully_specified_xlfd (char *p
)
7503 for (i
= 0; i
< 13; i
++)
7505 q
= strchr (p
+ 1, '-');
7508 if (q
- p
== 2 && *(p
+ 1) == '*')
7513 if (strchr (p
+ 1, '-') != NULL
)
7516 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7523 const int kDefaultFontSize
= 12;
7526 /* XLoadQueryFont creates and returns an internal representation for a
7527 font in a MacFontStruct struct. There is really no concept
7528 corresponding to "loading" a font on the Mac. But we check its
7529 existence and find the font number and all other information for it
7530 and store them in the returned MacFontStruct. */
7532 static MacFontStruct
*
7533 XLoadQueryFont (Display
*dpy
, char *fontname
)
7535 int i
, size
, point_size
, avgwidth
, is_two_byte_font
, char_width
;
7538 SInt16 old_fontnum
, old_fontsize
;
7540 Str255 mfontname
, mfontname_decoded
;
7544 ATSUStyle mac_style
= NULL
;
7547 #if TARGET_API_MAC_CARBON
7548 TextEncoding encoding
;
7553 MacFontStruct
*font
;
7554 FontInfo the_fontinfo
;
7556 UInt32 old_flags
, new_flags
;
7559 if (is_fully_specified_xlfd (fontname
))
7563 Lisp_Object matched_fonts
;
7565 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7566 if (NILP (matched_fonts
))
7568 name
= SDATA (XCAR (matched_fonts
));
7571 GetPort (&port
); /* save the current font number used */
7572 #if TARGET_API_MAC_CARBON
7573 old_fontnum
= GetPortTextFont (port
);
7574 old_fontsize
= GetPortTextSize (port
);
7575 old_fontface
= GetPortTextFace (port
);
7577 old_fontnum
= port
->txFont
;
7578 old_fontsize
= port
->txSize
;
7579 old_fontface
= port
->txFace
;
7582 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%*s", &size
, &point_size
, &avgwidth
) != 3)
7588 size
= point_size
/ 10;
7589 else if (avgwidth
> 0)
7590 size
= avgwidth
/ 10;
7593 size
= kDefaultFontSize
;
7595 x_font_name_to_mac_font_name (name
, mfontname
, mfontname_decoded
,
7596 &fontface
, charset
);
7598 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7601 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7602 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7603 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7604 sizeof (Boolean
), sizeof (Boolean
)};
7605 static ATSUFontID font_id
;
7606 static Fixed size_fixed
;
7607 static Boolean bold_p
, italic_p
;
7608 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7609 &bold_p
, &italic_p
};
7610 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
};
7611 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
};
7612 Lisp_Object font_id_cons
;
7614 font_id_cons
= Fgethash (Fdowncase
7615 (make_unibyte_string (mfontname
,
7616 strlen (mfontname
))),
7617 atsu_font_id_hash
, Qnil
);
7618 if (NILP (font_id_cons
))
7620 font_id
= cons_to_long (font_id_cons
);
7621 size_fixed
= Long2Fix (size
);
7622 bold_p
= (fontface
& bold
) != 0;
7623 italic_p
= (fontface
& italic
) != 0;
7624 err
= ATSUCreateStyle (&mac_style
);
7627 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7631 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7632 tags
, sizes
, values
);
7634 scriptcode
= kTextEncodingMacUnicode
;
7640 #if TARGET_API_MAC_CARBON
7641 fontnum
= FMGetFontFamilyFromName (mfontname
);
7642 if (fontnum
== kInvalidFontFamily
7643 || FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7645 scriptcode
= GetTextEncodingBase (encoding
);
7647 GetFNum (mfontname
, &fontnum
);
7650 scriptcode
= FontToScript (fontnum
);
7656 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7658 font
->mac_fontnum
= fontnum
;
7659 font
->mac_fontsize
= size
;
7660 font
->mac_fontface
= fontface
;
7661 font
->mac_scriptcode
= scriptcode
;
7663 font
->mac_style
= mac_style
;
7666 /* Apple Japanese (SJIS) font is listed as both
7667 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7668 (Roman script) in init_font_name_table (). The latter should be
7669 treated as a one-byte font. */
7670 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7671 font
->mac_scriptcode
= smRoman
;
7673 font
->full_name
= mac_to_x_fontname (mfontname_decoded
, size
, fontface
, charset
);
7676 if (font
->mac_style
)
7679 ATSUTextLayout text_layout
;
7681 Rect char_bounds
, min_bounds
, max_bounds
;
7682 int min_width
, max_width
;
7683 ATSTrapezoid glyph_bounds
;
7685 font
->per_char
= xmalloc (sizeof (XCharStruct
) * 0x10000);
7686 if (font
->per_char
== NULL
)
7688 mac_unload_font (&one_mac_display_info
, font
);
7691 bzero (font
->per_char
, sizeof (XCharStruct
) * 0x10000);
7693 err
= atsu_get_text_layout_with_text_ptr (&c
, 1,
7698 mac_unload_font (&one_mac_display_info
, font
);
7702 for (c
= 0x20; c
<= 0x7e; c
++)
7704 err
= ATSUClearLayoutCache (text_layout
, kATSUFromTextBeginning
);
7706 err
= ATSUMeasureTextImage (text_layout
,
7707 kATSUFromTextBeginning
, kATSUToTextEnd
,
7708 0, 0, &char_bounds
);
7710 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
7711 kATSUFromTextBeginning
, kATSUToTextEnd
,
7712 kATSUseFractionalOrigins
, 1,
7713 &glyph_bounds
, NULL
);
7716 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
7717 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
7719 char_width
= Fix2Long (glyph_bounds
.upperRight
.x
7720 - glyph_bounds
.upperLeft
.x
);
7721 STORE_XCHARSTRUCT (font
->per_char
[c
],
7722 char_width
, char_bounds
);
7725 min_width
= max_width
= char_width
;
7726 min_bounds
= max_bounds
= char_bounds
;
7727 font
->ascent
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
7728 font
->descent
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
7734 min_width
= min (min_width
, char_width
);
7735 max_width
= max (max_width
, char_width
);
7737 if (!EmptyRect (&char_bounds
))
7739 SetRect (&min_bounds
,
7740 max (min_bounds
.left
, char_bounds
.left
),
7741 max (min_bounds
.top
, char_bounds
.top
),
7742 min (min_bounds
.right
, char_bounds
.right
),
7743 min (min_bounds
.bottom
, char_bounds
.bottom
));
7744 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7749 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7750 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7752 font
->min_byte1
= 0;
7753 font
->max_byte1
= 0xff;
7754 font
->min_char_or_byte2
= 0;
7755 font
->max_char_or_byte2
= 0xff;
7760 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
7761 font
->mac_scriptcode
== smTradChinese
||
7762 font
->mac_scriptcode
== smSimpChinese
||
7763 font
->mac_scriptcode
== smKorean
;
7767 TextFace (fontface
);
7769 GetFontInfo (&the_fontinfo
);
7771 font
->ascent
= the_fontinfo
.ascent
;
7772 font
->descent
= the_fontinfo
.descent
;
7774 if (is_two_byte_font
)
7776 font
->min_byte1
= 0xa1;
7777 font
->max_byte1
= 0xfe;
7778 font
->min_char_or_byte2
= 0xa1;
7779 font
->max_char_or_byte2
= 0xfe;
7781 /* Use the width of an "ideographic space" of that font because
7782 the_fontinfo.widMax returns the wrong width for some fonts. */
7783 switch (font
->mac_scriptcode
)
7786 font
->min_byte1
= 0x81;
7787 font
->max_byte1
= 0xfc;
7788 font
->min_char_or_byte2
= 0x40;
7789 font
->max_char_or_byte2
= 0xfc;
7790 char_width
= StringWidth("\p\x81\x40");
7793 font
->min_char_or_byte2
= 0x40;
7794 char_width
= StringWidth("\p\xa1\x40");
7797 char_width
= StringWidth("\p\xa1\xa1");
7800 char_width
= StringWidth("\p\xa1\xa1");
7806 font
->min_byte1
= font
->max_byte1
= 0;
7807 font
->min_char_or_byte2
= 0x20;
7808 font
->max_char_or_byte2
= 0xff;
7810 /* Do this instead of use the_fontinfo.widMax, which incorrectly
7811 returns 15 for 12-point Monaco! */
7812 char_width
= CharWidth ('m');
7815 if (is_two_byte_font
)
7817 font
->per_char
= NULL
;
7819 if (fontface
& italic
)
7820 font
->max_bounds
.rbearing
= char_width
+ 1;
7822 font
->max_bounds
.rbearing
= char_width
;
7823 font
->max_bounds
.lbearing
= 0;
7824 font
->max_bounds
.width
= char_width
;
7825 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7826 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7828 font
->min_bounds
= font
->max_bounds
;
7832 int c
, min_width
, max_width
;
7833 Rect char_bounds
, min_bounds
, max_bounds
;
7836 font
->per_char
= xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7838 min_width
= max_width
= char_width
;
7839 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7840 SetRect (&max_bounds
, 0, 0, 0, 0);
7841 for (c
= 0x20; c
<= 0xff; c
++)
7844 char_width
= CharWidth (ch
);
7845 QDTextBounds (1, &ch
, &char_bounds
);
7846 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7847 char_width
, char_bounds
);
7848 /* Some Japanese fonts (in SJIS encoding) return 0 as the
7849 character width of 0x7f. */
7852 min_width
= min (min_width
, char_width
);
7853 max_width
= max (max_width
, char_width
);
7855 if (!EmptyRect (&char_bounds
))
7857 SetRect (&min_bounds
,
7858 max (min_bounds
.left
, char_bounds
.left
),
7859 max (min_bounds
.top
, char_bounds
.top
),
7860 min (min_bounds
.right
, char_bounds
.right
),
7861 min (min_bounds
.bottom
, char_bounds
.bottom
));
7862 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7865 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7866 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7867 if (min_width
== max_width
7868 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7870 /* Fixed width and no overhangs. */
7871 xfree (font
->per_char
);
7872 font
->per_char
= NULL
;
7876 TextFont (old_fontnum
); /* restore previous font number, size and face */
7877 TextSize (old_fontsize
);
7878 TextFace (old_fontface
);
7888 mac_unload_font (dpyinfo
, font
)
7889 struct mac_display_info
*dpyinfo
;
7892 xfree (font
->full_name
);
7894 xfree (font
->per_char
);
7896 if (font
->mac_style
)
7897 ATSUDisposeStyle (font
->mac_style
);
7903 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7904 pointer to the structure font_info while allocating it dynamically.
7905 If SIZE is 0, load any size of font.
7906 If loading is failed, return NULL. */
7909 x_load_font (f
, fontname
, size
)
7911 register char *fontname
;
7914 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7915 Lisp_Object font_names
;
7917 /* Get a list of all the fonts that match this name. Once we
7918 have a list of matching fonts, we compare them against the fonts
7919 we already have by comparing names. */
7920 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7922 if (!NILP (font_names
))
7927 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7928 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7929 if (dpyinfo
->font_table
[i
].name
7930 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7931 SDATA (XCAR (tail
)))
7932 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7933 SDATA (XCAR (tail
)))))
7934 return (dpyinfo
->font_table
+ i
);
7939 /* Load the font and add it to the table. */
7942 struct MacFontStruct
*font
;
7943 struct font_info
*fontp
;
7944 unsigned long value
;
7947 fontname
= (char *) SDATA (XCAR (font_names
));
7950 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7955 /* Find a free slot in the font table. */
7956 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7957 if (dpyinfo
->font_table
[i
].name
== NULL
)
7960 /* If no free slot found, maybe enlarge the font table. */
7961 if (i
== dpyinfo
->n_fonts
7962 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7965 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7966 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7968 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7971 fontp
= dpyinfo
->font_table
+ i
;
7972 if (i
== dpyinfo
->n_fonts
)
7975 /* Now fill in the slots of *FONTP. */
7977 bzero (fontp
, sizeof (*fontp
));
7979 fontp
->font_idx
= i
;
7980 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7981 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7983 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7985 /* Fixed width font. */
7986 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7993 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7994 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7996 fontp
->space_width
= pcm
->width
;
7998 fontp
->space_width
= FONT_WIDTH (font
);
8002 int width
= pcm
->width
;
8003 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8004 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8005 width
+= pcm
->width
;
8006 fontp
->average_width
= width
/ 95;
8009 fontp
->average_width
= FONT_WIDTH (font
);
8012 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8013 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8015 fontp
->size
= font
->max_bounds
.width
;
8016 fontp
->height
= FONT_HEIGHT (font
);
8018 /* For some font, ascent and descent in max_bounds field is
8019 larger than the above value. */
8020 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8021 if (max_height
> fontp
->height
)
8022 fontp
->height
= max_height
;
8025 /* The slot `encoding' specifies how to map a character
8026 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8027 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8028 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8029 2:0xA020..0xFF7F). For the moment, we don't know which charset
8030 uses this font. So, we set information in fontp->encoding[1]
8031 which is never used by any charset. If mapping can't be
8032 decided, set FONT_ENCODING_NOT_DECIDED. */
8033 if (font
->mac_scriptcode
== smJapanese
)
8034 fontp
->encoding
[1] = 4;
8038 = (font
->max_byte1
== 0
8040 ? (font
->min_char_or_byte2
< 0x80
8041 ? (font
->max_char_or_byte2
< 0x80
8042 ? 0 /* 0x20..0x7F */
8043 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8044 : 1) /* 0xA0..0xFF */
8046 : (font
->min_byte1
< 0x80
8047 ? (font
->max_byte1
< 0x80
8048 ? (font
->min_char_or_byte2
< 0x80
8049 ? (font
->max_char_or_byte2
< 0x80
8050 ? 0 /* 0x2020..0x7F7F */
8051 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8052 : 3) /* 0x20A0..0x7FFF */
8053 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8054 : (font
->min_char_or_byte2
< 0x80
8055 ? (font
->max_char_or_byte2
< 0x80
8056 ? 2 /* 0xA020..0xFF7F */
8057 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8058 : 1))); /* 0xA0A0..0xFFFF */
8061 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8062 fontp
->baseline_offset
8063 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8064 ? (long) value
: 0);
8065 fontp
->relative_compose
8066 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8067 ? (long) value
: 0);
8068 fontp
->default_ascent
8069 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8070 ? (long) value
: 0);
8072 fontp
->baseline_offset
= 0;
8073 fontp
->relative_compose
= 0;
8074 fontp
->default_ascent
= 0;
8077 /* Set global flag fonts_changed_p to non-zero if the font loaded
8078 has a character with a smaller width than any other character
8079 before, or if the font loaded has a smaller height than any
8080 other font loaded before. If this happens, it will make a
8081 glyph matrix reallocation necessary. */
8082 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8089 /* Return a pointer to struct font_info of a font named FONTNAME for
8090 frame F. If no such font is loaded, return NULL. */
8093 x_query_font (f
, fontname
)
8095 register char *fontname
;
8097 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8100 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8101 if (dpyinfo
->font_table
[i
].name
8102 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8103 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8104 return (dpyinfo
->font_table
+ i
);
8109 /* Find a CCL program for a font specified by FONTP, and set the member
8110 `encoder' of the structure. */
8113 x_find_ccl_program (fontp
)
8114 struct font_info
*fontp
;
8116 Lisp_Object list
, elt
;
8118 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8122 && STRINGP (XCAR (elt
))
8123 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8129 struct ccl_program
*ccl
8130 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8132 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8135 fontp
->font_encoder
= ccl
;
8141 /* The Mac Event loop code */
8143 #if !TARGET_API_MAC_CARBON
8145 #include <Quickdraw.h>
8146 #include <Balloons.h>
8147 #include <Devices.h>
8149 #include <Gestalt.h>
8151 #include <Processes.h>
8153 #include <ToolUtils.h>
8154 #include <TextUtils.h>
8155 #include <Dialogs.h>
8158 #include <Resources.h>
8163 #endif /* ! TARGET_API_MAC_CARBON */
8168 #define WINDOW_RESOURCE 128
8169 #define TERM_WINDOW_RESOURCE 129
8171 #define DEFAULT_NUM_COLS 80
8173 #define MIN_DOC_SIZE 64
8174 #define MAX_DOC_SIZE 32767
8176 #define EXTRA_STACK_ALLOC (256 * 1024)
8178 #define ARGV_STRING_LIST_ID 129
8179 #define ABOUT_ALERT_ID 128
8180 #define RAM_TOO_LARGE_ALERT_ID 129
8182 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8183 Lisp_Object Qreverse
;
8185 /* True if using command key as meta key. */
8186 Lisp_Object Vmac_command_key_is_meta
;
8188 /* Modifier associated with the option key, or nil for normal behavior. */
8189 Lisp_Object Vmac_option_modifier
;
8191 /* True if the ctrl and meta keys should be reversed. */
8192 Lisp_Object Vmac_reverse_ctrl_meta
;
8194 /* True if the option and command modifiers should be used to emulate
8195 a three button mouse */
8196 Lisp_Object Vmac_emulate_three_button_mouse
;
8198 #if USE_CARBON_EVENTS
8199 /* True if the mouse wheel button (i.e. button 4) should map to
8200 mouse-2, instead of mouse-3. */
8201 Lisp_Object Vmac_wheel_button_is_mouse_2
;
8203 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
8204 for processing before Emacs sees it. */
8205 Lisp_Object Vmac_pass_command_to_system
;
8207 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
8208 for processing before Emacs sees it. */
8209 Lisp_Object Vmac_pass_control_to_system
;
8212 /* Points to the variable `inev' in the function XTread_socket. It is
8213 used for passing an input event to the function back from
8214 Carbon/Apple event handlers. */
8215 static struct input_event
*read_socket_inev
= NULL
;
8217 /* Set in term/mac-win.el to indicate that event loop can now generate
8218 drag and drop events. */
8219 Lisp_Object Qmac_ready_for_drag_n_drop
;
8221 Point saved_menu_event_location
;
8224 static void init_required_apple_events (void);
8226 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
8228 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
8229 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
8230 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
8232 #if TARGET_API_MAC_CARBON
8234 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8235 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8236 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8237 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8240 static Lisp_Object Qapplication
, Qabout
;
8241 #if USE_CARBON_EVENTS
8243 extern void init_service_handler ();
8244 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
8246 /* Window Event Handler */
8247 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8250 OSErr
install_window_handler (WindowPtr
);
8252 extern void init_emacs_passwd_dir ();
8253 extern int emacs_main (int, char **, char **);
8255 extern void initialize_applescript();
8256 extern void terminate_applescript();
8259 #if USE_CARBON_EVENTS
8260 mac_to_emacs_modifiers (UInt32 mods
)
8262 mac_to_emacs_modifiers (EventModifiers mods
)
8265 unsigned int result
= 0;
8266 if (mods
& macShiftKey
)
8267 result
|= shift_modifier
;
8268 if (mods
& macCtrlKey
)
8269 result
|= ctrl_modifier
;
8270 if (mods
& macMetaKey
)
8271 result
|= meta_modifier
;
8272 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
8273 result
|= alt_modifier
;
8274 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8275 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8277 result
|= XUINT(val
);
8284 mac_get_emulated_btn ( UInt32 modifiers
)
8287 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8288 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8289 if (modifiers
& cmdKey
)
8290 result
= cmdIs3
? 2 : 1;
8291 else if (modifiers
& optionKey
)
8292 result
= cmdIs3
? 1 : 2;
8297 #if USE_CARBON_EVENTS
8298 /* Obtains the event modifiers from the event ref and then calls
8299 mac_to_emacs_modifiers. */
8301 mac_event_to_emacs_modifiers (EventRef eventRef
)
8304 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8305 sizeof (UInt32
), NULL
, &mods
);
8306 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8307 GetEventClass(eventRef
) == kEventClassMouse
)
8309 mods
&= ~(optionKey
| cmdKey
);
8311 return mac_to_emacs_modifiers (mods
);
8314 /* Given an event ref, return the code to use for the mouse button
8315 code in the emacs input_event. */
8317 mac_get_mouse_btn (EventRef ref
)
8319 EventMouseButton result
= kEventMouseButtonPrimary
;
8320 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8321 sizeof (EventMouseButton
), NULL
, &result
);
8324 case kEventMouseButtonPrimary
:
8325 if (NILP (Vmac_emulate_three_button_mouse
))
8329 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8330 sizeof (UInt32
), NULL
, &mods
);
8331 return mac_get_emulated_btn(mods
);
8333 case kEventMouseButtonSecondary
:
8334 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
8335 case kEventMouseButtonTertiary
:
8336 case 4: /* 4 is the number for the mouse wheel button */
8337 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
8343 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8344 events. However the click of the mouse wheel is not converted to a
8345 mouseDown or mouseUp event. Likewise for dead key down events.
8346 This calls ConvertEventRef, but then checks to see if it is a mouse
8347 up/down, or a dead key down carbon event that has not been
8348 converted, and if so, converts it by hand (to be picked up in the
8349 XTread_socket loop). */
8350 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8352 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8357 switch (GetEventClass (eventRef
))
8359 case kEventClassMouse
:
8360 switch (GetEventKind (eventRef
))
8362 case kEventMouseDown
:
8363 eventRec
->what
= mouseDown
;
8368 eventRec
->what
= mouseUp
;
8377 case kEventClassKeyboard
:
8378 switch (GetEventKind (eventRef
))
8380 case kEventRawKeyDown
:
8382 unsigned char char_codes
;
8385 eventRec
->what
= keyDown
;
8386 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8387 NULL
, sizeof (char), NULL
, &char_codes
);
8388 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8389 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8390 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8406 /* Need where and when. */
8409 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8410 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8411 /* Use two step process because new event modifiers are 32-bit
8412 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8413 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8414 NULL
, sizeof (UInt32
), NULL
, &mods
);
8415 eventRec
->modifiers
= mods
;
8417 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8428 Handle menubar_handle
;
8429 MenuHandle menu_handle
;
8431 menubar_handle
= GetNewMBar (128);
8432 if(menubar_handle
== NULL
)
8434 SetMenuBar (menubar_handle
);
8437 #if !TARGET_API_MAC_CARBON
8438 menu_handle
= GetMenuHandle (M_APPLE
);
8439 if(menu_handle
!= NULL
)
8440 AppendResMenu (menu_handle
,'DRVR');
8448 do_init_managers (void)
8450 #if !TARGET_API_MAC_CARBON
8451 InitGraf (&qd
.thePort
);
8453 FlushEvents (everyEvent
, 0);
8458 #endif /* !TARGET_API_MAC_CARBON */
8461 #if !TARGET_API_MAC_CARBON
8462 /* set up some extra stack space for use by emacs */
8463 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8465 /* MaxApplZone must be called for AppleScript to execute more
8466 complicated scripts */
8469 #endif /* !TARGET_API_MAC_CARBON */
8473 do_check_ram_size (void)
8475 SInt32 physical_ram_size
, logical_ram_size
;
8477 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8478 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8479 || physical_ram_size
> (1 << VALBITS
)
8480 || logical_ram_size
> (1 << VALBITS
))
8482 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8488 do_window_update (WindowPtr win
)
8490 struct frame
*f
= mac_window_to_frame (win
);
8494 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8496 if (win
!= tip_window
)
8498 if (f
->async_visible
== 0)
8500 /* Update events may occur when a frame gets iconified. */
8502 f
->async_visible
= 1;
8503 f
->async_iconified
= 0;
8504 SET_FRAME_GARBAGED (f
);
8510 #if TARGET_API_MAC_CARBON
8511 RgnHandle region
= NewRgn ();
8513 GetPortVisibleRegion (GetWindowPort (win
), region
);
8514 GetRegionBounds (region
, &r
);
8515 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8516 UpdateControls (win
, region
);
8517 DisposeRgn (region
);
8519 r
= (*win
->visRgn
)->rgnBBox
;
8520 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8521 UpdateControls (win
, win
->visRgn
);
8530 is_emacs_window (WindowPtr win
)
8532 Lisp_Object tail
, frame
;
8537 FOR_EACH_FRAME (tail
, frame
)
8538 if (FRAME_MAC_P (XFRAME (frame
)))
8539 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8548 /* Window-activate events will do the job. */
8554 /* Window-deactivate events will do the job. */
8559 do_apple_menu (SInt16 menu_item
)
8561 #if !TARGET_API_MAC_CARBON
8563 SInt16 da_driver_refnum
;
8565 if (menu_item
== I_ABOUT
)
8566 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8569 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8570 da_driver_refnum
= OpenDeskAcc (item_name
);
8572 #endif /* !TARGET_API_MAC_CARBON */
8576 do_menu_choice (SInt32 menu_choice
)
8578 SInt16 menu_id
, menu_item
;
8580 menu_id
= HiWord (menu_choice
);
8581 menu_item
= LoWord (menu_choice
);
8589 do_apple_menu (menu_item
);
8594 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8595 MenuHandle menu
= GetMenuHandle (menu_id
);
8600 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8601 menubar_selection_callback (f
, refcon
);
8610 /* Handle drags in size box. Based on code contributed by Ben
8611 Mesander and IM - Window Manager A. */
8614 do_grow_window (WindowPtr w
, EventRecord
*e
)
8617 int rows
, columns
, width
, height
;
8618 struct frame
*f
= mac_window_to_frame (w
);
8619 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8620 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8621 #if TARGET_API_MAC_CARBON
8627 if (size_hints
->flags
& PMinSize
)
8629 min_width
= size_hints
->min_width
;
8630 min_height
= size_hints
->min_height
;
8632 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8634 #if TARGET_API_MAC_CARBON
8635 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8637 height
= new_rect
.bottom
- new_rect
.top
;
8638 width
= new_rect
.right
- new_rect
.left
;
8640 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8641 /* see if it really changed size */
8644 height
= HiWord (grow_size
);
8645 width
= LoWord (grow_size
);
8648 if (width
!= FRAME_PIXEL_WIDTH (f
)
8649 || height
!= FRAME_PIXEL_HEIGHT (f
))
8651 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8652 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8654 x_set_window_size (f
, 0, columns
, rows
);
8659 /* Handle clicks in zoom box. Calculation of "standard state" based
8660 on code in IM - Window Manager A and code contributed by Ben
8661 Mesander. The standard state of an Emacs window is 80-characters
8662 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8665 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8668 Rect zoom_rect
, port_rect
;
8670 int w_title_height
, columns
, rows
, width
, height
;
8671 struct frame
*f
= mac_window_to_frame (w
);
8672 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8674 #if TARGET_API_MAC_CARBON
8676 Point standard_size
;
8678 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8679 standard_size
.v
= dpyinfo
->height
;
8681 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8682 zoom_in_or_out
= inZoomIn
;
8685 /* Adjust the standard size according to character boundaries. */
8687 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8688 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8689 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8690 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8691 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8692 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8693 && port_rect
.left
== zoom_rect
.left
8694 && port_rect
.top
== zoom_rect
.top
)
8695 zoom_in_or_out
= inZoomIn
;
8697 zoom_in_or_out
= inZoomOut
;
8700 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8702 #else /* not TARGET_API_MAC_CARBON */
8703 GetPort (&save_port
);
8705 SetPortWindowPort (w
);
8707 /* Clear window to avoid flicker. */
8708 EraseRect (&(w
->portRect
));
8709 if (zoom_in_or_out
== inZoomOut
)
8711 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8712 LocalToGlobal (&top_left
);
8714 /* calculate height of window's title bar */
8715 w_title_height
= top_left
.v
- 1
8716 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8718 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8719 zoom_rect
= qd
.screenBits
.bounds
;
8720 zoom_rect
.top
+= w_title_height
;
8721 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8723 zoom_rect
.right
= zoom_rect
.left
8724 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8726 /* Adjust the standard size according to character boundaries. */
8727 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8729 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8731 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8735 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8737 SetPort (save_port
);
8738 #endif /* not TARGET_API_MAC_CARBON */
8740 /* retrieve window size and update application values */
8741 #if TARGET_API_MAC_CARBON
8742 GetWindowPortBounds (w
, &port_rect
);
8744 port_rect
= w
->portRect
;
8746 height
= port_rect
.bottom
- port_rect
.top
;
8747 width
= port_rect
.right
- port_rect
.left
;
8749 if (width
!= FRAME_PIXEL_WIDTH (f
)
8750 || height
!= FRAME_PIXEL_HEIGHT (f
))
8752 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8753 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8755 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8756 SET_FRAME_GARBAGED (f
);
8757 cancel_mouse_face (f
);
8759 FRAME_PIXEL_WIDTH (f
) = width
;
8760 FRAME_PIXEL_HEIGHT (f
) = height
;
8762 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8765 /* Intialize AppleEvent dispatcher table for the required events. */
8767 init_required_apple_events ()
8772 /* Make sure we have apple events before starting. */
8773 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8777 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8780 #if TARGET_API_MAC_CARBON
8781 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8782 NewAEEventHandlerUPP
8783 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8786 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8787 NewAEEventHandlerProc
8788 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8794 #if TARGET_API_MAC_CARBON
8795 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8796 NewAEEventHandlerUPP
8797 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8800 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8801 NewAEEventHandlerProc
8802 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8808 #if TARGET_API_MAC_CARBON
8809 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8810 NewAEEventHandlerUPP
8811 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8814 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8815 NewAEEventHandlerProc
8816 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8822 #if TARGET_API_MAC_CARBON
8823 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8824 NewAEEventHandlerUPP
8825 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8828 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8829 NewAEEventHandlerProc
8830 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8838 mac_store_application_menu_event (event
)
8839 #if USE_CARBON_EVENTS
8845 struct input_event buf
;
8846 Lisp_Object frame
, entry
;
8850 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8851 buf
.kind
= MENU_BAR_EVENT
;
8852 buf
.frame_or_window
= frame
;
8854 kbd_buffer_store_event (&buf
);
8856 buf
.arg
= Qapplication
;
8857 kbd_buffer_store_event (&buf
);
8859 #if USE_CARBON_EVENTS
8860 switch (GetEventClass (event
))
8863 case kEventClassService
:
8864 buf
.arg
= Qservices
;
8865 kbd_buffer_store_event (&buf
);
8866 switch (GetEventKind (event
))
8868 case kEventServicePaste
:
8872 case kEventServicePerform
:
8875 CFStringRef message
;
8877 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8878 typeCFStringRef
, NULL
,
8879 sizeof (CFStringRef
), NULL
, &message
);
8881 kbd_buffer_store_event (&buf
);
8882 if (err
== noErr
&& message
)
8883 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8893 #endif /* MAC_OSX */
8894 case kEventClassCommand
:
8898 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8899 NULL
, sizeof (HICommand
), NULL
, &command
);
8900 switch (command
.commandID
)
8902 case kHICommandAbout
:
8906 case kHICommandPreferences
:
8907 entry
= Qpreferences
;
8909 #endif /* MAC_OSX */
8910 case kHICommandQuit
:
8922 #else /* USE_CARBON_EVENTS */
8925 case kHICommandAbout
:
8928 case kHICommandQuit
:
8937 kbd_buffer_store_event (&buf
);
8940 #if USE_CARBON_EVENTS
8941 static pascal OSStatus
8942 mac_handle_command_event (next_handler
, event
, data
)
8943 EventHandlerCallRef next_handler
;
8950 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8951 sizeof (HICommand
), NULL
, &command
);
8953 switch (command
.commandID
)
8955 case kHICommandAbout
:
8957 case kHICommandPreferences
:
8958 #endif /* MAC_OSX */
8959 result
= CallNextEventHandler (next_handler
, event
);
8960 if (result
!= eventNotHandledErr
)
8963 mac_store_application_menu_event (event
);
8970 return eventNotHandledErr
;
8974 init_command_handler ()
8977 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8978 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8980 if (handle_command_eventUPP
== NULL
)
8981 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8982 return InstallApplicationEventHandler (handle_command_eventUPP
,
8983 GetEventTypeCount (specs
), specs
,
8987 static pascal OSStatus
8988 mac_handle_window_event (next_handler
, event
, data
)
8989 EventHandlerCallRef next_handler
;
8996 XSizeHints
*size_hints
;
8998 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8999 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
9001 switch (GetEventKind (event
))
9003 case kEventWindowUpdate
:
9004 result
= CallNextEventHandler (next_handler
, event
);
9005 if (result
!= eventNotHandledErr
)
9008 do_window_update (wp
);
9011 case kEventWindowBoundsChanging
:
9012 result
= CallNextEventHandler (next_handler
, event
);
9013 if (result
!= eventNotHandledErr
)
9016 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
9017 NULL
, sizeof (UInt32
), NULL
, &attributes
);
9018 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
9019 if ((attributes
& kWindowBoundsChangeUserResize
)
9020 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
9021 == (PResizeInc
| PBaseSize
| PMinSize
)))
9026 GetEventParameter (event
, kEventParamCurrentBounds
,
9028 NULL
, sizeof (Rect
), NULL
, &bounds
);
9029 width
= bounds
.right
- bounds
.left
;
9030 height
= bounds
.bottom
- bounds
.top
;
9032 if (width
< size_hints
->min_width
)
9033 width
= size_hints
->min_width
;
9035 width
= size_hints
->base_width
9036 + (int) ((width
- size_hints
->base_width
)
9037 / (float) size_hints
->width_inc
+ .5)
9038 * size_hints
->width_inc
;
9040 if (height
< size_hints
->min_height
)
9041 height
= size_hints
->min_height
;
9043 height
= size_hints
->base_height
9044 + (int) ((height
- size_hints
->base_height
)
9045 / (float) size_hints
->height_inc
+ .5)
9046 * size_hints
->height_inc
;
9048 bounds
.right
= bounds
.left
+ width
;
9049 bounds
.bottom
= bounds
.top
+ height
;
9050 SetEventParameter (event
, kEventParamCurrentBounds
,
9051 typeQDRectangle
, sizeof (Rect
), &bounds
);
9056 case kEventWindowShown
:
9057 case kEventWindowHidden
:
9058 case kEventWindowExpanded
:
9059 case kEventWindowCollapsed
:
9060 result
= CallNextEventHandler (next_handler
, event
);
9062 mac_handle_visibility_change (mac_window_to_frame (wp
));
9068 return eventNotHandledErr
;
9071 static pascal OSStatus
9072 mac_handle_mouse_event (next_handler
, event
, data
)
9073 EventHandlerCallRef next_handler
;
9079 switch (GetEventKind (event
))
9081 case kEventMouseWheelMoved
:
9085 EventMouseWheelAxis axis
;
9089 result
= CallNextEventHandler (next_handler
, event
);
9090 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9093 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9094 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9095 f
= mac_window_to_frame (wp
);
9096 if (f
!= mac_focus_frame (&one_mac_display_info
))
9099 GetEventParameter (event
, kEventParamMouseWheelAxis
,
9100 typeMouseWheelAxis
, NULL
,
9101 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9102 if (axis
!= kEventMouseWheelAxisY
)
9105 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
9106 NULL
, sizeof (SInt32
), NULL
, &delta
);
9107 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9108 NULL
, sizeof (Point
), NULL
, &point
);
9109 read_socket_inev
->kind
= WHEEL_EVENT
;
9110 read_socket_inev
->code
= 0;
9111 read_socket_inev
->modifiers
=
9112 (mac_event_to_emacs_modifiers (event
)
9113 | ((delta
< 0) ? down_modifier
: up_modifier
));
9114 SetPortWindowPort (wp
);
9115 GlobalToLocal (&point
);
9116 XSETINT (read_socket_inev
->x
, point
.h
);
9117 XSETINT (read_socket_inev
->y
, point
.v
);
9118 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9128 return eventNotHandledErr
;
9130 #endif /* USE_CARBON_EVENTS */
9134 install_window_handler (window
)
9138 #if USE_CARBON_EVENTS
9139 EventTypeSpec specs_window
[] =
9140 {{kEventClassWindow
, kEventWindowUpdate
},
9141 {kEventClassWindow
, kEventWindowBoundsChanging
},
9142 {kEventClassWindow
, kEventWindowShown
},
9143 {kEventClassWindow
, kEventWindowHidden
},
9144 {kEventClassWindow
, kEventWindowExpanded
},
9145 {kEventClassWindow
, kEventWindowCollapsed
}};
9146 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9147 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9148 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9150 if (handle_window_eventUPP
== NULL
)
9151 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9152 if (handle_mouse_eventUPP
== NULL
)
9153 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9154 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9155 GetEventTypeCount (specs_window
),
9156 specs_window
, NULL
, NULL
);
9158 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9159 GetEventTypeCount (specs_mouse
),
9160 specs_mouse
, NULL
, NULL
);
9162 #if TARGET_API_MAC_CARBON
9163 if (mac_do_track_dragUPP
== NULL
)
9164 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9165 if (mac_do_receive_dragUPP
== NULL
)
9166 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9169 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9171 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9177 remove_window_handler (window
)
9180 #if TARGET_API_MAC_CARBON
9181 if (mac_do_track_dragUPP
)
9182 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9183 if (mac_do_receive_dragUPP
)
9184 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9188 /* Open Application Apple Event */
9190 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
9196 /* Called when we receive an AppleEvent with an ID of
9197 "kAEOpenDocuments". This routine gets the direct parameter,
9198 extracts the FSSpecs in it, and puts their names on a list. */
9199 #pragma options align=mac68k
9200 typedef struct SelectionRange
{
9201 short unused1
; // 0 (not used)
9202 short lineNum
; // line to select (<0 to specify range)
9203 long startRange
; // start of selection range (if line < 0)
9204 long endRange
; // end of selection range (if line < 0)
9205 long unused2
; // 0 (not used)
9206 long theDate
; // modification date/time
9208 #pragma options align=reset
9211 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
9216 DescType actual_type
;
9218 SelectionRange position
;
9219 Lisp_Object file_list
= Qnil
;
9221 xassert (read_socket_inev
);
9223 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
9225 goto descriptor_error_exit
;
9227 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
9229 file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
9230 make_number (position
.startRange
+ 1),
9231 make_number (position
.endRange
+ 1)),
9234 /* Check to see that we got all of the required parameters from the
9235 event descriptor. For an 'odoc' event this should just be the
9237 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
9238 &actual_type
, (Ptr
) &keyword
,
9239 sizeof (keyword
), &actual_size
);
9240 /* No error means that we found some unused parameters.
9241 errAEDescNotFound means that there are no more parameters. If we
9242 get an error code other than that, flag it. */
9243 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
9245 err
= errAEEventNotHandled
;
9250 /* Got all the parameters we need. Now, go through the direct
9251 object list and parse it up. */
9253 long num_files_to_open
;
9255 err
= AECountItems (&the_desc
, &num_files_to_open
);
9260 /* AE file list is one based so just use that for indexing here. */
9261 for (i
= 1; i
<= num_files_to_open
; i
++)
9263 char unix_path_name
[MAXPATHLEN
];
9267 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
9268 &actual_type
, &fref
, sizeof (FSRef
),
9270 if (err
!= noErr
|| actual_type
!= typeFSRef
)
9273 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
9278 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
9279 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
9280 if (err
!= noErr
) continue;
9282 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
9283 sizeof (unix_path_name
) - 1) == noErr
)
9285 /* x-dnd functions expect undecoded filenames. */
9286 file_list
= Fcons (make_unibyte_string (unix_path_name
,
9287 strlen (unix_path_name
)),
9292 /* Build a DRAG_N_DROP_EVENT type event as is done in
9293 constuct_drag_n_drop in w32term.c. */
9294 if (!NILP (file_list
))
9296 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
9300 read_socket_inev
->kind
= DRAG_N_DROP_EVENT
;
9301 read_socket_inev
->code
= 0;
9302 read_socket_inev
->modifiers
= 0;
9304 XSETINT (read_socket_inev
->x
, 0);
9305 XSETINT (read_socket_inev
->y
, 0);
9307 XSETFRAME (frame
, f
);
9308 read_socket_inev
->frame_or_window
= Fcons (frame
, file_list
);
9311 /* Regardless of whether Emacs was suspended or in the
9312 foreground, ask it to redraw its entire screen. Otherwise
9313 parts of the screen can be left in an inconsistent
9315 wp
= FRAME_MAC_WINDOW (f
);
9317 #if TARGET_API_MAC_CARBON
9321 GetWindowPortBounds (wp
, &r
);
9322 InvalWindowRect (wp
, &r
);
9324 #else /* not TARGET_API_MAC_CARBON */
9325 InvalRect (&(wp
->portRect
));
9326 #endif /* not TARGET_API_MAC_CARBON */
9332 /* Nuke the coerced file list in any case */
9333 err2
= AEDisposeDesc(&the_desc
);
9335 descriptor_error_exit
:
9336 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
9341 #if TARGET_API_MAC_CARBON
9343 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9344 void *handlerRefCon
, DragReference theDrag
)
9346 static int can_accept
;
9349 ItemReference theItem
;
9350 FlavorFlags theFlags
;
9353 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9354 return dragNotAcceptedErr
;
9358 case kDragTrackingEnterHandler
:
9359 CountDragItems (theDrag
, &items
);
9361 for (index
= 1; index
<= items
; index
++)
9363 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9364 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9365 if (result
== noErr
)
9373 case kDragTrackingEnterWindow
:
9376 RgnHandle hilite_rgn
= NewRgn ();
9378 struct frame
*f
= mac_window_to_frame (window
);
9380 GetWindowPortBounds (window
, &r
);
9381 OffsetRect (&r
, -r
.left
, -r
.top
);
9382 RectRgn (hilite_rgn
, &r
);
9383 ShowDragHilite (theDrag
, hilite_rgn
, true);
9384 DisposeRgn (hilite_rgn
);
9385 SetThemeCursor (kThemeCopyArrowCursor
);
9389 case kDragTrackingInWindow
:
9392 case kDragTrackingLeaveWindow
:
9395 struct frame
*f
= mac_window_to_frame (window
);
9397 HideDragHilite (theDrag
);
9398 SetThemeCursor (kThemeArrowCursor
);
9402 case kDragTrackingLeaveHandler
:
9410 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9411 DragReference theDrag
)
9415 FlavorFlags theFlags
;
9418 ItemReference theItem
;
9420 Size size
= sizeof (HFSFlavor
);
9421 Lisp_Object file_list
;
9423 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9424 return dragNotAcceptedErr
;
9427 GetDragMouse (theDrag
, &mouse
, 0L);
9428 CountDragItems (theDrag
, &items
);
9429 for (index
= 1; index
<= items
; index
++)
9431 /* Only handle file references. */
9432 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9433 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9434 if (result
== noErr
)
9439 char unix_path_name
[MAXPATHLEN
];
9441 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
9443 /* Use Carbon routines, otherwise it converts the file name
9444 to /Macintosh HD/..., which is not correct. */
9445 FSpMakeFSRef (&data
.fileSpec
, &fref
);
9446 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
9448 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
9449 sizeof (unix_path_name
) - 1) == noErr
)
9451 /* x-dnd functions expect undecoded filenames. */
9452 file_list
= Fcons (make_unibyte_string (unix_path_name
,
9453 strlen (unix_path_name
)),
9457 /* If there are items in the list, construct an event and post it to
9458 the queue like an interrupt using kbd_buffer_store_event. */
9459 if (!NILP (file_list
))
9461 struct input_event event
;
9463 struct frame
*f
= mac_window_to_frame (window
);
9466 GlobalToLocal (&mouse
);
9467 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9469 event
.kind
= DRAG_N_DROP_EVENT
;
9471 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9472 event
.timestamp
= TickCount () * (1000 / 60);
9473 XSETINT (event
.x
, mouse
.h
);
9474 XSETINT (event
.y
, mouse
.v
);
9475 XSETFRAME (frame
, f
);
9476 event
.frame_or_window
= Fcons (frame
, file_list
);
9478 /* Post to the interrupt queue */
9479 kbd_buffer_store_event (&event
);
9480 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9482 ProcessSerialNumber psn
;
9483 GetCurrentProcess (&psn
);
9484 SetFrontProcess (&psn
);
9490 return dragNotAcceptedErr
;
9495 /* Print Document Apple Event */
9497 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
9499 return errAEEventNotHandled
;
9504 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
9506 #if USE_CARBON_EVENTS
9508 EventRef event
= NULL
;
9509 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
9511 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
9512 kEventAttributeUserEvent
, &event
);
9514 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9515 sizeof (HICommand
), &quit_command
);
9517 mac_store_application_menu_event (event
);
9519 ReleaseEvent (event
);
9524 return errAEEventNotHandled
;
9526 mac_store_application_menu_event (kHICommandQuit
);
9535 profiler_exit_proc ()
9537 ProfilerDump ("\pEmacs.prof");
9542 /* These few functions implement Emacs as a normal Mac application
9543 (almost): set up the heap and the Toolbox, handle necessary system
9544 events plus a few simple menu events. They also set up Emacs's
9545 access to functions defined in the rest of this file. Emacs uses
9546 function hooks to perform all its terminal I/O. A complete list of
9547 these functions appear in termhooks.h. For what they do, read the
9548 comments there and see also w32term.c and xterm.c. What's
9549 noticeably missing here is the event loop, which is normally
9550 present in most Mac application. After performing the necessary
9551 Mac initializations, main passes off control to emacs_main
9552 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9553 (defined further below) to read input. This is where
9554 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9561 #if __profile__ /* is the profiler on? */
9562 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9567 /* set creator and type for files created by MSL */
9572 do_init_managers ();
9577 do_check_ram_size ();
9580 init_emacs_passwd_dir ();
9584 initialize_applescript ();
9586 init_required_apple_events ();
9592 /* set up argv array from STR# resource */
9593 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9597 /* free up AppleScript resources on exit */
9598 atexit (terminate_applescript
);
9600 #if __profile__ /* is the profiler on? */
9601 atexit (profiler_exit_proc
);
9604 /* 3rd param "envp" never used in emacs_main */
9605 (void) emacs_main (argc
, argv
, 0);
9608 /* Never reached - real exit in Fkill_emacs */
9613 /* Table for translating Mac keycode to X keysym values. Contributed
9615 Mapping for special keys is now identical to that in Apple X11
9616 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9617 on the right of the Cmd key on laptops, and fn + `enter' (->
9619 static unsigned char keycode_to_xkeysym_table
[] = {
9620 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9621 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9622 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9624 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9625 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9626 /*0x38*/ 0, 0, 0, 0,
9627 /*0x3C*/ 0, 0, 0, 0,
9629 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9630 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9631 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9632 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9634 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9635 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9636 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9637 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9639 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9640 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9641 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9642 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9644 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9645 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9646 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9647 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9651 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9653 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9654 return *xKeySym
!= 0;
9657 #if !USE_CARBON_EVENTS
9658 static RgnHandle mouse_region
= NULL
;
9661 mac_wait_next_event (er
, sleep_time
, dequeue
)
9666 static EventRecord er_buf
= {nullEvent
};
9667 UInt32 target_tick
, current_tick
;
9668 EventMask event_mask
;
9670 if (mouse_region
== NULL
)
9671 mouse_region
= NewRgn ();
9673 event_mask
= everyEvent
;
9674 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
9675 event_mask
-= highLevelEventMask
;
9677 current_tick
= TickCount ();
9678 target_tick
= current_tick
+ sleep_time
;
9680 if (er_buf
.what
== nullEvent
)
9681 while (!WaitNextEvent (event_mask
, &er_buf
,
9682 target_tick
- current_tick
, mouse_region
))
9684 current_tick
= TickCount ();
9685 if (target_tick
<= current_tick
)
9691 er_buf
.what
= nullEvent
;
9694 #endif /* not USE_CARBON_EVENTS */
9696 /* Emacs calls this whenever it wants to read an input event from the
9699 XTread_socket (sd
, expected
, hold_quit
)
9701 struct input_event
*hold_quit
;
9703 struct input_event inev
;
9705 #if USE_CARBON_EVENTS
9707 EventTargetRef toolbox_dispatcher
;
9710 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9712 if (interrupt_input_blocked
)
9714 interrupt_input_pending
= 1;
9718 interrupt_input_pending
= 0;
9721 /* So people can tell when we have read the available input. */
9722 input_signal_count
++;
9724 #if USE_CARBON_EVENTS
9725 toolbox_dispatcher
= GetEventDispatcherTarget ();
9727 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9728 kEventRemoveFromQueue
, &eventRef
))
9729 #else /* !USE_CARBON_EVENTS */
9730 while (mac_wait_next_event (&er
, 0, true))
9731 #endif /* !USE_CARBON_EVENTS */
9735 unsigned long timestamp
;
9737 /* It is necessary to set this (additional) argument slot of an
9738 event to nil because keyboard.c protects incompletely
9739 processed event from being garbage collected by placing them
9740 in the kbd_buffer_gcpro vector. */
9742 inev
.kind
= NO_EVENT
;
9745 #if USE_CARBON_EVENTS
9746 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9748 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9751 #if USE_CARBON_EVENTS
9752 /* Handle new events */
9753 if (!mac_convert_event_ref (eventRef
, &er
))
9755 /* There used to be a handler for the kEventMouseWheelMoved
9756 event here. But as of Mac OS X 10.4, this kind of event
9757 is not directly posted to the main event queue by
9758 two-finger scrolling on the trackpad. Instead, some
9759 private event is posted and it is converted to a wheel
9760 event by the default handler for the application target.
9761 The converted one can be received by a Carbon event
9762 handler installed on a window target. */
9763 read_socket_inev
= &inev
;
9764 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9765 read_socket_inev
= NULL
;
9768 #endif /* USE_CARBON_EVENTS */
9774 WindowPtr window_ptr
;
9775 ControlPartCode part_code
;
9778 #if USE_CARBON_EVENTS
9779 /* This is needed to send mouse events like aqua window
9780 buttons to the correct handler. */
9781 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9782 != eventNotHandledErr
)
9786 if (dpyinfo
->grabbed
&& last_mouse_frame
9787 && FRAME_LIVE_P (last_mouse_frame
))
9789 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9790 part_code
= inContent
;
9794 part_code
= FindWindow (er
.where
, &window_ptr
);
9795 if (tip_window
&& window_ptr
== tip_window
)
9797 HideWindow (tip_window
);
9798 part_code
= FindWindow (er
.where
, &window_ptr
);
9802 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
9808 f
= mac_focus_frame (dpyinfo
);
9809 saved_menu_event_location
= er
.where
;
9810 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9811 XSETFRAME (inev
.frame_or_window
, f
);
9815 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9816 SelectWindow (window_ptr
);
9819 ControlPartCode control_part_code
;
9821 Point mouse_loc
= er
.where
;
9823 ControlKind control_kind
;
9826 f
= mac_window_to_frame (window_ptr
);
9827 /* convert to local coordinates of new window */
9828 SetPortWindowPort (window_ptr
);
9830 GlobalToLocal (&mouse_loc
);
9831 #if TARGET_API_MAC_CARBON
9832 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9833 &control_part_code
);
9836 GetControlKind (ch
, &control_kind
);
9839 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9843 #if USE_CARBON_EVENTS
9844 inev
.code
= mac_get_mouse_btn (eventRef
);
9845 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9847 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9848 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9850 XSETINT (inev
.x
, mouse_loc
.h
);
9851 XSETINT (inev
.y
, mouse_loc
.v
);
9853 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9855 #ifndef USE_TOOLKIT_SCROLL_BARS
9856 /* control_part_code becomes kControlNoPart if
9857 a progress indicator is clicked. */
9858 && control_part_code
!= kControlNoPart
9859 #else /* USE_TOOLKIT_SCROLL_BARS */
9861 && control_kind
.kind
== kControlKindScrollBar
9862 #endif /* MAC_OSX */
9863 #endif /* USE_TOOLKIT_SCROLL_BARS */
9866 struct scroll_bar
*bar
;
9868 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9870 bar
= tracked_scroll_bar
;
9871 #ifndef USE_TOOLKIT_SCROLL_BARS
9872 control_part_code
= kControlIndicatorPart
;
9876 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9877 #ifdef USE_TOOLKIT_SCROLL_BARS
9878 /* Make the "Ctrl-Mouse-2 splits window" work
9879 for toolkit scroll bars. */
9880 if (er
.modifiers
& controlKey
)
9881 x_scroll_bar_handle_click (bar
, control_part_code
,
9883 else if (er
.what
== mouseDown
)
9884 x_scroll_bar_handle_press (bar
, control_part_code
,
9887 x_scroll_bar_handle_release (bar
, &inev
);
9888 #else /* not USE_TOOLKIT_SCROLL_BARS */
9889 x_scroll_bar_handle_click (bar
, control_part_code
,
9891 if (er
.what
== mouseDown
9892 && control_part_code
== kControlIndicatorPart
)
9893 tracked_scroll_bar
= bar
;
9895 tracked_scroll_bar
= NULL
;
9896 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9901 int x
= mouse_loc
.h
;
9902 int y
= mouse_loc
.v
;
9904 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9905 if (EQ (window
, f
->tool_bar_window
))
9907 if (er
.what
== mouseDown
)
9908 handle_tool_bar_click (f
, x
, y
, 1, 0);
9910 handle_tool_bar_click (f
, x
, y
, 0,
9916 XSETFRAME (inev
.frame_or_window
, f
);
9917 inev
.kind
= MOUSE_CLICK_EVENT
;
9921 if (er
.what
== mouseDown
)
9923 dpyinfo
->grabbed
|= (1 << inev
.code
);
9924 last_mouse_frame
= f
;
9925 /* Ignore any mouse motion that happened
9926 before this event; any subsequent
9927 mouse-movement Emacs events should reflect
9928 only motion after the ButtonPress. */
9933 last_tool_bar_item
= -1;
9937 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9938 /* If a button is released though it was not
9939 previously pressed, that would be because
9940 of multi-button emulation. */
9941 dpyinfo
->grabbed
= 0;
9943 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9946 #ifdef USE_TOOLKIT_SCROLL_BARS
9947 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9952 inev
.modifiers
|= down_modifier
;
9955 inev
.modifiers
|= up_modifier
;
9962 #if TARGET_API_MAC_CARBON
9963 DragWindow (window_ptr
, er
.where
, NULL
);
9964 #else /* not TARGET_API_MAC_CARBON */
9965 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9966 #endif /* not TARGET_API_MAC_CARBON */
9967 /* Update the frame parameters. */
9969 struct frame
*f
= mac_window_to_frame (window_ptr
);
9971 if (f
&& !f
->async_iconified
)
9972 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9977 if (TrackGoAway (window_ptr
, er
.where
))
9979 inev
.kind
= DELETE_WINDOW_EVENT
;
9980 XSETFRAME (inev
.frame_or_window
,
9981 mac_window_to_frame (window_ptr
));
9985 /* window resize handling added --ben */
9987 do_grow_window (window_ptr
, &er
);
9990 /* window zoom handling added --ben */
9993 if (TrackBox (window_ptr
, er
.where
, part_code
))
9994 do_zoom_window (window_ptr
, part_code
);
10004 #if USE_CARBON_EVENTS
10005 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10006 != eventNotHandledErr
)
10009 do_window_update ((WindowPtr
) er
.message
);
10014 #if USE_CARBON_EVENTS
10015 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10016 != eventNotHandledErr
)
10019 switch ((er
.message
>> 24) & 0x000000FF)
10021 case suspendResumeMessage
:
10022 if ((er
.message
& resumeFlag
) == 1)
10028 case mouseMovedMessage
:
10029 #if !USE_CARBON_EVENTS
10030 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
10031 er
.where
.h
+ 1, er
.where
.v
+ 1);
10033 previous_help_echo_string
= help_echo_string
;
10034 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
10035 help_echo_pos
= -1;
10037 if (dpyinfo
->grabbed
&& last_mouse_frame
10038 && FRAME_LIVE_P (last_mouse_frame
))
10039 f
= last_mouse_frame
;
10041 f
= dpyinfo
->x_focus_frame
;
10043 if (dpyinfo
->mouse_face_hidden
)
10045 dpyinfo
->mouse_face_hidden
= 0;
10046 clear_mouse_face (dpyinfo
);
10051 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
10052 Point mouse_pos
= er
.where
;
10054 SetPortWindowPort (wp
);
10056 GlobalToLocal (&mouse_pos
);
10058 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10059 #ifdef USE_TOOLKIT_SCROLL_BARS
10060 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
10062 #else /* not USE_TOOLKIT_SCROLL_BARS */
10063 x_scroll_bar_note_movement (tracked_scroll_bar
,
10065 - XINT (tracked_scroll_bar
->top
),
10066 er
.when
* (1000 / 60));
10067 #endif /* not USE_TOOLKIT_SCROLL_BARS */
10070 /* Generate SELECT_WINDOW_EVENTs when needed. */
10071 if (mouse_autoselect_window
)
10073 Lisp_Object window
;
10075 window
= window_from_coordinates (f
,
10080 /* Window will be selected only when it is
10081 not selected now and last mouse movement
10082 event was not in it. Minibuffer window
10083 will be selected iff it is active. */
10084 if (WINDOWP (window
)
10085 && !EQ (window
, last_window
)
10086 && !EQ (window
, selected_window
))
10088 inev
.kind
= SELECT_WINDOW_EVENT
;
10089 inev
.frame_or_window
= window
;
10092 last_window
=window
;
10094 note_mouse_movement (f
, &mouse_pos
);
10098 /* If the contents of the global variable
10099 help_echo_string has changed, generate a
10101 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10109 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10111 #if USE_CARBON_EVENTS
10112 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10113 != eventNotHandledErr
)
10116 if (window_ptr
== tip_window
)
10118 HideWindow (tip_window
);
10122 if (!is_emacs_window (window_ptr
))
10125 if ((er
.modifiers
& activeFlag
) != 0)
10127 /* A window has been activated */
10128 Point mouse_loc
= er
.where
;
10130 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10132 SetPortWindowPort (window_ptr
);
10133 GlobalToLocal (&mouse_loc
);
10134 /* Window-activated event counts as mouse movement,
10135 so update things that depend on mouse position. */
10136 note_mouse_movement (mac_window_to_frame (window_ptr
),
10141 /* A window has been deactivated */
10142 #if USE_TOOLKIT_SCROLL_BARS
10143 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10145 struct input_event event
;
10147 EVENT_INIT (event
);
10148 event
.kind
= NO_EVENT
;
10149 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10150 if (event
.kind
!= NO_EVENT
)
10152 event
.timestamp
= timestamp
;
10153 kbd_buffer_store_event_hold (&event
, hold_quit
);
10158 dpyinfo
->grabbed
= 0;
10160 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10162 f
= mac_window_to_frame (window_ptr
);
10163 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10165 /* If we move outside the frame, then we're
10166 certainly no longer on any text in the
10168 clear_mouse_face (dpyinfo
);
10169 dpyinfo
->mouse_face_mouse_frame
= 0;
10172 /* Generate a nil HELP_EVENT to cancel a help-echo.
10173 Do it only if there's something to cancel.
10174 Otherwise, the startup message is cleared when the
10175 mouse leaves the frame. */
10176 if (any_help_event_p
)
10185 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10188 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10189 /* When using Carbon Events, we need to pass raw keyboard
10190 events to the TSM ourselves. If TSM handles it, it
10191 will pass back noErr, otherwise it will pass back
10192 "eventNotHandledErr" and we can process it
10194 if ((!NILP (Vmac_pass_command_to_system
)
10195 || !(er
.modifiers
& cmdKey
))
10196 && (!NILP (Vmac_pass_control_to_system
)
10197 || !(er
.modifiers
& controlKey
))
10198 && (!NILP (Vmac_command_key_is_meta
)
10199 && NILP (Vmac_option_modifier
)
10200 || !(er
.modifiers
& optionKey
)))
10201 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10202 != eventNotHandledErr
)
10207 if (dpyinfo
->x_focus_frame
== NULL
)
10209 /* Beep if keyboard input occurs when all the frames
10217 static SInt16 last_key_script
= -1;
10218 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10220 if (last_key_script
!= current_key_script
)
10222 struct input_event event
;
10224 EVENT_INIT (event
);
10225 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10227 event
.code
= current_key_script
;
10228 event
.timestamp
= timestamp
;
10229 kbd_buffer_store_event (&event
);
10232 last_key_script
= current_key_script
;
10237 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10239 clear_mouse_face (dpyinfo
);
10240 dpyinfo
->mouse_face_hidden
= 1;
10243 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10245 inev
.code
= 0xff00 | xkeysym
;
10246 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10250 if (er
.modifiers
& (controlKey
|
10251 (NILP (Vmac_command_key_is_meta
) ? optionKey
10254 /* This code comes from Keyboard Resource,
10255 Appendix C of IM - Text. This is necessary
10256 since shift is ignored in KCHR table
10257 translation when option or command is pressed.
10258 It also does not translate correctly
10259 control-shift chars like C-% so mask off shift
10261 int new_modifiers
= er
.modifiers
& 0xe600;
10262 /* mask off option and command */
10263 int new_keycode
= keycode
| new_modifiers
;
10264 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10265 unsigned long some_state
= 0;
10266 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
10267 &some_state
) & 0xff;
10269 else if (!NILP (Vmac_option_modifier
)
10270 && (er
.modifiers
& optionKey
))
10272 /* When using the option key as an emacs modifier,
10273 convert the pressed key code back to one
10274 without the Mac option modifier applied. */
10275 int new_modifiers
= er
.modifiers
& ~optionKey
;
10276 int new_keycode
= keycode
| new_modifiers
;
10277 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10278 unsigned long some_state
= 0;
10279 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
10280 &some_state
) & 0xff;
10283 inev
.code
= er
.message
& charCodeMask
;
10284 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10288 #if USE_CARBON_EVENTS
10289 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10291 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10293 inev
.modifiers
|= (extra_keyboard_modifiers
10294 & (meta_modifier
| alt_modifier
10295 | hyper_modifier
| super_modifier
));
10296 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10299 case kHighLevelEvent
:
10300 read_socket_inev
= &inev
;
10301 AEProcessAppleEvent (&er
);
10302 read_socket_inev
= NULL
;
10308 #if USE_CARBON_EVENTS
10309 ReleaseEvent (eventRef
);
10312 if (inev
.kind
!= NO_EVENT
)
10314 inev
.timestamp
= timestamp
;
10315 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10320 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10325 XSETFRAME (frame
, f
);
10331 any_help_event_p
= 1;
10332 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10333 help_echo_object
, help_echo_pos
);
10337 help_echo_string
= Qnil
;
10338 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10345 /* If the focus was just given to an autoraising frame,
10347 /* ??? This ought to be able to handle more than one such frame. */
10348 if (pending_autoraise_frame
)
10350 x_raise_frame (pending_autoraise_frame
);
10351 pending_autoraise_frame
= 0;
10354 #if !USE_CARBON_EVENTS
10355 /* Check which frames are still visible. We do this here because
10356 there doesn't seem to be any direct notification from the Window
10357 Manager that the visibility of a window has changed (at least,
10358 not in all cases). */
10360 Lisp_Object tail
, frame
;
10362 FOR_EACH_FRAME (tail
, frame
)
10364 struct frame
*f
= XFRAME (frame
);
10366 /* The tooltip has been drawn already. Avoid the
10367 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10368 if (EQ (frame
, tip_frame
))
10371 if (FRAME_MAC_P (f
))
10372 mac_handle_visibility_change (f
);
10382 /* Need to override CodeWarrior's input function so no conversion is
10383 done on newlines Otherwise compiled functions in .elc files will be
10384 read incorrectly. Defined in ...:MSL C:MSL
10385 Common:Source:buffer_io.c. */
10388 __convert_to_newlines (unsigned char * p
, size_t * n
)
10390 #pragma unused(p,n)
10394 __convert_from_newlines (unsigned char * p
, size_t * n
)
10396 #pragma unused(p,n)
10402 make_mac_terminal_frame (struct frame
*f
)
10407 XSETFRAME (frame
, f
);
10409 f
->output_method
= output_mac
;
10410 f
->output_data
.mac
= (struct mac_output
*)
10411 xmalloc (sizeof (struct mac_output
));
10412 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10414 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10416 FRAME_COLS (f
) = 96;
10417 FRAME_LINES (f
) = 4;
10419 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10420 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10422 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10424 f
->output_data
.mac
->cursor_pixel
= 0;
10425 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10426 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10427 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10429 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10430 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10431 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10432 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10433 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10434 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10436 FRAME_FONTSET (f
) = -1;
10437 f
->output_data
.mac
->explicit_parent
= 0;
10440 f
->border_width
= 0;
10442 f
->internal_border_width
= 0;
10447 f
->new_text_cols
= 0;
10448 f
->new_text_lines
= 0;
10450 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10451 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10452 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10456 if (!(FRAME_MAC_WINDOW (f
) =
10457 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10458 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10460 /* so that update events can find this mac_output struct */
10461 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10467 /* Need to be initialized for unshow_buffer in window.c. */
10468 selected_window
= f
->selected_window
;
10470 Fmodify_frame_parameters (frame
,
10471 Fcons (Fcons (Qfont
,
10472 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10473 Fmodify_frame_parameters (frame
,
10474 Fcons (Fcons (Qforeground_color
,
10475 build_string ("black")), Qnil
));
10476 Fmodify_frame_parameters (frame
,
10477 Fcons (Fcons (Qbackground_color
,
10478 build_string ("white")), Qnil
));
10483 /***********************************************************************
10485 ***********************************************************************/
10487 int mac_initialized
= 0;
10490 mac_initialize_display_info ()
10492 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10493 GDHandle main_device_handle
;
10495 bzero (dpyinfo
, sizeof (*dpyinfo
));
10498 dpyinfo
->mac_id_name
10499 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10500 + SCHARS (Vsystem_name
)
10502 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10503 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10505 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10506 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10509 main_device_handle
= LMGetMainDevice();
10511 dpyinfo
->reference_count
= 0;
10512 dpyinfo
->resx
= 75.0;
10513 dpyinfo
->resy
= 75.0;
10514 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10516 /* HasDepth returns true if it is possible to have a 32 bit display,
10517 but this may not be what is actually used. Mac OSX can do better.
10518 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10519 header for CGGetActiveDisplayList says that the first display returned
10520 is the active one, so we use that. */
10522 CGDirectDisplayID disp_id
[1];
10523 CGDisplayCount disp_count
;
10524 CGDisplayErr error_code
;
10526 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10527 if (error_code
!= 0)
10528 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10530 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10533 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10534 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10535 gdDevType
, dpyinfo
->color_p
))
10538 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10539 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10540 dpyinfo
->grabbed
= 0;
10541 dpyinfo
->root_window
= NULL
;
10542 dpyinfo
->image_cache
= make_image_cache ();
10544 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10545 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10546 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10547 dpyinfo
->mouse_face_window
= Qnil
;
10548 dpyinfo
->mouse_face_overlay
= Qnil
;
10549 dpyinfo
->mouse_face_hidden
= 0;
10554 mac_make_rdb (xrm_option
)
10557 XrmDatabase database
;
10559 database
= xrm_get_preference_database (NULL
);
10561 xrm_merge_string_database (database
, xrm_option
);
10566 struct mac_display_info
*
10567 mac_term_init (display_name
, xrm_option
, resource_name
)
10568 Lisp_Object display_name
;
10570 char *resource_name
;
10572 struct mac_display_info
*dpyinfo
;
10576 if (!mac_initialized
)
10579 mac_initialized
= 1;
10582 if (x_display_list
)
10583 error ("Sorry, this version can only handle one display");
10585 mac_initialize_display_info ();
10587 dpyinfo
= &one_mac_display_info
;
10589 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10591 /* Put this display on the chain. */
10592 dpyinfo
->next
= x_display_list
;
10593 x_display_list
= dpyinfo
;
10595 /* Put it on x_display_name_list. */
10596 x_display_name_list
= Fcons (Fcons (display_name
,
10597 Fcons (Qnil
, dpyinfo
->xrdb
)),
10598 x_display_name_list
);
10599 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10605 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10608 x_delete_display (dpyinfo
)
10609 struct mac_display_info
*dpyinfo
;
10613 /* Discard this display from x_display_name_list and x_display_list.
10614 We can't use Fdelq because that can quit. */
10615 if (! NILP (x_display_name_list
)
10616 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10617 x_display_name_list
= XCDR (x_display_name_list
);
10622 tail
= x_display_name_list
;
10623 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10625 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10627 XSETCDR (tail
, XCDR (XCDR (tail
)));
10630 tail
= XCDR (tail
);
10634 if (x_display_list
== dpyinfo
)
10635 x_display_list
= dpyinfo
->next
;
10638 struct x_display_info
*tail
;
10640 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10641 if (tail
->next
== dpyinfo
)
10642 tail
->next
= tail
->next
->next
;
10645 /* Free the font names in the font table. */
10646 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10647 if (dpyinfo
->font_table
[i
].name
)
10649 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10650 xfree (dpyinfo
->font_table
[i
].full_name
);
10651 xfree (dpyinfo
->font_table
[i
].name
);
10654 if (dpyinfo
->font_table
->font_encoder
)
10655 xfree (dpyinfo
->font_table
->font_encoder
);
10657 xfree (dpyinfo
->font_table
);
10658 xfree (dpyinfo
->mac_id_name
);
10660 if (x_display_list
== 0)
10662 mac_clear_font_name_table ();
10663 bzero (dpyinfo
, sizeof (*dpyinfo
));
10672 extern int inhibit_window_system
;
10673 extern int noninteractive
;
10674 CFBundleRef appsBundle
;
10677 /* No need to test if already -nw*/
10678 if (inhibit_window_system
|| noninteractive
)
10681 appsBundle
= CFBundleGetMainBundle();
10682 if (appsBundle
!= NULL
)
10684 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10685 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10686 /* We found the bundle identifier, now we know we are valid. */
10693 /* MAC_TODO: Have this start the bundled executable */
10695 /* For now, prevent the fatal error by bringing it up in the terminal */
10696 inhibit_window_system
= 1;
10700 MakeMeTheFrontProcess ()
10702 ProcessSerialNumber psn
;
10705 err
= GetCurrentProcess (&psn
);
10707 (void) SetFrontProcess (&psn
);
10710 /***** Code to handle C-g testing *****/
10712 /* Contains the Mac modifier formed from quit_char */
10713 int mac_quit_char_modifiers
= 0;
10714 int mac_quit_char_keycode
;
10715 extern int quit_char
;
10718 mac_determine_quit_char_modifiers()
10720 /* Todo: Determine modifiers from quit_char. */
10721 UInt32 qc_modifiers
= ctrl_modifier
;
10723 /* Map modifiers */
10724 mac_quit_char_modifiers
= 0;
10725 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
10726 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
10727 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
10728 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
10732 init_quit_char_handler ()
10734 /* TODO: Let this support keys other the 'g' */
10735 mac_quit_char_keycode
= 5;
10736 /* Look at <architecture/adb_kb_map.h> for details */
10737 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10739 mac_determine_quit_char_modifiers();
10741 #endif /* MAC_OSX */
10749 MenuItemIndex menu_index
;
10751 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10752 &menu
, &menu_index
);
10754 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10755 #if USE_CARBON_EVENTS
10756 EnableMenuCommand (NULL
, kHICommandPreferences
);
10757 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10758 &menu
, &menu_index
);
10761 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10762 InsertMenuItemTextWithCFString (menu
, NULL
,
10763 0, kMenuItemAttrSeparator
, 0);
10764 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10765 0, 0, kHICommandAbout
);
10767 #endif /* USE_CARBON_EVENTS */
10768 #else /* !MAC_OSX */
10769 #if USE_CARBON_EVENTS
10770 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10776 /* Set up use of X before we make the first connection. */
10778 extern frame_parm_handler mac_frame_parm_handlers
[];
10780 static struct redisplay_interface x_redisplay_interface
=
10782 mac_frame_parm_handlers
,
10786 x_clear_end_of_line
,
10788 x_after_update_window_line
,
10789 x_update_window_begin
,
10790 x_update_window_end
,
10793 0, /* flush_display_optional */
10794 x_clear_window_mouse_face
,
10795 x_get_glyph_overhangs
,
10796 x_fix_overlapping_area
,
10797 x_draw_fringe_bitmap
,
10798 0, /* define_fringe_bitmap */
10799 0, /* destroy_fringe_bitmap */
10800 mac_per_char_metric
,
10802 mac_compute_glyph_string_overhangs
,
10803 x_draw_glyph_string
,
10804 mac_define_frame_cursor
,
10805 mac_clear_frame_area
,
10806 mac_draw_window_cursor
,
10807 mac_draw_vertical_window_border
,
10808 mac_shift_glyphs_for_insert
10814 rif
= &x_redisplay_interface
;
10816 clear_frame_hook
= x_clear_frame
;
10817 ins_del_lines_hook
= x_ins_del_lines
;
10818 delete_glyphs_hook
= x_delete_glyphs
;
10819 ring_bell_hook
= XTring_bell
;
10820 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10821 set_terminal_modes_hook
= XTset_terminal_modes
;
10822 update_begin_hook
= x_update_begin
;
10823 update_end_hook
= x_update_end
;
10824 set_terminal_window_hook
= XTset_terminal_window
;
10825 read_socket_hook
= XTread_socket
;
10826 frame_up_to_date_hook
= XTframe_up_to_date
;
10827 mouse_position_hook
= XTmouse_position
;
10828 frame_rehighlight_hook
= XTframe_rehighlight
;
10829 frame_raise_lower_hook
= XTframe_raise_lower
;
10831 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10832 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10833 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10834 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10836 scroll_region_ok
= 1; /* we'll scroll partial frames */
10837 char_ins_del_ok
= 1;
10838 line_ins_del_ok
= 1; /* we'll just blt 'em */
10839 fast_clear_end_of_line
= 1; /* X does this well */
10840 memory_below_frame
= 0; /* we don't remember what scrolls
10844 last_tool_bar_item
= -1;
10845 any_help_event_p
= 0;
10847 /* Try to use interrupt input; if we can't, then start polling. */
10848 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10852 #if TARGET_API_MAC_CARBON
10853 init_required_apple_events ();
10855 #if USE_CARBON_EVENTS
10857 init_service_handler ();
10859 init_quit_char_handler ();
10860 #endif /* MAC_OSX */
10862 init_command_handler ();
10865 #endif /* USE_CARBON_EVENTS */
10868 if (!inhibit_window_system
)
10869 MakeMeTheFrontProcess ();
10880 staticpro (&x_error_message_string
);
10881 x_error_message_string
= Qnil
;
10884 Qmodifier_value
= intern ("modifier-value");
10885 Qalt
= intern ("alt");
10886 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10887 Qhyper
= intern ("hyper");
10888 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10889 Qsuper
= intern ("super");
10890 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10892 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10893 Qabout
= intern ("about"); staticpro (&Qabout
);
10895 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10896 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10897 Qservices
= intern ("services"); staticpro (&Qservices
);
10898 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10899 Qperform
= intern ("perform"); staticpro (&Qperform
);
10903 Fprovide (intern ("mac-carbon"), Qnil
);
10906 staticpro (&Qreverse
);
10907 Qreverse
= intern ("reverse");
10909 staticpro (&x_display_name_list
);
10910 x_display_name_list
= Qnil
;
10912 staticpro (&last_mouse_scroll_bar
);
10913 last_mouse_scroll_bar
= Qnil
;
10915 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10916 staticpro (&Qmac_ready_for_drag_n_drop
);
10919 staticpro (&atsu_font_id_hash
);
10920 atsu_font_id_hash
= Qnil
;
10923 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10924 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10925 #ifdef USE_TOOLKIT_SCROLL_BARS
10926 Vx_toolkit_scroll_bars
= Qt
;
10928 Vx_toolkit_scroll_bars
= Qnil
;
10931 staticpro (&last_mouse_motion_frame
);
10932 last_mouse_motion_frame
= Qnil
;
10934 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10935 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10936 Otherwise the option key is used. */);
10937 Vmac_command_key_is_meta
= Qt
;
10939 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10940 doc
: /* Modifier to use for the Mac alt/option key. The value can
10941 be alt, hyper, or super for the respective modifier. If the value is
10942 nil then the key will act as the normal Mac option modifier. */);
10943 Vmac_option_modifier
= Qnil
;
10945 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10946 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10947 useful for non-standard keyboard layouts. */);
10948 Vmac_reverse_ctrl_meta
= Qnil
;
10950 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10951 &Vmac_emulate_three_button_mouse
,
10952 doc
: /* t means that when the option-key is held down while pressing the
10953 mouse button, the click will register as mouse-2 and while the
10954 command-key is held down, the click will register as mouse-3.
10955 'reverse means that the option-key will register for mouse-3
10956 and the command-key will register for mouse-2. nil means that
10957 no emulation should be done and the modifiers should be placed
10958 on the mouse-1 event. */);
10959 Vmac_emulate_three_button_mouse
= Qnil
;
10961 #if USE_CARBON_EVENTS
10962 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10963 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10964 the right click will be mouse-3.
10965 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10966 Vmac_wheel_button_is_mouse_2
= Qt
;
10968 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10969 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10970 Toolbox for processing before Emacs sees it. */);
10971 Vmac_pass_command_to_system
= Qt
;
10973 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10974 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10975 Toolbox for processing before Emacs sees it. */);
10976 Vmac_pass_control_to_system
= Qt
;
10980 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10981 doc
: /* If non-nil, allow anti-aliasing.
10982 The text will be rendered using Core Graphics text rendering which
10983 may anti-alias the text. */);
10984 Vmac_use_core_graphics
= Qnil
;
10986 /* Register an entry for `mac-roman' so that it can be used when
10987 creating the terminal frame on Mac OS 9 before loading
10988 term/mac-win.elc. */
10989 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10990 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10991 Each entry should be of the form:
10993 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10995 where CHARSET-NAME is a string used in font names to identify the
10996 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10997 is a coding system corresponding to TEXT-ENCODING. */);
10998 Vmac_charset_info_alist
=
10999 Fcons (list3 (build_string ("mac-roman"),
11000 make_number (smRoman
), Qnil
), Qnil
);
11003 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
11004 (do not change this comment) */