1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
29 #include "blockinput.h"
38 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
41 #define USE_CARBON_EVENTS 1
42 #else /* not MAC_OSX */
43 #include <Quickdraw.h>
44 #include <ToolUtils.h>
48 #include <Resources.h>
50 #include <TextUtils.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
61 #endif /* not MAC_OSX */
75 #include "dispextern.h"
77 #include "termhooks.h"
84 #include "intervals.h"
85 #include "composite.h"
88 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
89 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
90 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
91 #define macShiftKey (shiftKey)
92 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
93 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
95 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
99 /* Non-nil means Emacs uses toolkit scroll bars. */
101 Lisp_Object Vx_toolkit_scroll_bars
;
103 /* Non-zero means that a HELP_EVENT has been generated since Emacs
106 static int any_help_event_p
;
108 /* Non-zero means autoselect window with the mouse cursor. */
110 int x_autoselect_window_p
;
112 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
114 int x_use_underline_position_properties
;
116 /* Non-zero means draw block and hollow cursor as wide as the glyph
117 under it. For example, if a block cursor is over a tab, it will be
118 drawn as wide as that tab on the display. */
121 /* This is a chain of structures for all the X displays currently in
124 struct x_display_info
*x_display_list
;
126 /* This is a list of cons cells, each of the form (NAME
127 . FONT-LIST-CACHE), one for each element of x_display_list and in
128 the same order. NAME is the name of the frame. FONT-LIST-CACHE
129 records previous values returned by x-list-fonts. */
131 Lisp_Object x_display_name_list
;
133 /* This is display since Mac does not support multiple ones. */
134 struct mac_display_info one_mac_display_info
;
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the XT functions.
138 It is zero while not inside an update. In that case, the XT
139 functions assume that `selected_frame' is the frame to apply to. */
141 extern struct frame
*updating_frame
;
143 extern int waiting_for_input
;
145 /* This is a frame waiting to be auto-raised, within XTread_socket. */
147 struct frame
*pending_autoraise_frame
;
149 /* Non-zero means user is interacting with a toolkit scroll bar. */
151 static int toolkit_scroll_bar_interaction
;
155 Formerly, we used PointerMotionHintMask (in standard_event_mask)
156 so that we would have to call XQueryPointer after each MotionNotify
157 event to ask for another such event. However, this made mouse tracking
158 slow, and there was a bug that made it eventually stop.
160 Simply asking for MotionNotify all the time seems to work better.
162 In order to avoid asking for motion events and then throwing most
163 of them away or busy-polling the server for mouse positions, we ask
164 the server for pointer motion hints. This means that we get only
165 one event per group of mouse movements. "Groups" are delimited by
166 other kinds of events (focus changes and button clicks, for
167 example), or by XQueryPointer calls; when one of these happens, we
168 get another MotionNotify event the next time the mouse moves. This
169 is at least as efficient as getting motion events when mouse
170 tracking is on, and I suspect only negligibly worse when tracking
173 /* Where the mouse was last time we reported a mouse event. */
175 static Rect last_mouse_glyph
;
176 static Lisp_Object last_mouse_press_frame
;
178 /* The scroll bar in which the last X motion event occurred.
180 If the last X motion event occurred in a scroll bar, we set this so
181 XTmouse_position can know whether to report a scroll bar motion or
184 If the last X motion event didn't occur in a scroll bar, we set
185 this to Qnil, to tell XTmouse_position to return an ordinary motion
188 static Lisp_Object last_mouse_scroll_bar
;
190 /* This is a hack. We would really prefer that XTmouse_position would
191 return the time associated with the position it returns, but there
192 doesn't seem to be any way to wrest the time-stamp from the server
193 along with the position query. So, we just keep track of the time
194 of the last movement we received, and return that in hopes that
195 it's somewhat accurate. */
197 static Time last_mouse_movement_time
;
199 struct scroll_bar
*tracked_scroll_bar
= NULL
;
201 /* Incremented by XTread_socket whenever it really tries to read
205 static int volatile input_signal_count
;
207 static int input_signal_count
;
210 /* Used locally within XTread_socket. */
212 static int x_noop_count
;
214 /* Initial values of argv and argc. */
216 extern char **initial_argv
;
217 extern int initial_argc
;
219 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
221 /* Tells if a window manager is present or not. */
223 extern Lisp_Object Vx_no_window_manager
;
227 /* A mask of extra modifier bits to put into every keyboard char. */
229 extern int extra_keyboard_modifiers
;
231 static Lisp_Object Qvendor_specific_keysyms
;
234 extern XrmDatabase x_load_resources
P_ ((Display
*, char *, char *, char *));
237 extern int inhibit_window_system
;
240 QDGlobals qd
; /* QuickDraw global information structure. */
244 struct frame
* x_window_to_frame (struct mac_display_info
*, WindowPtr
);
245 struct mac_display_info
*mac_display_info_for_display (Display
*);
246 static void x_update_window_end
P_ ((struct window
*, int, int));
247 static void mac_handle_tool_bar_click
P_ ((struct frame
*, EventRecord
*));
248 static int x_io_error_quitter
P_ ((Display
*));
249 int x_catch_errors
P_ ((Display
*));
250 void x_uncatch_errors
P_ ((Display
*, int));
251 void x_lower_frame
P_ ((struct frame
*));
252 void x_scroll_bar_clear
P_ ((struct frame
*));
253 int x_had_errors_p
P_ ((Display
*));
254 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
255 void x_raise_frame
P_ ((struct frame
*));
256 void x_set_window_size
P_ ((struct frame
*, int, int, int));
257 void x_wm_set_window_state
P_ ((struct frame
*, int));
258 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
259 void mac_initialize
P_ ((void));
260 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
261 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
262 static void x_update_end
P_ ((struct frame
*));
263 static void XTframe_up_to_date
P_ ((struct frame
*));
264 static void XTreassert_line_highlight
P_ ((int, int));
265 static void x_change_line_highlight
P_ ((int, int, int, int));
266 static void XTset_terminal_modes
P_ ((void));
267 static void XTreset_terminal_modes
P_ ((void));
268 static void x_clear_frame
P_ ((void));
269 static void frame_highlight
P_ ((struct frame
*));
270 static void frame_unhighlight
P_ ((struct frame
*));
271 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
272 static void XTframe_rehighlight
P_ ((struct frame
*));
273 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
274 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
275 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
276 enum text_cursor_kinds
));
278 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, GC
));
279 static void x_flush
P_ ((struct frame
*f
));
280 static void x_update_begin
P_ ((struct frame
*));
281 static void x_update_window_begin
P_ ((struct window
*));
282 static void x_after_update_window_line
P_ ((struct glyph_row
*));
284 void activate_scroll_bars (FRAME_PTR
);
285 void deactivate_scroll_bars (FRAME_PTR
);
287 static int is_emacs_window (WindowPtr
);
289 int x_bitmap_icon (struct frame
*, Lisp_Object
);
290 void x_make_frame_visible (struct frame
*);
292 extern void window_scroll (Lisp_Object
, int, int, int);
294 /* Defined in macmenu.h. */
295 extern void menubar_selection_callback (FRAME_PTR
, int);
296 extern void set_frame_menubar (FRAME_PTR
, int, int);
298 /* X display function emulation */
301 XFreePixmap (display
, pixmap
)
302 Display
*display
; /* not used */
305 DisposeGWorld (pixmap
);
309 /* Set foreground color for subsequent QuickDraw commands. Assume
310 graphic port has already been set. */
313 mac_set_forecolor (unsigned long color
)
317 fg_color
.red
= RED16_FROM_ULONG (color
);
318 fg_color
.green
= GREEN16_FROM_ULONG (color
);
319 fg_color
.blue
= BLUE16_FROM_ULONG (color
);
321 RGBForeColor (&fg_color
);
325 /* Set background color for subsequent QuickDraw commands. Assume
326 graphic port has already been set. */
329 mac_set_backcolor (unsigned long color
)
333 bg_color
.red
= RED16_FROM_ULONG (color
);
334 bg_color
.green
= GREEN16_FROM_ULONG (color
);
335 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
337 RGBBackColor (&bg_color
);
340 /* Set foreground and background color for subsequent QuickDraw
341 commands. Assume that the graphic port has already been set. */
344 mac_set_colors (GC gc
)
346 mac_set_forecolor (gc
->foreground
);
347 mac_set_backcolor (gc
->background
);
350 /* Mac version of XDrawLine. */
353 XDrawLine (display
, w
, gc
, x1
, y1
, x2
, y2
)
359 SetPortWindowPort (w
);
368 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
377 GetGWorld (&old_port
, &old_gdh
);
382 LockPixels (GetGWorldPixMap (p
));
385 UnlockPixels (GetGWorldPixMap (p
));
387 SetGWorld (old_port
, old_gdh
);
390 /* Mac version of XClearArea. */
393 XClearArea (display
, w
, x
, y
, width
, height
, exposures
)
397 unsigned int width
, height
;
400 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
404 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
405 xgc
.background
= mwp
->x_compatible
.background_pixel
;
407 SetPortWindowPort (w
);
409 mac_set_colors (&xgc
);
410 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
415 /* Mac version of XClearWindow. */
418 XClearWindow (display
, w
)
422 struct mac_output
*mwp
= (mac_output
*) GetWRefCon (w
);
425 xgc
.foreground
= mwp
->x_compatible
.foreground_pixel
;
426 xgc
.background
= mwp
->x_compatible
.background_pixel
;
428 SetPortWindowPort (w
);
430 mac_set_colors (&xgc
);
432 #if TARGET_API_MAC_CARBON
436 GetWindowPortBounds (w
, &r
);
439 #else /* not TARGET_API_MAC_CARBON */
440 EraseRect (&(w
->portRect
));
441 #endif /* not TARGET_API_MAC_CARBON */
445 /* Mac replacement for XCopyArea. */
448 mac_draw_bitmap (display
, w
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
452 int x
, y
, width
, height
;
453 unsigned short *bits
;
459 bitmap
.rowBytes
= sizeof(unsigned short);
460 bitmap
.baseAddr
= (char *)bits
;
461 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
463 SetPortWindowPort (w
);
466 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
468 #if TARGET_API_MAC_CARBON
469 LockPortBits (GetWindowPort (w
));
470 CopyBits (&bitmap
, GetPortBitMapForCopyBits (GetWindowPort (w
)),
471 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
472 UnlockPortBits (GetWindowPort (w
));
473 #else /* not TARGET_API_MAC_CARBON */
474 CopyBits (&bitmap
, &(w
->portBits
), &(bitmap
.bounds
), &r
,
475 overlay_p
? srcOr
: srcCopy
, 0);
476 #endif /* not TARGET_API_MAC_CARBON */
480 /* Mac replacement for XSetClipRectangles. */
483 mac_set_clip_rectangle (display
, w
, r
)
488 SetPortWindowPort (w
);
494 /* Mac replacement for XSetClipMask. */
497 mac_reset_clipping (display
, w
)
503 SetPortWindowPort (w
);
505 SetRect (&r
, -32767, -32767, 32767, 32767);
510 /* XBM bits seem to be backward within bytes compared with how
517 unsigned char reflected
= 0x00;
518 for (i
= 0; i
< 8; i
++)
520 if (orig
& (0x01 << i
))
521 reflected
|= 0x80 >> i
;
527 /* Mac replacement for XCreateBitmapFromBitmapData. */
530 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
538 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
539 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
540 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
541 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
542 for (i
= 0; i
< h
; i
++)
544 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
545 for (j
= 0; j
< w1
; j
++)
546 *p
++ = reflect_byte (*bits
++);
549 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
554 mac_free_bitmap (bitmap
)
557 xfree (bitmap
->baseAddr
);
562 XCreatePixmap (display
, w
, width
, height
, depth
)
563 Display
*display
; /* not used */
565 unsigned int width
, height
;
566 unsigned int depth
; /* not used */
572 SetPortWindowPort (w
);
574 SetRect (&r
, 0, 0, width
, height
);
575 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
583 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
584 Display
*display
; /* not used */
587 unsigned int width
, height
;
588 unsigned long fg
, bg
;
589 unsigned int depth
; /* not used */
596 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
600 GetGWorld (&old_port
, &old_gdh
);
601 SetGWorld (pixmap
, NULL
);
602 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
603 mac_set_forecolor (fg
);
604 mac_set_backcolor (bg
);
605 LockPixels (GetGWorldPixMap (pixmap
));
606 #if TARGET_API_MAC_CARBON
607 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
608 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
609 #else /* not TARGET_API_MAC_CARBON */
610 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
611 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
612 #endif /* not TARGET_API_MAC_CARBON */
613 UnlockPixels (GetGWorldPixMap (pixmap
));
614 SetGWorld (old_port
, old_gdh
);
615 mac_free_bitmap (&bitmap
);
621 /* Mac replacement for XFillRectangle. */
624 XFillRectangle (display
, w
, gc
, x
, y
, width
, height
)
629 unsigned int width
, height
;
633 SetPortWindowPort (w
);
636 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
638 PaintRect (&r
); /* using foreground color of gc */
643 mac_fill_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
648 unsigned int width
, height
;
654 GetGWorld (&old_port
, &old_gdh
);
657 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
659 LockPixels (GetGWorldPixMap (p
));
660 PaintRect (&r
); /* using foreground color of gc */
661 UnlockPixels (GetGWorldPixMap (p
));
663 SetGWorld (old_port
, old_gdh
);
667 /* Mac replacement for XDrawRectangle: dest is a window. */
670 mac_draw_rectangle (display
, w
, gc
, x
, y
, width
, height
)
675 unsigned int width
, height
;
679 SetPortWindowPort (w
);
682 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
684 FrameRect (&r
); /* using foreground color of gc */
688 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
691 mac_draw_rectangle_to_pixmap (display
, p
, gc
, x
, y
, width
, height
)
696 unsigned int width
, height
;
702 GetGWorld (&old_port
, &old_gdh
);
705 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
707 LockPixels (GetGWorldPixMap (p
));
708 FrameRect (&r
); /* using foreground color of gc */
709 UnlockPixels (GetGWorldPixMap (p
));
711 SetGWorld (old_port
, old_gdh
);
716 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, mode
,
723 int nchars
, mode
, bytes_per_char
;
725 SetPortWindowPort (w
);
729 TextFont (gc
->font
->mac_fontnum
);
730 TextSize (gc
->font
->mac_fontsize
);
731 TextFace (gc
->font
->mac_fontface
);
735 DrawText (buf
, 0, nchars
* bytes_per_char
);
739 /* Mac replacement for XDrawString. */
742 XDrawString (display
, w
, gc
, x
, y
, buf
, nchars
)
750 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
754 /* Mac replacement for XDrawString16. */
757 XDrawString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
765 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
,
770 /* Mac replacement for XDrawImageString. */
773 XDrawImageString (display
, w
, gc
, x
, y
, buf
, nchars
)
781 mac_draw_string_common (display
, w
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
785 /* Mac replacement for XDrawString16. */
788 XDrawImageString16 (display
, w
, gc
, x
, y
, buf
, nchars
)
796 mac_draw_string_common (display
, w
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
,
801 /* Mac replacement for XCopyArea: dest must be window. */
804 mac_copy_area (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
, dest_x
,
811 unsigned int width
, height
;
816 SetPortWindowPort (dest
);
818 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
819 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
821 ForeColor (blackColor
);
822 BackColor (whiteColor
);
824 LockPixels (GetGWorldPixMap (src
));
825 #if TARGET_API_MAC_CARBON
826 LockPortBits (GetWindowPort (dest
));
827 CopyBits (GetPortBitMapForCopyBits (src
),
828 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
829 &src_r
, &dest_r
, srcCopy
, 0);
830 UnlockPortBits (GetWindowPort (dest
));
831 #else /* not TARGET_API_MAC_CARBON */
832 CopyBits (&(((GrafPtr
)src
)->portBits
), &(dest
->portBits
),
833 &src_r
, &dest_r
, srcCopy
, 0);
834 #endif /* not TARGET_API_MAC_CARBON */
835 UnlockPixels (GetGWorldPixMap (src
));
840 mac_copy_area_with_mask (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
841 width
, height
, dest_x
, dest_y
)
847 unsigned int width
, height
;
852 SetPortWindowPort (dest
);
854 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
855 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
857 ForeColor (blackColor
);
858 BackColor (whiteColor
);
860 LockPixels (GetGWorldPixMap (src
));
861 LockPixels (GetGWorldPixMap (mask
));
862 #if TARGET_API_MAC_CARBON
863 LockPortBits (GetWindowPort (dest
));
864 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
865 GetPortBitMapForCopyBits (GetWindowPort (dest
)),
866 &src_r
, &src_r
, &dest_r
);
867 UnlockPortBits (GetWindowPort (dest
));
868 #else /* not TARGET_API_MAC_CARBON */
869 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
870 &(dest
->portBits
), &src_r
, &src_r
, &dest_r
);
871 #endif /* not TARGET_API_MAC_CARBON */
872 UnlockPixels (GetGWorldPixMap (mask
));
873 UnlockPixels (GetGWorldPixMap (src
));
878 /* Convert a pair of local coordinates to global (screen) coordinates.
879 Assume graphic port has been properly set. */
881 local_to_global_coord (short *h
, short *v
)
895 /* Mac replacement for XCopyArea: used only for scrolling. */
898 mac_scroll_area (display
, w
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
903 unsigned int width
, height
;
906 #if TARGET_API_MAC_CARBON
907 Rect gw_r
, src_r
, dest_r
;
909 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
910 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
912 SetPortWindowPort (w
);
914 ForeColor (blackColor
);
915 BackColor (whiteColor
);
917 LockPortBits (GetWindowPort (w
));
919 const BitMap
*bitmap
= GetPortBitMapForCopyBits (GetWindowPort (w
));
920 CopyBits (bitmap
, bitmap
, &src_r
, &dest_r
, srcCopy
, 0);
922 UnlockPortBits (GetWindowPort (w
));
925 #else /* not TARGET_API_MAC_CARBON */
933 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
934 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
937 /* Need to use global coordinates and screenBits since src and dest
938 areas overlap in general. */
939 local_to_global_coord (&src_r
.left
, &src_r
.top
);
940 local_to_global_coord (&src_r
.right
, &src_r
.bottom
);
941 local_to_global_coord (&dest_r
.left
, &dest_r
.top
);
942 local_to_global_coord (&dest_r
.right
, &dest_r
.bottom
);
944 CopyBits (&qd
.screenBits
, &qd
.screenBits
, &src_r
, &dest_r
, srcCopy
, 0);
946 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
947 color mapping in CopyBits. Otherwise, it will be slow. */
948 ForeColor (blackColor
);
949 BackColor (whiteColor
);
950 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
954 #endif /* not TARGET_API_MAC_CARBON */
958 /* Mac replacement for XCopyArea: dest must be Pixmap. */
961 mac_copy_area_to_pixmap (display
, src
, dest
, gc
, src_x
, src_y
, width
, height
,
967 unsigned int width
, height
;
974 GetGWorld (&old_port
, &old_gdh
);
975 SetGWorld (dest
, NULL
);
976 ForeColor (blackColor
);
977 BackColor (whiteColor
);
979 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
980 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
982 LockPixels (GetGWorldPixMap (src
));
983 LockPixels (GetGWorldPixMap (dest
));
984 #if TARGET_API_MAC_CARBON
985 CopyBits (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (dest
),
986 &src_r
, &dest_r
, srcCopy
, 0);
987 #else /* not TARGET_API_MAC_CARBON */
988 CopyBits (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)dest
)->portBits
),
989 &src_r
, &dest_r
, srcCopy
, 0);
990 #endif /* not TARGET_API_MAC_CARBON */
991 UnlockPixels (GetGWorldPixMap (dest
));
992 UnlockPixels (GetGWorldPixMap (src
));
994 SetGWorld (old_port
, old_gdh
);
999 mac_copy_area_with_mask_to_pixmap (display
, src
, mask
, dest
, gc
, src_x
, src_y
,
1000 width
, height
, dest_x
, dest_y
)
1002 Pixmap src
, mask
, dest
;
1005 unsigned int width
, height
;
1012 GetGWorld (&old_port
, &old_gdh
);
1013 SetGWorld (dest
, NULL
);
1014 ForeColor (blackColor
);
1015 BackColor (whiteColor
);
1017 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1018 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1020 LockPixels (GetGWorldPixMap (src
));
1021 LockPixels (GetGWorldPixMap (mask
));
1022 LockPixels (GetGWorldPixMap (dest
));
1023 #if TARGET_API_MAC_CARBON
1024 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1025 GetPortBitMapForCopyBits (dest
), &src_r
, &src_r
, &dest_r
);
1026 #else /* not TARGET_API_MAC_CARBON */
1027 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1028 &(((GrafPtr
)dest
)->portBits
), &src_r
, &src_r
, &dest_r
);
1029 #endif /* not TARGET_API_MAC_CARBON */
1030 UnlockPixels (GetGWorldPixMap (dest
));
1031 UnlockPixels (GetGWorldPixMap (mask
));
1032 UnlockPixels (GetGWorldPixMap (src
));
1034 SetGWorld (old_port
, old_gdh
);
1038 /* Mac replacement for XChangeGC. */
1041 XChangeGC (void * ignore
, XGCValues
* gc
, unsigned long mask
,
1044 if (mask
& GCForeground
)
1045 gc
->foreground
= xgcv
->foreground
;
1046 if (mask
& GCBackground
)
1047 gc
->background
= xgcv
->background
;
1049 gc
->font
= xgcv
->font
;
1053 /* Mac replacement for XCreateGC. */
1056 XCreateGC (void * ignore
, Window window
, unsigned long mask
,
1059 XGCValues
*gc
= (XGCValues
*) xmalloc (sizeof (XGCValues
));
1060 bzero (gc
, sizeof (XGCValues
));
1062 XChangeGC (ignore
, gc
, mask
, xgcv
);
1068 /* Used in xfaces.c. */
1071 XFreeGC (display
, gc
)
1079 /* Mac replacement for XGetGCValues. */
1082 XGetGCValues (void* ignore
, XGCValues
*gc
,
1083 unsigned long mask
, XGCValues
*xgcv
)
1085 XChangeGC (ignore
, xgcv
, mask
, gc
);
1089 /* Mac replacement for XSetForeground. */
1092 XSetForeground (display
, gc
, color
)
1095 unsigned long color
;
1097 gc
->foreground
= color
;
1101 /* Mac replacement for XSetFont. */
1104 XSetFont (display
, gc
, font
)
1114 XTextExtents16 (XFontStruct
*font
, XChar2b
*text
, int nchars
,
1115 int *direction
,int *font_ascent
,
1116 int *font_descent
, XCharStruct
*cs
)
1118 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1122 /* x_sync is a no-op on Mac. */
1130 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1131 Calls to XFlush should be unnecessary because the X output buffer
1132 is flushed automatically as needed by calls to XPending,
1133 XNextEvent, or XWindowEvent according to the XFlush man page.
1134 XTread_socket calls XPending. Removing XFlush improves
1137 #if TARGET_API_MAC_CARBON
1138 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1140 #define XFlush(DISPLAY) (void) 0
1143 /* Flush display of frame F, or of all frames if F is null. */
1149 #if TARGET_API_MAC_CARBON
1153 Lisp_Object rest
, frame
;
1154 FOR_EACH_FRAME (rest
, frame
)
1155 x_flush (XFRAME (frame
));
1157 else if (FRAME_MAC_P (f
))
1158 XFlush (FRAME_MAC_DISPLAY (f
));
1160 #endif /* TARGET_API_MAC_CARBON */
1165 /* Return the struct mac_display_info corresponding to DPY. There's
1168 struct mac_display_info
*
1169 mac_display_info_for_display (dpy
)
1172 return &one_mac_display_info
;
1177 /***********************************************************************
1178 Starting and ending an update
1179 ***********************************************************************/
1181 /* Start an update of frame F. This function is installed as a hook
1182 for update_begin, i.e. it is called when update_begin is called.
1183 This function is called prior to calls to x_update_window_begin for
1184 each window being updated. */
1190 /* Nothing to do. */
1194 /* Start update of window W. Set the global variable updated_window
1195 to the window being updated and set output_cursor to the cursor
1199 x_update_window_begin (w
)
1202 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1203 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1206 set_output_cursor (&w
->cursor
);
1210 if (f
== display_info
->mouse_face_mouse_frame
)
1212 /* Don't do highlighting for mouse motion during the update. */
1213 display_info
->mouse_face_defer
= 1;
1215 /* If F needs to be redrawn, simply forget about any prior mouse
1217 if (FRAME_GARBAGED_P (f
))
1218 display_info
->mouse_face_window
= Qnil
;
1220 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1221 their mouse_face_p flag set, which means that they are always
1222 unequal to rows in a desired matrix which never have that
1223 flag set. So, rows containing mouse-face glyphs are never
1224 scrolled, and we don't have to switch the mouse highlight off
1225 here to prevent it from being scrolled. */
1227 /* Can we tell that this update does not affect the window
1228 where the mouse highlight is? If so, no need to turn off.
1229 Likewise, don't do anything if the frame is garbaged;
1230 in that case, the frame's current matrix that we would use
1231 is all wrong, and we will redisplay that line anyway. */
1232 if (!NILP (display_info
->mouse_face_window
)
1233 && w
== XWINDOW (display_info
->mouse_face_window
))
1237 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1238 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1241 if (i
< w
->desired_matrix
->nrows
)
1242 clear_mouse_face (display_info
);
1251 /* Draw a vertical window border from (x,y0) to (x,y1) */
1254 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1258 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1260 XDrawLine (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1261 f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1265 /* End update of window W (which is equal to updated_window).
1267 Draw vertical borders between horizontally adjacent windows, and
1268 display W's cursor if CURSOR_ON_P is non-zero.
1270 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1271 glyphs in mouse-face were overwritten. In that case we have to
1272 make sure that the mouse-highlight is properly redrawn.
1274 W may be a menu bar pseudo-window in case we don't have X toolkit
1275 support. Such windows don't have a cursor, so don't display it
1279 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1281 int cursor_on_p
, mouse_face_overwritten_p
;
1283 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1285 if (!w
->pseudo_window_p
)
1290 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1292 output_cursor
.x
, output_cursor
.y
);
1294 x_draw_vertical_border (w
);
1296 draw_window_fringes (w
);
1301 /* If a row with mouse-face was overwritten, arrange for
1302 XTframe_up_to_date to redisplay the mouse highlight. */
1303 if (mouse_face_overwritten_p
)
1305 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1306 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1307 dpyinfo
->mouse_face_window
= Qnil
;
1311 /* Unhide the caret. This won't actually show the cursor, unless it
1312 was visible before the corresponding call to HideCaret in
1313 x_update_window_begin. */
1314 if (w32_use_visible_system_caret
)
1315 SendMessage (w32_system_caret_hwnd
, WM_EMACS_SHOW_CARET
, 0, 0);
1318 updated_window
= NULL
;
1322 /* End update of frame F. This function is installed as a hook in
1329 /* Mouse highlight may be displayed again. */
1330 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1333 /* Reset the background color of Mac OS Window to that of the frame after
1334 update so that it is used by Mac Toolbox to clear the update region before
1335 an update event is generated. */
1336 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1338 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f
));
1340 XFlush (FRAME_MAC_DISPLAY (f
));
1345 /* This function is called from various places in xdisp.c whenever a
1346 complete update has been performed. The global variable
1347 updated_window is not available here. */
1350 XTframe_up_to_date (f
)
1353 if (FRAME_MAC_P (f
))
1355 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1357 if (dpyinfo
->mouse_face_deferred_gc
1358 || f
== dpyinfo
->mouse_face_mouse_frame
)
1361 if (dpyinfo
->mouse_face_mouse_frame
)
1362 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1363 dpyinfo
->mouse_face_mouse_x
,
1364 dpyinfo
->mouse_face_mouse_y
);
1365 dpyinfo
->mouse_face_deferred_gc
= 0;
1372 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1373 arrow bitmaps, or clear the fringes if no bitmaps are required
1374 before DESIRED_ROW is made current. The window being updated is
1375 found in updated_window. This function is called from
1376 update_window_line only if it is known that there are differences
1377 between bitmaps to be drawn between current row and DESIRED_ROW. */
1380 x_after_update_window_line (desired_row
)
1381 struct glyph_row
*desired_row
;
1383 struct window
*w
= updated_window
;
1389 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1390 desired_row
->redraw_fringe_bitmaps_p
= 1;
1392 /* When a window has disappeared, make sure that no rest of
1393 full-width rows stays visible in the internal border. Could
1394 check here if updated_window is the leftmost/rightmost window,
1395 but I guess it's not worth doing since vertically split windows
1396 are almost never used, internal border is rarely set, and the
1397 overhead is very small. */
1398 if (windows_or_buffers_changed
1399 && desired_row
->full_width_p
1400 && (f
= XFRAME (w
->frame
),
1401 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1403 && (height
= desired_row
->visible_height
,
1406 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1407 /* Internal border is drawn below the tool bar. */
1408 if (WINDOWP (f
->tool_bar_window
)
1409 && w
== XWINDOW (f
->tool_bar_window
))
1414 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1415 0, y
, width
, height
, 0);
1416 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1417 FRAME_PIXEL_WIDTH (f
) - width
, y
,
1425 /* Draw the bitmap WHICH in one of the left or right fringes of
1426 window W. ROW is the glyph row for which to display the bitmap; it
1427 determines the vertical position at which the bitmap has to be
1431 x_draw_fringe_bitmap (w
, row
, p
)
1433 struct glyph_row
*row
;
1434 struct draw_fringe_bitmap_params
*p
;
1436 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1437 Display
*display
= FRAME_MAC_DISPLAY (f
);
1438 WindowPtr window
= FRAME_MAC_WINDOW (f
);
1440 GC gc
= f
->output_data
.mac
->normal_gc
;
1441 struct face
*face
= p
->face
;
1444 /* Must clip because of partially visible lines. */
1445 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1448 /* Adjust position of "bottom aligned" bitmap on partially
1449 visible last row. */
1451 int oldVH
= row
->visible_height
;
1452 row
->visible_height
= p
->h
;
1453 row
->y
-= rowY
- p
->y
;
1454 x_clip_to_row (w
, row
, gc
);
1456 row
->visible_height
= oldVH
;
1459 x_clip_to_row (w
, row
, gc
);
1461 if (p
->bx
>= 0 && !p
->overlay_p
)
1464 gcv
.foreground
= face
->background
;
1466 #if 0 /* MAC_TODO: stipple */
1467 /* In case the same realized face is used for fringes and
1468 for something displayed in the text (e.g. face `region' on
1469 mono-displays, the fill style may have been changed to
1470 FillSolid in x_draw_glyph_string_background. */
1472 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1474 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1477 XFillRectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
1479 p
->bx
, p
->by
, p
->nx
, p
->ny
);
1481 #if 0 /* MAC_TODO: stipple */
1483 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1489 unsigned short *bits
= p
->bits
+ p
->dh
;
1491 gcv
.foreground
= (p
->cursor_p
1492 ? (p
->overlay_p
? face
->background
1493 : f
->output_data
.mac
->cursor_pixel
)
1494 : face
->foreground
);
1495 gcv
.background
= face
->background
;
1497 mac_draw_bitmap (display
, window
, &gcv
, p
->x
, p
->y
,
1498 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1501 mac_reset_clipping (display
, window
);
1505 /* This is called when starting Emacs and when restarting after
1506 suspend. When starting Emacs, no window is mapped. And nothing
1507 must be done to Emacs's own window if it is suspended (though that
1511 XTset_terminal_modes ()
1515 /* This is called when exiting or suspending Emacs. Exiting will make
1516 the windows go away, and suspending requires no action. */
1519 XTreset_terminal_modes ()
1524 /***********************************************************************
1526 ***********************************************************************/
1528 /* Function prototypes of this page. */
1530 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1531 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1534 /* Return a pointer to per-char metric information in FONT of a
1535 character pointed by B which is a pointer to an XChar2b. */
1537 #define PER_CHAR_METRIC(font, b) \
1539 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1540 + (((font)->min_byte1 || (font)->max_byte1) \
1541 ? (((b)->byte1 - (font)->min_byte1) \
1542 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1544 : &((font)->max_bounds))
1547 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1548 is not contained in the font. */
1550 static INLINE XCharStruct
*
1551 x_per_char_metric (font
, char2b
)
1555 /* The result metric information. */
1556 XCharStruct
*pcm
= NULL
;
1558 xassert (font
&& char2b
);
1560 if (font
->per_char
!= NULL
)
1562 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1564 /* min_char_or_byte2 specifies the linear character index
1565 corresponding to the first element of the per_char array,
1566 max_char_or_byte2 is the index of the last character. A
1567 character with non-zero CHAR2B->byte1 is not in the font.
1568 A character with byte2 less than min_char_or_byte2 or
1569 greater max_char_or_byte2 is not in the font. */
1570 if (char2b
->byte1
== 0
1571 && char2b
->byte2
>= font
->min_char_or_byte2
1572 && char2b
->byte2
<= font
->max_char_or_byte2
)
1573 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1577 /* If either min_byte1 or max_byte1 are nonzero, both
1578 min_char_or_byte2 and max_char_or_byte2 are less than
1579 256, and the 2-byte character index values corresponding
1580 to the per_char array element N (counting from 0) are:
1582 byte1 = N/D + min_byte1
1583 byte2 = N\D + min_char_or_byte2
1587 D = max_char_or_byte2 - min_char_or_byte2 + 1
1588 / = integer division
1589 \ = integer modulus */
1590 if (char2b
->byte1
>= font
->min_byte1
1591 && char2b
->byte1
<= font
->max_byte1
1592 && char2b
->byte2
>= font
->min_char_or_byte2
1593 && char2b
->byte2
<= font
->max_char_or_byte2
)
1595 pcm
= (font
->per_char
1596 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1597 * (char2b
->byte1
- font
->min_byte1
))
1598 + (char2b
->byte2
- font
->min_char_or_byte2
));
1604 /* If the per_char pointer is null, all glyphs between the first
1605 and last character indexes inclusive have the same
1606 information, as given by both min_bounds and max_bounds. */
1607 if (char2b
->byte2
>= font
->min_char_or_byte2
1608 && char2b
->byte2
<= font
->max_char_or_byte2
)
1609 pcm
= &font
->max_bounds
;
1612 return ((pcm
== NULL
1613 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1620 static XCharStruct
*
1621 mac_per_char_metric (font
, char2b
, font_type
)
1626 return x_per_char_metric (font
, char2b
);
1630 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1631 the two-byte form of C. Encoding is returned in *CHAR2B. */
1634 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1637 struct font_info
*font_info
;
1640 int charset
= CHAR_CHARSET (c
);
1641 XFontStruct
*font
= font_info
->font
;
1643 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1644 This may be either a program in a special encoder language or a
1646 if (font_info
->font_encoder
)
1648 /* It's a program. */
1649 struct ccl_program
*ccl
= font_info
->font_encoder
;
1651 if (CHARSET_DIMENSION (charset
) == 1)
1653 ccl
->reg
[0] = charset
;
1654 ccl
->reg
[1] = char2b
->byte2
;
1658 ccl
->reg
[0] = charset
;
1659 ccl
->reg
[1] = char2b
->byte1
;
1660 ccl
->reg
[2] = char2b
->byte2
;
1663 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1665 /* We assume that MSBs are appropriately set/reset by CCL
1667 if (font
->max_byte1
== 0) /* 1-byte font */
1668 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1670 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1672 else if (font_info
->encoding
[charset
])
1674 /* Fixed encoding scheme. See fontset.h for the meaning of the
1675 encoding numbers. */
1676 int enc
= font_info
->encoding
[charset
];
1678 if ((enc
== 1 || enc
== 2)
1679 && CHARSET_DIMENSION (charset
) == 2)
1680 char2b
->byte1
|= 0x80;
1682 if (enc
== 1 || enc
== 3)
1683 char2b
->byte2
|= 0x80;
1689 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1690 char2b
->byte1
= sjis1
;
1691 char2b
->byte2
= sjis2
;
1696 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1698 return FONT_TYPE_UNKNOWN
;
1703 /***********************************************************************
1705 ***********************************************************************/
1708 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1709 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1710 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1712 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1713 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1714 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1715 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1716 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1717 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1718 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1719 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1720 unsigned long *, double, int));*/
1721 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1722 double, int, unsigned long));
1723 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1724 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1725 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1726 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1727 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1728 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1730 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1731 int, int, int, int, int, int,
1733 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1734 int, int, int, Rect
*));
1737 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1741 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1746 struct glyph_string
*s
;
1748 if (s
->font
== FRAME_FONT (s
->f
)
1749 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1750 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1752 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1755 /* Cursor on non-default face: must merge. */
1759 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1760 xgcv
.foreground
= s
->face
->background
;
1762 /* If the glyph would be invisible, try a different foreground. */
1763 if (xgcv
.foreground
== xgcv
.background
)
1764 xgcv
.foreground
= s
->face
->foreground
;
1765 if (xgcv
.foreground
== xgcv
.background
)
1766 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1767 if (xgcv
.foreground
== xgcv
.background
)
1768 xgcv
.foreground
= s
->face
->foreground
;
1770 /* Make sure the cursor is distinct from text in this face. */
1771 if (xgcv
.background
== s
->face
->background
1772 && xgcv
.foreground
== s
->face
->foreground
)
1774 xgcv
.background
= s
->face
->foreground
;
1775 xgcv
.foreground
= s
->face
->background
;
1778 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1779 xgcv
.font
= s
->font
;
1780 mask
= GCForeground
| GCBackground
| GCFont
;
1782 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1783 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1786 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1787 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1789 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1794 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1797 x_set_mouse_face_gc (s
)
1798 struct glyph_string
*s
;
1803 /* What face has to be used last for the mouse face? */
1804 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1805 face
= FACE_FROM_ID (s
->f
, face_id
);
1807 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1809 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1810 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1812 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1813 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1814 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1816 /* If font in this face is same as S->font, use it. */
1817 if (s
->font
== s
->face
->font
)
1818 s
->gc
= s
->face
->gc
;
1821 /* Otherwise construct scratch_cursor_gc with values from FACE
1826 xgcv
.background
= s
->face
->background
;
1827 xgcv
.foreground
= s
->face
->foreground
;
1828 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1829 xgcv
.font
= s
->font
;
1830 mask
= GCForeground
| GCBackground
| GCFont
;
1832 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1833 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1836 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1837 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1839 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1842 xassert (s
->gc
!= 0);
1846 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1847 Faces to use in the mode line have already been computed when the
1848 matrix was built, so there isn't much to do, here. */
1851 x_set_mode_line_face_gc (s
)
1852 struct glyph_string
*s
;
1854 s
->gc
= s
->face
->gc
;
1858 /* Set S->gc of glyph string S for drawing that glyph string. Set
1859 S->stippled_p to a non-zero value if the face of S has a stipple
1863 x_set_glyph_string_gc (s
)
1864 struct glyph_string
*s
;
1866 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1868 if (s
->hl
== DRAW_NORMAL_TEXT
)
1870 s
->gc
= s
->face
->gc
;
1871 s
->stippled_p
= s
->face
->stipple
!= 0;
1873 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
1875 x_set_mode_line_face_gc (s
);
1876 s
->stippled_p
= s
->face
->stipple
!= 0;
1878 else if (s
->hl
== DRAW_CURSOR
)
1880 x_set_cursor_gc (s
);
1883 else if (s
->hl
== DRAW_MOUSE_FACE
)
1885 x_set_mouse_face_gc (s
);
1886 s
->stippled_p
= s
->face
->stipple
!= 0;
1888 else if (s
->hl
== DRAW_IMAGE_RAISED
1889 || s
->hl
== DRAW_IMAGE_SUNKEN
)
1891 s
->gc
= s
->face
->gc
;
1892 s
->stippled_p
= s
->face
->stipple
!= 0;
1896 s
->gc
= s
->face
->gc
;
1897 s
->stippled_p
= s
->face
->stipple
!= 0;
1900 /* GC must have been set. */
1901 xassert (s
->gc
!= 0);
1905 /* Set clipping for output of glyph string S. S may be part of a mode
1906 line or menu if we don't have X toolkit support. */
1909 x_set_glyph_string_clipping (s
)
1910 struct glyph_string
*s
;
1913 get_glyph_string_clip_rect (s
, &r
);
1914 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
1919 Compute left and right overhang of glyph string S. If S is a glyph
1920 string for a composition, assume overhangs don't exist. */
1923 mac_compute_glyph_string_overhangs (s
)
1924 struct glyph_string
*s
;
1927 /* MAC_TODO: XTextExtents16 does nothing yet... */
1930 && s
->first_glyph
->type
== CHAR_GLYPH
)
1933 int direction
, font_ascent
, font_descent
;
1934 XTextExtents16 (s
->font
, s
->char2b
, s
->nchars
, &direction
,
1935 &font_ascent
, &font_descent
, &cs
);
1936 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
1937 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
1943 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
1946 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
1947 struct glyph_string
*s
;
1952 xgcv
.foreground
= s
->gc
->background
;
1953 XFillRectangle (s
->display
, s
->window
, &xgcv
, x
, y
, w
, h
);
1957 /* Draw the background of glyph_string S. If S->background_filled_p
1958 is non-zero don't draw it. FORCE_P non-zero means draw the
1959 background even if it wouldn't be drawn normally. This is used
1960 when a string preceding S draws into the background of S, or S
1961 contains the first component of a composition. */
1964 x_draw_glyph_string_background (s
, force_p
)
1965 struct glyph_string
*s
;
1968 /* Nothing to do if background has already been drawn or if it
1969 shouldn't be drawn in the first place. */
1970 if (!s
->background_filled_p
)
1972 int box_line_width
= max (s
->face
->box_line_width
, 0);
1974 #if 0 /* MAC_TODO: stipple */
1977 /* Fill background with a stipple pattern. */
1978 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
1979 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
1980 s
->y
+ box_line_width
,
1981 s
->background_width
,
1982 s
->height
- 2 * box_line_width
);
1983 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
1984 s
->background_filled_p
= 1;
1988 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
1989 || s
->font_not_found_p
1990 || s
->extends_to_end_of_line_p
1993 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
1994 s
->background_width
,
1995 s
->height
- 2 * box_line_width
);
1996 s
->background_filled_p
= 1;
2002 /* Draw the foreground of glyph string S. */
2005 x_draw_glyph_string_foreground (s
)
2006 struct glyph_string
*s
;
2010 /* If first glyph of S has a left box line, start drawing the text
2011 of S to the right of that box line. */
2012 if (s
->face
->box
!= FACE_NO_BOX
2013 && s
->first_glyph
->left_box_line_p
)
2014 x
= s
->x
+ abs (s
->face
->box_line_width
);
2018 /* Draw characters of S as rectangles if S's font could not be
2020 if (s
->font_not_found_p
)
2022 for (i
= 0; i
< s
->nchars
; ++i
)
2024 struct glyph
*g
= s
->first_glyph
+ i
;
2025 mac_draw_rectangle (s
->display
, s
->window
,
2026 s
->gc
, x
, s
->y
, g
->pixel_width
- 1,
2028 x
+= g
->pixel_width
;
2033 char *char1b
= (char *) s
->char2b
;
2034 int boff
= s
->font_info
->baseline_offset
;
2036 if (s
->font_info
->vertical_centering
)
2037 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2039 /* If we can use 8-bit functions, condense S->char2b. */
2041 for (i
= 0; i
< s
->nchars
; ++i
)
2042 char1b
[i
] = s
->char2b
[i
].byte2
;
2044 /* Draw text with XDrawString if background has already been
2045 filled. Otherwise, use XDrawImageString. (Note that
2046 XDrawImageString is usually faster than XDrawString.) Always
2047 use XDrawImageString when drawing the cursor so that there is
2048 no chance that characters under a box cursor are invisible. */
2049 if (s
->for_overlaps_p
2050 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2052 /* Draw characters with 16-bit or 8-bit functions. */
2054 XDrawString16 (s
->display
, s
->window
, s
->gc
, x
,
2055 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2057 XDrawString (s
->display
, s
->window
, s
->gc
, x
,
2058 s
->ybase
- boff
, char1b
, s
->nchars
);
2063 XDrawImageString16 (s
->display
, s
->window
, s
->gc
, x
,
2064 s
->ybase
- boff
, s
->char2b
, s
->nchars
);
2066 XDrawImageString (s
->display
, s
->window
, s
->gc
, x
,
2067 s
->ybase
- boff
, char1b
, s
->nchars
);
2072 /* Draw the foreground of composite glyph string S. */
2075 x_draw_composite_glyph_string_foreground (s
)
2076 struct glyph_string
*s
;
2080 /* If first glyph of S has a left box line, start drawing the text
2081 of S to the right of that box line. */
2082 if (s
->face
->box
!= FACE_NO_BOX
2083 && s
->first_glyph
->left_box_line_p
)
2084 x
= s
->x
+ abs (s
->face
->box_line_width
);
2088 /* S is a glyph string for a composition. S->gidx is the index of
2089 the first character drawn for glyphs of this composition.
2090 S->gidx == 0 means we are drawing the very first character of
2091 this composition. */
2093 /* Draw a rectangle for the composition if the font for the very
2094 first character of the composition could not be loaded. */
2095 if (s
->font_not_found_p
)
2098 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, s
->y
,
2099 s
->width
- 1, s
->height
- 1);
2103 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2104 XDrawString16 (s
->display
, s
->window
, s
->gc
,
2105 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2106 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2112 #ifdef USE_X_TOOLKIT
2114 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2117 /* Return the frame on which widget WIDGET is used.. Abort if frame
2118 cannot be determined. */
2120 static struct frame
*
2121 x_frame_of_widget (widget
)
2124 struct x_display_info
*dpyinfo
;
2128 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2130 /* Find the top-level shell of the widget. Note that this function
2131 can be called when the widget is not yet realized, so XtWindow
2132 (widget) == 0. That's the reason we can't simply use
2133 x_any_window_to_frame. */
2134 while (!XtIsTopLevelShell (widget
))
2135 widget
= XtParent (widget
);
2137 /* Look for a frame with that top-level widget. Allocate the color
2138 on that frame to get the right gamma correction value. */
2139 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2140 if (GC_FRAMEP (XCAR (tail
))
2141 && (f
= XFRAME (XCAR (tail
)),
2142 (f
->output_data
.nothing
!= 1
2143 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2144 && f
->output_data
.x
->widget
== widget
)
2151 /* Allocate the color COLOR->pixel on the screen and display of
2152 widget WIDGET in colormap CMAP. If an exact match cannot be
2153 allocated, try the nearest color available. Value is non-zero
2154 if successful. This is called from lwlib. */
2157 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2162 struct frame
*f
= x_frame_of_widget (widget
);
2163 return x_alloc_nearest_color (f
, cmap
, color
);
2167 #endif /* USE_X_TOOLKIT */
2169 #if 0 /* MAC_TODO */
2171 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2172 CMAP. If an exact match can't be allocated, try the nearest color
2173 available. Value is non-zero if successful. Set *COLOR to the
2177 x_alloc_nearest_color (f
, cmap
, color
)
2182 Display
*display
= FRAME_X_DISPLAY (f
);
2183 Screen
*screen
= FRAME_X_SCREEN (f
);
2186 gamma_correct (f
, color
);
2187 rc
= XAllocColor (display
, cmap
, color
);
2190 /* If we got to this point, the colormap is full, so we're going
2191 to try to get the next closest color. The algorithm used is
2192 a least-squares matching, which is what X uses for closest
2193 color matching with StaticColor visuals. */
2195 unsigned long nearest_delta
= ~0;
2196 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2197 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2199 for (i
= 0; i
< ncells
; ++i
)
2201 XQueryColors (display
, cmap
, cells
, ncells
);
2203 for (nearest
= i
= 0; i
< ncells
; ++i
)
2205 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2206 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2207 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2208 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2210 if (delta
< nearest_delta
)
2213 nearest_delta
= delta
;
2217 color
->red
= cells
[nearest
].red
;
2218 color
->green
= cells
[nearest
].green
;
2219 color
->blue
= cells
[nearest
].blue
;
2220 rc
= XAllocColor (display
, cmap
, color
);
2223 #ifdef DEBUG_X_COLORS
2225 register_color (color
->pixel
);
2226 #endif /* DEBUG_X_COLORS */
2232 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2233 It's necessary to do this instead of just using PIXEL directly to
2234 get color reference counts right. */
2237 x_copy_color (f
, pixel
)
2239 unsigned long pixel
;
2243 color
.pixel
= pixel
;
2245 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2246 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2248 #ifdef DEBUG_X_COLORS
2249 register_color (pixel
);
2255 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2256 It's necessary to do this instead of just using PIXEL directly to
2257 get color reference counts right. */
2260 x_copy_dpy_color (dpy
, cmap
, pixel
)
2263 unsigned long pixel
;
2267 color
.pixel
= pixel
;
2269 XQueryColor (dpy
, cmap
, &color
);
2270 XAllocColor (dpy
, cmap
, &color
);
2272 #ifdef DEBUG_X_COLORS
2273 register_color (pixel
);
2278 #endif /* MAC_TODO */
2281 /* Brightness beyond which a color won't have its highlight brightness
2284 Nominally, highlight colors for `3d' faces are calculated by
2285 brightening an object's color by a constant scale factor, but this
2286 doesn't yield good results for dark colors, so for colors who's
2287 brightness is less than this value (on a scale of 0-255) have to
2288 use an additional additive factor.
2290 The value here is set so that the default menu-bar/mode-line color
2291 (grey75) will not have its highlights changed at all. */
2292 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2295 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2296 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2297 If this produces the same color as COLOR, try a color where all RGB
2298 values have DELTA added. Return the allocated color in *COLOR.
2299 DISPLAY is the X display, CMAP is the colormap to operate on.
2300 Value is non-zero if successful. */
2303 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2305 unsigned long *color
;
2312 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2315 /* Change RGB values by specified FACTOR. Avoid overflow! */
2316 xassert (factor
>= 0);
2317 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2318 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2319 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2321 /* Calculate brightness of COLOR. */
2322 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2323 + BLUE_FROM_ULONG (*color
)) / 6;
2325 /* We only boost colors that are darker than
2326 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2327 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2328 /* Make an additive adjustment to NEW, because it's dark enough so
2329 that scaling by FACTOR alone isn't enough. */
2331 /* How far below the limit this color is (0 - 1, 1 being darker). */
2332 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2333 /* The additive adjustment. */
2334 int min_delta
= delta
* dimness
* factor
/ 2;
2337 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2338 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2339 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2341 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2342 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2343 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2347 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2348 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2349 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2351 /* MAC_TODO: Map to palette and retry with delta if same? */
2352 /* MAC_TODO: Free colors (if using palette)? */
2363 /* Set up the foreground color for drawing relief lines of glyph
2364 string S. RELIEF is a pointer to a struct relief containing the GC
2365 with which lines will be drawn. Use a color that is FACTOR or
2366 DELTA lighter or darker than the relief's background which is found
2367 in S->f->output_data.x->relief_background. If such a color cannot
2368 be allocated, use DEFAULT_PIXEL, instead. */
2371 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2373 struct relief
*relief
;
2376 unsigned long default_pixel
;
2379 struct mac_output
*di
= f
->output_data
.mac
;
2380 unsigned long mask
= GCForeground
;
2381 unsigned long pixel
;
2382 unsigned long background
= di
->relief_background
;
2383 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2385 /* MAC_TODO: Free colors (if using palette)? */
2387 /* Allocate new color. */
2388 xgcv
.foreground
= default_pixel
;
2390 if (dpyinfo
->n_planes
!= 1
2391 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2393 relief
->allocated_p
= 1;
2394 xgcv
.foreground
= relief
->pixel
= pixel
;
2397 if (relief
->gc
== 0)
2399 #if 0 /* MAC_TODO: stipple */
2400 xgcv
.stipple
= dpyinfo
->gray
;
2403 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2406 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2410 /* Set up colors for the relief lines around glyph string S. */
2413 x_setup_relief_colors (s
)
2414 struct glyph_string
*s
;
2416 struct mac_output
*di
= s
->f
->output_data
.mac
;
2417 unsigned long color
;
2419 if (s
->face
->use_box_color_for_shadows_p
)
2420 color
= s
->face
->box_color
;
2421 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2423 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2424 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2429 /* Get the background color of the face. */
2430 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2431 color
= xgcv
.background
;
2434 if (di
->white_relief
.gc
== 0
2435 || color
!= di
->relief_background
)
2437 di
->relief_background
= color
;
2438 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2439 WHITE_PIX_DEFAULT (s
->f
));
2440 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2441 BLACK_PIX_DEFAULT (s
->f
));
2446 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2447 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2448 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2449 relief. LEFT_P non-zero means draw a relief on the left side of
2450 the rectangle. RIGHT_P non-zero means draw a relief on the right
2451 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2455 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2456 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2458 int left_x
, top_y
, right_x
, bottom_y
, width
;
2459 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2462 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2463 Window window
= FRAME_MAC_WINDOW (f
);
2468 gc
= f
->output_data
.mac
->white_relief
.gc
;
2470 gc
= f
->output_data
.mac
->black_relief
.gc
;
2471 mac_set_clip_rectangle (dpy
, window
, clip_rect
);
2475 for (i
= 0; i
< width
; ++i
)
2476 XDrawLine (dpy
, window
, gc
,
2477 left_x
+ i
* left_p
, top_y
+ i
,
2478 right_x
- i
* right_p
, top_y
+ i
);
2482 for (i
= 0; i
< width
; ++i
)
2483 XDrawLine (dpy
, window
, gc
,
2484 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2486 mac_reset_clipping (dpy
, window
);
2488 gc
= f
->output_data
.mac
->black_relief
.gc
;
2490 gc
= f
->output_data
.mac
->white_relief
.gc
;
2491 mac_set_clip_rectangle (dpy
, window
,
2496 for (i
= 0; i
< width
; ++i
)
2497 XDrawLine (dpy
, window
, gc
,
2498 left_x
+ i
* left_p
, bottom_y
- i
,
2499 right_x
- i
* right_p
, bottom_y
- i
);
2503 for (i
= 0; i
< width
; ++i
)
2504 XDrawLine (dpy
, window
, gc
,
2505 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2507 mac_reset_clipping (dpy
, window
);
2511 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2512 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2513 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2514 left side of the rectangle. RIGHT_P non-zero means draw a line
2515 on the right side of the rectangle. CLIP_RECT is the clipping
2516 rectangle to use when drawing. */
2519 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2520 left_p
, right_p
, clip_rect
)
2521 struct glyph_string
*s
;
2522 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2527 xgcv
.foreground
= s
->face
->box_color
;
2528 mac_set_clip_rectangle (s
->display
, s
->window
, clip_rect
);
2531 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2532 left_x
, top_y
, right_x
- left_x
+ 1, width
);
2536 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2537 left_x
, top_y
, width
, bottom_y
- top_y
+ 1);
2540 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2541 left_x
, bottom_y
- width
+ 1, right_x
- left_x
+ 1, width
);
2545 XFillRectangle (s
->display
, s
->window
, &xgcv
,
2546 right_x
- width
+ 1, top_y
, width
, bottom_y
- top_y
+ 1);
2548 mac_reset_clipping (s
->display
, s
->window
);
2552 /* Draw a box around glyph string S. */
2555 x_draw_glyph_string_box (s
)
2556 struct glyph_string
*s
;
2558 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2559 int left_p
, right_p
;
2560 struct glyph
*last_glyph
;
2563 last_x
= window_box_right (s
->w
, s
->area
);
2564 if (s
->row
->full_width_p
2565 && !s
->w
->pseudo_window_p
)
2567 last_x
+= WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s
->w
);
2568 if (s
->area
!= RIGHT_MARGIN_AREA
2569 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s
->w
))
2570 last_x
+= WINDOW_RIGHT_FRINGE_WIDTH (s
->w
);
2573 /* The glyph that may have a right box line. */
2574 last_glyph
= (s
->cmp
|| s
->img
2576 : s
->first_glyph
+ s
->nchars
- 1);
2578 width
= abs (s
->face
->box_line_width
);
2579 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2581 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2583 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2585 bottom_y
= top_y
+ s
->height
- 1;
2587 left_p
= (s
->first_glyph
->left_box_line_p
2588 || (s
->hl
== DRAW_MOUSE_FACE
2590 || s
->prev
->hl
!= s
->hl
)));
2591 right_p
= (last_glyph
->right_box_line_p
2592 || (s
->hl
== DRAW_MOUSE_FACE
2594 || s
->next
->hl
!= s
->hl
)));
2596 get_glyph_string_clip_rect (s
, &clip_rect
);
2598 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2599 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2600 left_p
, right_p
, &clip_rect
);
2603 x_setup_relief_colors (s
);
2604 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2605 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2610 /* Draw foreground of image glyph string S. */
2613 x_draw_image_foreground (s
)
2614 struct glyph_string
*s
;
2617 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2619 /* If first glyph of S has a left box line, start drawing it to the
2620 right of that line. */
2621 if (s
->face
->box
!= FACE_NO_BOX
2622 && s
->first_glyph
->left_box_line_p
2624 x
+= abs (s
->face
->box_line_width
);
2626 /* If there is a margin around the image, adjust x- and y-position
2628 if (s
->slice
.x
== 0)
2629 x
+= s
->img
->hmargin
;
2630 if (s
->slice
.y
== 0)
2631 y
+= s
->img
->vmargin
;
2638 XRectangle clip_rect
, image_rect
, r
;
2640 get_glyph_string_clip_rect (s
, &nr
);
2641 CONVERT_TO_XRECT (clip_rect
, nr
);
2644 image_rect
.width
= s
->slice
.width
;
2645 image_rect
.height
= s
->slice
.height
;
2646 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2647 mac_copy_area_with_mask (s
->display
, s
->img
->pixmap
, s
->img
->mask
,
2649 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2650 r
.width
, r
.height
, r
.x
, r
.y
);
2655 XRectangle clip_rect
, image_rect
, r
;
2657 get_glyph_string_clip_rect (s
, &nr
);
2658 CONVERT_TO_XRECT (clip_rect
, nr
);
2661 image_rect
.width
= s
->slice
.width
;
2662 image_rect
.height
= s
->slice
.height
;
2663 if (x_intersect_rectangles (&clip_rect
, &image_rect
, &r
))
2664 mac_copy_area (s
->display
, s
->img
->pixmap
, s
->window
, s
->gc
,
2665 s
->slice
.x
+ r
.x
- x
, s
->slice
.y
+ r
.y
- y
,
2666 r
.width
, r
.height
, r
.x
, r
.y
);
2668 /* When the image has a mask, we can expect that at
2669 least part of a mouse highlight or a block cursor will
2670 be visible. If the image doesn't have a mask, make
2671 a block cursor visible by drawing a rectangle around
2672 the image. I believe it's looking better if we do
2673 nothing here for mouse-face. */
2674 if (s
->hl
== DRAW_CURSOR
)
2676 int r
= s
->img
->relief
;
2678 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
,
2680 s
->slice
.width
+ r
*2 - 1,
2681 s
->slice
.height
+ r
*2 - 1);
2686 /* Draw a rectangle if image could not be loaded. */
2687 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
, y
,
2688 s
->slice
.width
- 1, s
->slice
.height
- 1);
2692 /* Draw a relief around the image glyph string S. */
2695 x_draw_image_relief (s
)
2696 struct glyph_string
*s
;
2698 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2701 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2703 /* If first glyph of S has a left box line, start drawing it to the
2704 right of that line. */
2705 if (s
->face
->box
!= FACE_NO_BOX
2706 && s
->first_glyph
->left_box_line_p
2708 x
+= abs (s
->face
->box_line_width
);
2710 /* If there is a margin around the image, adjust x- and y-position
2712 if (s
->slice
.x
== 0)
2713 x
+= s
->img
->hmargin
;
2714 if (s
->slice
.y
== 0)
2715 y
+= s
->img
->vmargin
;
2717 if (s
->hl
== DRAW_IMAGE_SUNKEN
2718 || s
->hl
== DRAW_IMAGE_RAISED
)
2720 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2721 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2725 thick
= abs (s
->img
->relief
);
2726 raised_p
= s
->img
->relief
> 0;
2731 x1
= x
+ s
->slice
.width
+ thick
- 1;
2732 y1
= y
+ s
->slice
.height
+ thick
- 1;
2734 x_setup_relief_colors (s
);
2735 get_glyph_string_clip_rect (s
, &r
);
2736 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2738 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2740 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2745 /* Draw the foreground of image glyph string S to PIXMAP. */
2748 x_draw_image_foreground_1 (s
, pixmap
)
2749 struct glyph_string
*s
;
2753 int y
= s
->ybase
- s
->y
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2755 /* If first glyph of S has a left box line, start drawing it to the
2756 right of that line. */
2757 if (s
->face
->box
!= FACE_NO_BOX
2758 && s
->first_glyph
->left_box_line_p
2760 x
+= abs (s
->face
->box_line_width
);
2762 /* If there is a margin around the image, adjust x- and y-position
2764 if (s
->slice
.x
== 0)
2765 x
+= s
->img
->hmargin
;
2766 if (s
->slice
.y
== 0)
2767 y
+= s
->img
->vmargin
;
2772 mac_copy_area_with_mask_to_pixmap (s
->display
, s
->img
->pixmap
,
2773 s
->img
->mask
, pixmap
, s
->gc
,
2774 s
->slice
.x
, s
->slice
.y
,
2775 s
->slice
.width
, s
->slice
.height
,
2779 mac_copy_area_to_pixmap (s
->display
, s
->img
->pixmap
, pixmap
, s
->gc
,
2780 s
->slice
.x
, s
->slice
.y
,
2781 s
->slice
.width
, s
->slice
.height
,
2784 /* When the image has a mask, we can expect that at
2785 least part of a mouse highlight or a block cursor will
2786 be visible. If the image doesn't have a mask, make
2787 a block cursor visible by drawing a rectangle around
2788 the image. I believe it's looking better if we do
2789 nothing here for mouse-face. */
2790 if (s
->hl
== DRAW_CURSOR
)
2792 int r
= s
->img
->relief
;
2794 mac_draw_rectangle (s
->display
, s
->window
, s
->gc
, x
- r
, y
- r
,
2795 s
->slice
.width
+ r
*2 - 1,
2796 s
->slice
.height
+ r
*2 - 1);
2801 /* Draw a rectangle if image could not be loaded. */
2802 mac_draw_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
, x
, y
,
2803 s
->slice
.width
- 1, s
->slice
.height
- 1);
2807 /* Draw part of the background of glyph string S. X, Y, W, and H
2808 give the rectangle to draw. */
2811 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2812 struct glyph_string
*s
;
2815 #if 0 /* MAC_TODO: stipple */
2818 /* Fill background with a stipple pattern. */
2819 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2820 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2821 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2824 #endif /* MAC_TODO */
2825 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2829 /* Draw image glyph string S.
2832 s->x +-------------------------
2835 | +-------------------------
2838 | | +-------------------
2844 x_draw_image_glyph_string (s
)
2845 struct glyph_string
*s
;
2848 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2849 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2853 height
= s
->height
- 2 * box_line_vwidth
;
2856 /* Fill background with face under the image. Do it only if row is
2857 taller than image or if image has a clip mask to reduce
2859 s
->stippled_p
= s
->face
->stipple
!= 0;
2860 if (height
> s
->slice
.height
2864 || s
->img
->pixmap
== 0
2865 || s
->width
!= s
->background_width
)
2868 if (s
->first_glyph
->left_box_line_p
2870 x
+= box_line_hwidth
;
2873 if (s
->slice
.y
== 0)
2874 y
+= box_line_vwidth
;
2878 /* Create a pixmap as large as the glyph string. Fill it
2879 with the background color. Copy the image to it, using
2880 its mask. Copy the temporary pixmap to the display. */
2881 int depth
= one_mac_display_info
.n_planes
;
2883 /* Create a pixmap as large as the glyph string. */
2884 pixmap
= XCreatePixmap (s
->display
, s
->window
,
2885 s
->background_width
,
2888 /* Fill the pixmap with the background color/stipple. */
2889 #if 0 /* TODO: stipple */
2892 /* Fill background with a stipple pattern. */
2893 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2894 XFillRectangle (s
->display
, pixmap
, s
->gc
,
2895 0, 0, s
->background_width
, s
->height
);
2896 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2902 XGetGCValues (s
->display
, s
->gc
, GCForeground
| GCBackground
,
2904 XSetForeground (s
->display
, s
->gc
, xgcv
.background
);
2905 mac_fill_rectangle_to_pixmap (s
->display
, pixmap
, s
->gc
,
2906 0, 0, s
->background_width
,
2908 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2912 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
2914 s
->background_filled_p
= 1;
2917 /* Draw the foreground. */
2920 x_draw_image_foreground_1 (s
, pixmap
);
2921 x_set_glyph_string_clipping (s
);
2922 mac_copy_area (s
->display
, pixmap
, s
->window
, s
->gc
,
2923 0, 0, s
->background_width
, s
->height
, s
->x
, s
->y
);
2924 mac_reset_clipping (s
->display
, s
->window
);
2925 XFreePixmap (s
->display
, pixmap
);
2928 x_draw_image_foreground (s
);
2930 /* If we must draw a relief around the image, do it. */
2932 || s
->hl
== DRAW_IMAGE_RAISED
2933 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2934 x_draw_image_relief (s
);
2938 /* Draw stretch glyph string S. */
2941 x_draw_stretch_glyph_string (s
)
2942 struct glyph_string
*s
;
2944 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
2945 s
->stippled_p
= s
->face
->stipple
!= 0;
2947 if (s
->hl
== DRAW_CURSOR
2948 && !x_stretch_cursor_p
)
2950 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
2951 as wide as the stretch glyph. */
2952 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
2955 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
2957 /* Clear rest using the GC of the original non-cursor face. */
2958 if (width
< s
->background_width
)
2960 int x
= s
->x
+ width
, y
= s
->y
;
2961 int w
= s
->background_width
- width
, h
= s
->height
;
2965 if (s
->row
->mouse_face_p
2966 && cursor_in_mouse_face_p (s
->w
))
2968 x_set_mouse_face_gc (s
);
2974 get_glyph_string_clip_rect (s
, &r
);
2975 mac_set_clip_rectangle (s
->display
, s
->window
, &r
);
2977 #if 0 /* MAC_TODO: stipple */
2978 if (s
->face
->stipple
)
2980 /* Fill background with a stipple pattern. */
2981 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
2982 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2983 XSetFillStyle (s
->display
, gc
, FillSolid
);
2986 #endif /* MAC_TODO */
2989 XGetGCValues (s
->display
, gc
, GCForeground
| GCBackground
, &xgcv
);
2990 XSetForeground (s
->display
, gc
, xgcv
.background
);
2991 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
2992 XSetForeground (s
->display
, gc
, xgcv
.foreground
);
2995 mac_reset_clipping (s
->display
, s
->window
);
2998 else if (!s
->background_filled_p
)
2999 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3002 s
->background_filled_p
= 1;
3006 /* Draw glyph string S. */
3009 x_draw_glyph_string (s
)
3010 struct glyph_string
*s
;
3012 int relief_drawn_p
= 0;
3014 /* If S draws into the background of its successor, draw the
3015 background of the successor first so that S can draw into it.
3016 This makes S->next use XDrawString instead of XDrawImageString. */
3017 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps_p
)
3019 xassert (s
->next
->img
== NULL
);
3020 x_set_glyph_string_gc (s
->next
);
3021 x_set_glyph_string_clipping (s
->next
);
3022 x_draw_glyph_string_background (s
->next
, 1);
3025 /* Set up S->gc, set clipping and draw S. */
3026 x_set_glyph_string_gc (s
);
3028 /* Draw relief (if any) in advance for char/composition so that the
3029 glyph string can be drawn over it. */
3030 if (!s
->for_overlaps_p
3031 && s
->face
->box
!= FACE_NO_BOX
3032 && (s
->first_glyph
->type
== CHAR_GLYPH
3033 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3036 x_set_glyph_string_clipping (s
);
3037 x_draw_glyph_string_background (s
, 1);
3038 x_draw_glyph_string_box (s
);
3039 x_set_glyph_string_clipping (s
);
3043 x_set_glyph_string_clipping (s
);
3045 switch (s
->first_glyph
->type
)
3048 x_draw_image_glyph_string (s
);
3052 x_draw_stretch_glyph_string (s
);
3056 if (s
->for_overlaps_p
)
3057 s
->background_filled_p
= 1;
3059 x_draw_glyph_string_background (s
, 0);
3060 x_draw_glyph_string_foreground (s
);
3063 case COMPOSITE_GLYPH
:
3064 if (s
->for_overlaps_p
|| s
->gidx
> 0)
3065 s
->background_filled_p
= 1;
3067 x_draw_glyph_string_background (s
, 1);
3068 x_draw_composite_glyph_string_foreground (s
);
3075 if (!s
->for_overlaps_p
)
3077 /* Draw underline. */
3078 if (s
->face
->underline_p
)
3080 unsigned long h
= 1;
3081 unsigned long dy
= s
->height
- h
;
3083 if (s
->face
->underline_defaulted_p
)
3084 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3089 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3090 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3091 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3093 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3097 /* Draw overline. */
3098 if (s
->face
->overline_p
)
3100 unsigned long dy
= 0, h
= 1;
3102 if (s
->face
->overline_color_defaulted_p
)
3103 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3108 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3109 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3110 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3112 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3116 /* Draw strike-through. */
3117 if (s
->face
->strike_through_p
)
3119 unsigned long h
= 1;
3120 unsigned long dy
= (s
->height
- h
) / 2;
3122 if (s
->face
->strike_through_color_defaulted_p
)
3123 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3128 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3129 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3130 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
, s
->y
+ dy
,
3132 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3136 /* Draw relief if not yet drawn. */
3137 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3138 x_draw_glyph_string_box (s
);
3141 /* Reset clipping. */
3142 mac_reset_clipping (s
->display
, s
->window
);
3145 /* Shift display to make room for inserted glyphs. */
3148 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3150 int x
, y
, width
, height
, shift_by
;
3152 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3153 f
->output_data
.mac
->normal_gc
,
3154 x
, y
, width
, height
,
3158 /* Delete N glyphs at the nominal cursor position. Not implemented
3169 /* Clear entire frame. If updating_frame is non-null, clear that
3170 frame. Otherwise clear the selected frame. */
3180 f
= SELECTED_FRAME ();
3182 /* Clearing the frame will erase any cursor, so mark them all as no
3184 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3185 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3186 output_cursor
.x
= -1;
3188 /* We don't set the output cursor here because there will always
3189 follow an explicit cursor_to. */
3191 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
3193 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3194 /* We have to clear the scroll bars, too. If we have changed
3195 colors or something like that, then they should be notified. */
3196 x_scroll_bar_clear (f
);
3199 XFlush (FRAME_MAC_DISPLAY (f
));
3205 /* Invert the middle quarter of the frame for .15 sec. */
3207 /* We use the select system call to do the waiting, so we have to make
3208 sure it's available. If it isn't, we just won't do visual bells. */
3210 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3213 /* Subtract the `struct timeval' values X and Y, storing the result in
3214 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3217 timeval_subtract (result
, x
, y
)
3218 struct timeval
*result
, x
, y
;
3220 /* Perform the carry for the later subtraction by updating y. This
3221 is safer because on some systems the tv_sec member is unsigned. */
3222 if (x
.tv_usec
< y
.tv_usec
)
3224 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3225 y
.tv_usec
-= 1000000 * nsec
;
3229 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3231 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3232 y
.tv_usec
+= 1000000 * nsec
;
3236 /* Compute the time remaining to wait. tv_usec is certainly
3238 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3239 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3241 /* Return indication of whether the result should be considered
3243 return x
.tv_sec
< y
.tv_sec
;
3255 struct timeval wakeup
;
3257 EMACS_GET_TIME (wakeup
);
3259 /* Compute time to wait until, propagating carry from usecs. */
3260 wakeup
.tv_usec
+= 150000;
3261 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3262 wakeup
.tv_usec
%= 1000000;
3264 /* Keep waiting until past the time wakeup. */
3267 struct timeval timeout
;
3269 EMACS_GET_TIME (timeout
);
3271 /* In effect, timeout = wakeup - timeout.
3272 Break if result would be negative. */
3273 if (timeval_subtract (&timeout
, wakeup
, timeout
))
3276 /* Try to wait that long--but we might wake up sooner. */
3277 select (0, NULL
, NULL
, NULL
, &timeout
);
3286 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3289 /* Make audible bell. */
3294 struct frame
*f
= SELECTED_FRAME ();
3296 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3304 XFlush (FRAME_MAC_DISPLAY (f
));
3311 /* Specify how many text lines, from the top of the window,
3312 should be affected by insert-lines and delete-lines operations.
3313 This, and those operations, are used only within an update
3314 that is bounded by calls to x_update_begin and x_update_end. */
3317 XTset_terminal_window (n
)
3320 /* This function intentionally left blank. */
3325 /***********************************************************************
3327 ***********************************************************************/
3329 /* Perform an insert-lines or delete-lines operation, inserting N
3330 lines or deleting -N lines at vertical position VPOS. */
3333 x_ins_del_lines (vpos
, n
)
3340 /* Scroll part of the display as described by RUN. */
3343 x_scroll_run (w
, run
)
3347 struct frame
*f
= XFRAME (w
->frame
);
3348 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3350 /* Get frame-relative bounding box of the text display area of W,
3351 without mode lines. Include in this box the left and right
3353 window_box (w
, -1, &x
, &y
, &width
, &height
);
3355 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3356 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3357 bottom_y
= y
+ height
;
3361 /* Scrolling up. Make sure we don't copy part of the mode
3362 line at the bottom. */
3363 if (from_y
+ run
->height
> bottom_y
)
3364 height
= bottom_y
- from_y
;
3366 height
= run
->height
;
3370 /* Scolling down. Make sure we don't copy over the mode line.
3372 if (to_y
+ run
->height
> bottom_y
)
3373 height
= bottom_y
- to_y
;
3375 height
= run
->height
;
3380 /* Cursor off. Will be switched on again in x_update_window_end. */
3384 mac_scroll_area (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
3385 f
->output_data
.mac
->normal_gc
,
3395 /***********************************************************************
3397 ***********************************************************************/
3404 x_update_cursor (f
, 1);
3408 frame_unhighlight (f
)
3411 x_update_cursor (f
, 1);
3414 /* The focus has changed. Update the frames as necessary to reflect
3415 the new situation. Note that we can't change the selected frame
3416 here, because the Lisp code we are interrupting might become confused.
3417 Each event gets marked with the frame in which it occurred, so the
3418 Lisp code can tell when the switch took place by examining the events. */
3421 x_new_focus_frame (dpyinfo
, frame
)
3422 struct x_display_info
*dpyinfo
;
3423 struct frame
*frame
;
3425 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3427 if (frame
!= dpyinfo
->x_focus_frame
)
3429 /* Set this before calling other routines, so that they see
3430 the correct value of x_focus_frame. */
3431 dpyinfo
->x_focus_frame
= frame
;
3433 if (old_focus
&& old_focus
->auto_lower
)
3434 x_lower_frame (old_focus
);
3437 selected_frame
= frame
;
3438 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3440 Fselect_window (selected_frame
->selected_window
, Qnil
);
3441 choose_minibuf_frame ();
3444 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3445 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3447 pending_autoraise_frame
= 0;
3450 x_frame_rehighlight (dpyinfo
);
3453 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3456 x_mouse_leave (dpyinfo
)
3457 struct x_display_info
*dpyinfo
;
3459 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3462 /* The focus has changed, or we have redirected a frame's focus to
3463 another frame (this happens when a frame uses a surrogate
3464 mini-buffer frame). Shift the highlight as appropriate.
3466 The FRAME argument doesn't necessarily have anything to do with which
3467 frame is being highlighted or un-highlighted; we only use it to find
3468 the appropriate X display info. */
3471 XTframe_rehighlight (frame
)
3472 struct frame
*frame
;
3474 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3478 x_frame_rehighlight (dpyinfo
)
3479 struct x_display_info
*dpyinfo
;
3481 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3483 if (dpyinfo
->x_focus_frame
)
3485 dpyinfo
->x_highlight_frame
3486 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3487 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3488 : dpyinfo
->x_focus_frame
);
3489 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3491 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3492 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3496 dpyinfo
->x_highlight_frame
= 0;
3498 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3501 frame_unhighlight (old_highlight
);
3502 if (dpyinfo
->x_highlight_frame
)
3503 frame_highlight (dpyinfo
->x_highlight_frame
);
3509 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3511 #if 0 /* MAC_TODO */
3512 /* Initialize mode_switch_bit and modifier_meaning. */
3514 x_find_modifier_meanings (dpyinfo
)
3515 struct x_display_info
*dpyinfo
;
3517 int min_code
, max_code
;
3520 XModifierKeymap
*mods
;
3522 dpyinfo
->meta_mod_mask
= 0;
3523 dpyinfo
->shift_lock_mask
= 0;
3524 dpyinfo
->alt_mod_mask
= 0;
3525 dpyinfo
->super_mod_mask
= 0;
3526 dpyinfo
->hyper_mod_mask
= 0;
3529 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3531 min_code
= dpyinfo
->display
->min_keycode
;
3532 max_code
= dpyinfo
->display
->max_keycode
;
3535 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3536 min_code
, max_code
- min_code
+ 1,
3538 mods
= XGetModifierMapping (dpyinfo
->display
);
3540 /* Scan the modifier table to see which modifier bits the Meta and
3541 Alt keysyms are on. */
3543 int row
, col
; /* The row and column in the modifier table. */
3545 for (row
= 3; row
< 8; row
++)
3546 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3549 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3551 /* Zeroes are used for filler. Skip them. */
3555 /* Are any of this keycode's keysyms a meta key? */
3559 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3561 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3567 dpyinfo
->meta_mod_mask
|= (1 << row
);
3572 dpyinfo
->alt_mod_mask
|= (1 << row
);
3577 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3582 dpyinfo
->super_mod_mask
|= (1 << row
);
3586 /* Ignore this if it's not on the lock modifier. */
3587 if ((1 << row
) == LockMask
)
3588 dpyinfo
->shift_lock_mask
= LockMask
;
3596 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3597 if (! dpyinfo
->meta_mod_mask
)
3599 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3600 dpyinfo
->alt_mod_mask
= 0;
3603 /* If some keys are both alt and meta,
3604 make them just meta, not alt. */
3605 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3607 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3610 XFree ((char *) syms
);
3611 XFreeModifiermap (mods
);
3614 #endif /* MAC_TODO */
3616 /* Convert between the modifier bits X uses and the modifier bits
3620 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3621 struct x_display_info
*dpyinfo
;
3622 unsigned short state
;
3624 return (((state
& shiftKey
) ? shift_modifier
: 0)
3625 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3626 | ((state
& cmdKey
) ? meta_modifier
: 0)
3627 | ((state
& optionKey
) ? alt_modifier
: 0));
3630 #if 0 /* MAC_TODO */
3631 static unsigned short
3632 x_emacs_to_x_modifiers (dpyinfo
, state
)
3633 struct x_display_info
*dpyinfo
;
3636 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3637 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3638 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3639 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3640 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3641 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3643 #endif /* MAC_TODO */
3645 /* Convert a keysym to its name. */
3648 x_get_keysym_name (keysym
)
3655 value
= XKeysymToString (keysym
);
3666 /* Mouse clicks and mouse movement. Rah. */
3668 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3670 If the event is a button press, then note that we have grabbed
3674 construct_mouse_click (result
, event
, f
)
3675 struct input_event
*result
;
3681 result
->kind
= MOUSE_CLICK_EVENT
;
3682 result
->code
= 0; /* only one mouse button */
3683 result
->timestamp
= event
->when
;
3684 result
->modifiers
= event
->what
== mouseDown
? down_modifier
: up_modifier
;
3686 mouseLoc
= event
->where
;
3688 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
3690 GlobalToLocal (&mouseLoc
);
3691 XSETINT (result
->x
, mouseLoc
.h
);
3692 XSETINT (result
->y
, mouseLoc
.v
);
3694 XSETFRAME (result
->frame_or_window
, f
);
3701 /* Function to report a mouse movement to the mainstream Emacs code.
3702 The input handler calls this.
3704 We have received a mouse movement event, which is given in *event.
3705 If the mouse is over a different glyph than it was last time, tell
3706 the mainstream emacs code by setting mouse_moved. If not, ask for
3707 another motion event, so we can check again the next time it moves. */
3709 static Point last_mouse_motion_position
;
3710 static Lisp_Object last_mouse_motion_frame
;
3713 note_mouse_movement (frame
, pos
)
3717 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3718 #if TARGET_API_MAC_CARBON
3722 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3723 last_mouse_motion_position
= *pos
;
3724 XSETFRAME (last_mouse_motion_frame
, frame
);
3726 #if TARGET_API_MAC_CARBON
3727 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3729 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3732 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3733 /* This case corresponds to LeaveNotify in X11. */
3735 /* If we move outside the frame, then we're certainly no
3736 longer on any text in the frame. */
3737 clear_mouse_face (dpyinfo
);
3738 dpyinfo
->mouse_face_mouse_frame
= 0;
3739 if (!dpyinfo
->grabbed
)
3740 rif
->define_frame_cursor (frame
,
3741 frame
->output_data
.mac
->nontext_cursor
);
3744 /* Has the mouse moved off the glyph it was on at the last sighting? */
3745 else if (pos
->h
< last_mouse_glyph
.left
3746 || pos
->h
>= last_mouse_glyph
.right
3747 || pos
->v
< last_mouse_glyph
.top
3748 || pos
->v
>= last_mouse_glyph
.bottom
)
3750 frame
->mouse_moved
= 1;
3751 last_mouse_scroll_bar
= Qnil
;
3752 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3756 /* This is used for debugging, to turn off note_mouse_highlight. */
3758 int disable_mouse_highlight
;
3762 /************************************************************************
3764 ************************************************************************/
3766 static struct scroll_bar
*x_window_to_scroll_bar ();
3767 static void x_scroll_bar_report_motion ();
3768 static void x_check_fullscreen
P_ ((struct frame
*));
3769 static void x_check_fullscreen_move
P_ ((struct frame
*));
3770 static int glyph_rect
P_ ((struct frame
*f
, int, int, Rect
*));
3773 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3776 redo_mouse_highlight ()
3778 if (!NILP (last_mouse_motion_frame
)
3779 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3780 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3781 last_mouse_motion_position
.h
,
3782 last_mouse_motion_position
.v
);
3786 /* Try to determine frame pixel position and size of the glyph under
3787 frame pixel coordinates X/Y on frame F . Return the position and
3788 size in *RECT. Value is non-zero if we could compute these
3792 glyph_rect (f
, x
, y
, rect
)
3799 window
= window_from_coordinates (f
, x
, y
, 0, &x
, &y
, 0);
3803 struct window
*w
= XWINDOW (window
);
3804 struct glyph_row
*r
= MATRIX_FIRST_TEXT_ROW (w
->current_matrix
);
3805 struct glyph_row
*end
= r
+ w
->current_matrix
->nrows
- 1;
3807 for (; r
< end
&& r
->enabled_p
; ++r
)
3808 if (r
->y
<= y
&& r
->y
+ r
->height
> y
)
3810 /* Found the row at y. */
3811 struct glyph
*g
= r
->glyphs
[TEXT_AREA
];
3812 struct glyph
*end
= g
+ r
->used
[TEXT_AREA
];
3815 rect
->top
= WINDOW_TO_FRAME_PIXEL_Y (w
, r
->y
);
3816 rect
->bottom
= rect
->top
+ r
->height
;
3820 /* x is to the left of the first glyph in the row. */
3821 /* Shouldn't this be a pixel value?
3822 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3824 rect
->left
= WINDOW_LEFT_EDGE_COL (w
);
3825 rect
->right
= WINDOW_TO_FRAME_PIXEL_X (w
, r
->x
);
3829 for (gx
= r
->x
; g
< end
; gx
+= g
->pixel_width
, ++g
)
3830 if (gx
<= x
&& gx
+ g
->pixel_width
> x
)
3832 /* x is on a glyph. */
3833 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3834 rect
->right
= rect
->left
+ g
->pixel_width
;
3838 /* x is to the right of the last glyph in the row. */
3839 rect
->left
= WINDOW_TO_FRAME_PIXEL_X (w
, gx
);
3840 /* Shouldn't this be a pixel value?
3841 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3843 rect
->right
= WINDOW_RIGHT_EDGE_COL (w
);
3848 /* The y is not on any row. */
3852 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3854 /* Record the position of the mouse in last_mouse_glyph. */
3856 remember_mouse_glyph (f1
, gx
, gy
)
3860 if (!glyph_rect (f1
, gx
, gy
, &last_mouse_glyph
))
3862 int width
= FRAME_SMALLEST_CHAR_WIDTH (f1
);
3863 int height
= FRAME_SMALLEST_FONT_HEIGHT (f1
);
3865 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3866 round down even for negative values. */
3872 /* This was the original code from XTmouse_position, but it seems
3873 to give the position of the glyph diagonally next to the one
3874 the mouse is over. */
3875 gx
= (gx
+ width
- 1) / width
* width
;
3876 gy
= (gy
+ height
- 1) / height
* height
;
3878 gx
= gx
/ width
* width
;
3879 gy
= gy
/ height
* height
;
3882 last_mouse_glyph
.left
= gx
;
3883 last_mouse_glyph
.top
= gy
;
3884 last_mouse_glyph
.right
= gx
+ width
;
3885 last_mouse_glyph
.bottom
= gy
+ height
;
3891 front_emacs_window ()
3893 #if TARGET_API_MAC_CARBON
3894 WindowPtr wp
= GetFrontWindowOfClass (kDocumentWindowClass
, true);
3896 while (wp
&& !is_emacs_window (wp
))
3897 wp
= GetNextWindowOfClass (wp
, kDocumentWindowClass
, true);
3899 WindowPtr wp
= FrontWindow ();
3901 while (wp
&& (wp
== tip_window
|| !is_emacs_window (wp
)))
3902 wp
= GetNextWindow (wp
);
3908 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3910 /* Return the current position of the mouse.
3911 *fp should be a frame which indicates which display to ask about.
3913 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3914 and *part to the frame, window, and scroll bar part that the mouse
3915 is over. Set *x and *y to the portion and whole of the mouse's
3916 position on the scroll bar.
3918 If the mouse movement started elsewhere, set *fp to the frame the
3919 mouse is on, *bar_window to nil, and *x and *y to the character cell
3922 Set *time to the server time-stamp for the time at which the mouse
3923 was at this position.
3925 Don't store anything if we don't have a valid set of values to report.
3927 This clears the mouse_moved flag, so we can wait for the next mouse
3931 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3934 Lisp_Object
*bar_window
;
3935 enum scroll_bar_part
*part
;
3937 unsigned long *time
;
3940 int ignore1
, ignore2
;
3941 WindowPtr wp
= front_emacs_window ();
3943 Lisp_Object frame
, tail
;
3945 if (is_emacs_window(wp
))
3946 f
= mac_window_to_frame (wp
);
3950 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
3951 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
3954 /* Clear the mouse-moved flag for every frame on this display. */
3955 FOR_EACH_FRAME (tail
, frame
)
3956 XFRAME (frame
)->mouse_moved
= 0;
3958 last_mouse_scroll_bar
= Qnil
;
3960 SetPortWindowPort (wp
);
3962 GetMouse (&mouse_pos
);
3964 pixel_to_glyph_coords (f
, mouse_pos
.h
, mouse_pos
.v
, &ignore1
, &ignore2
,
3965 &last_mouse_glyph
, insist
);
3968 *part
= scroll_bar_handle
;
3970 XSETINT (*x
, mouse_pos
.h
);
3971 XSETINT (*y
, mouse_pos
.v
);
3972 *time
= last_mouse_movement_time
;
3979 /***********************************************************************
3981 ***********************************************************************/
3983 /* Handle mouse button event on the tool-bar of frame F, at
3984 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3988 mac_handle_tool_bar_click (f
, button_event
)
3990 EventRecord
*button_event
;
3992 int x
= button_event
->where
.h
;
3993 int y
= button_event
->where
.v
;
3995 if (button_event
->what
== mouseDown
)
3996 handle_tool_bar_click (f
, x
, y
, 1, 0);
3998 handle_tool_bar_click (f
, x
, y
, 0,
3999 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f
),
4000 button_event
->modifiers
));
4004 /************************************************************************
4005 Scroll bars, general
4006 ************************************************************************/
4008 /* Create a scroll bar and return the scroll bar vector for it. W is
4009 the Emacs window on which to create the scroll bar. TOP, LEFT,
4010 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4013 static struct scroll_bar
*
4014 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4016 int top
, left
, width
, height
, disp_top
, disp_height
;
4018 struct frame
*f
= XFRAME (w
->frame
);
4019 struct scroll_bar
*bar
4020 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4028 r
.right
= left
+ width
;
4029 r
.bottom
= disp_top
+ disp_height
;
4031 #ifdef TARGET_API_MAC_CARBON
4032 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0,
4033 kControlScrollBarProc
, 0L);
4035 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", 1, 0, 0, 0, scrollBarProc
,
4038 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4039 SetControlReference (ch
, (long) bar
);
4041 XSETWINDOW (bar
->window
, w
);
4042 XSETINT (bar
->top
, top
);
4043 XSETINT (bar
->left
, left
);
4044 XSETINT (bar
->width
, width
);
4045 XSETINT (bar
->height
, height
);
4046 XSETINT (bar
->start
, 0);
4047 XSETINT (bar
->end
, 0);
4048 bar
->dragging
= Qnil
;
4050 /* Add bar to its frame's list of scroll bars. */
4051 bar
->next
= FRAME_SCROLL_BARS (f
);
4053 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4054 if (!NILP (bar
->next
))
4055 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4062 /* Draw BAR's handle in the proper position.
4064 If the handle is already drawn from START to END, don't bother
4065 redrawing it, unless REBUILD is non-zero; in that case, always
4066 redraw it. (REBUILD is handy for drawing the handle after expose
4069 Normally, we want to constrain the start and end of the handle to
4070 fit inside its rectangle, but if the user is dragging the scroll
4071 bar handle, we want to let them drag it down all the way, so that
4072 the bar's top is as far down as it goes; otherwise, there's no way
4073 to move to the very end of the buffer. */
4076 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4077 struct scroll_bar
*bar
;
4081 int dragging
= ! NILP (bar
->dragging
);
4082 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4083 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4084 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4085 int length
= end
- start
;
4087 /* If the display is already accurate, do nothing. */
4089 && start
== XINT (bar
->start
)
4090 && end
== XINT (bar
->end
))
4095 /* Make sure the values are reasonable, and try to preserve the
4096 distance between start and end. */
4099 else if (start
> top_range
)
4101 end
= start
+ length
;
4105 else if (end
> top_range
&& ! dragging
)
4108 /* Store the adjusted setting in the scroll bar. */
4109 XSETINT (bar
->start
, start
);
4110 XSETINT (bar
->end
, end
);
4112 /* Clip the end position, just for display. */
4113 if (end
> top_range
)
4116 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4117 top positions, to make sure the handle is always at least that
4118 many pixels tall. */
4119 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4121 SetControlMinimum (ch
, 0);
4122 /* Don't inadvertently activate deactivated scroll bars */
4123 if (GetControlMaximum (ch
) != -1)
4124 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4126 SetControlValue (ch
, start
);
4127 #if TARGET_API_MAC_CARBON
4128 SetControlViewSize (ch
, end
- start
);
4135 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4139 x_scroll_bar_remove (bar
)
4140 struct scroll_bar
*bar
;
4142 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4146 /* Destroy the Mac scroll bar control */
4147 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4149 /* Disassociate this scroll bar from its window. */
4150 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4155 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4156 that we are displaying PORTION characters out of a total of WHOLE
4157 characters, starting at POSITION. If WINDOW has no scroll bar,
4160 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4162 int portion
, whole
, position
;
4164 struct frame
*f
= XFRAME (w
->frame
);
4165 struct scroll_bar
*bar
;
4166 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4167 int window_y
, window_height
;
4169 /* Get window dimensions. */
4170 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4175 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4177 height
= window_height
;
4179 /* Compute the left edge of the scroll bar area. */
4180 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4182 /* Compute the width of the scroll bar which might be less than
4183 the width of the area reserved for the scroll bar. */
4184 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4185 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4189 /* Compute the left edge of the scroll bar. */
4190 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4191 sb_left
= left
+ width
- sb_width
- (width
- sb_width
) / 2;
4193 sb_left
= left
+ (width
- sb_width
) / 2;
4195 /* Adjustments according to Inside Macintosh to make it look nice */
4197 disp_height
= height
;
4203 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4209 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4212 /* Does the scroll bar exist yet? */
4213 if (NILP (w
->vertical_scroll_bar
))
4216 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4217 left
, top
, width
, height
, 0);
4219 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4221 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4225 /* It may just need to be moved and resized. */
4228 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4229 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4233 /* If already correctly positioned, do nothing. */
4234 if (XINT (bar
->left
) == sb_left
4235 && XINT (bar
->top
) == top
4236 && XINT (bar
->width
) == sb_width
4237 && XINT (bar
->height
) == height
)
4241 /* Clear areas not covered by the scroll bar because it's not as
4242 wide as the area reserved for it . This makes sure a
4243 previous mode line display is cleared after C-x 2 C-x 1, for
4245 int area_width
= WINDOW_SCROLL_BAR_AREA_WIDTH (w
);
4246 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4247 left
, top
, area_width
, height
, 0);
4250 if (sb_left
+ sb_width
>= FRAME_PIXEL_WIDTH (f
))
4251 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4252 sb_left
- 1, top
, 1, height
, 0);
4256 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4257 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4261 /* Remember new settings. */
4262 XSETINT (bar
->left
, sb_left
);
4263 XSETINT (bar
->top
, top
);
4264 XSETINT (bar
->width
, sb_width
);
4265 XSETINT (bar
->height
, height
);
4271 /* Set the scroll bar's current state, unless we're currently being
4273 if (NILP (bar
->dragging
))
4275 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4278 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4281 int start
= ((double) position
* top_range
) / whole
;
4282 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4283 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4289 /* The following three hooks are used when we're doing a thorough
4290 redisplay of the frame. We don't explicitly know which scroll bars
4291 are going to be deleted, because keeping track of when windows go
4292 away is a real pain - "Can you say set-window-configuration, boys
4293 and girls?" Instead, we just assert at the beginning of redisplay
4294 that *all* scroll bars are to be removed, and then save a scroll bar
4295 from the fiery pit when we actually redisplay its window. */
4297 /* Arrange for all scroll bars on FRAME to be removed at the next call
4298 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4299 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4302 XTcondemn_scroll_bars (frame
)
4305 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4306 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4309 bar
= FRAME_SCROLL_BARS (frame
);
4310 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4311 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4312 XSCROLL_BAR (bar
)->prev
= Qnil
;
4313 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4314 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4315 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4320 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4321 Note that WINDOW isn't necessarily condemned at all. */
4324 XTredeem_scroll_bar (window
)
4325 struct window
*window
;
4327 struct scroll_bar
*bar
;
4329 /* We can't redeem this window's scroll bar if it doesn't have one. */
4330 if (NILP (window
->vertical_scroll_bar
))
4333 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4335 /* Unlink it from the condemned list. */
4337 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
4339 if (NILP (bar
->prev
))
4341 /* If the prev pointer is nil, it must be the first in one of
4343 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4344 /* It's not condemned. Everything's fine. */
4346 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4347 window
->vertical_scroll_bar
))
4348 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4350 /* If its prev pointer is nil, it must be at the front of
4351 one or the other! */
4355 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4357 if (! NILP (bar
->next
))
4358 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4360 bar
->next
= FRAME_SCROLL_BARS (f
);
4362 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4363 if (! NILP (bar
->next
))
4364 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4368 /* Remove all scroll bars on FRAME that haven't been saved since the
4369 last call to `*condemn_scroll_bars_hook'. */
4372 XTjudge_scroll_bars (f
)
4375 Lisp_Object bar
, next
;
4377 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4379 /* Clear out the condemned list now so we won't try to process any
4380 more events on the hapless scroll bars. */
4381 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4383 for (; ! NILP (bar
); bar
= next
)
4385 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4387 x_scroll_bar_remove (b
);
4390 b
->next
= b
->prev
= Qnil
;
4393 /* Now there should be no references to the condemned scroll bars,
4394 and they should get garbage-collected. */
4399 activate_scroll_bars (frame
)
4405 bar
= FRAME_SCROLL_BARS (frame
);
4406 while (! NILP (bar
))
4408 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4409 #ifdef TARGET_API_MAC_CARBON
4410 ActivateControl (ch
);
4412 SetControlMaximum (ch
,
4413 VERTICAL_SCROLL_BAR_TOP_RANGE (frame
,
4414 XINT (XSCROLL_BAR (bar
)
4417 bar
= XSCROLL_BAR (bar
)->next
;
4423 deactivate_scroll_bars (frame
)
4429 bar
= FRAME_SCROLL_BARS (frame
);
4430 while (! NILP (bar
))
4432 ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar
));
4433 #ifdef TARGET_API_MAC_CARBON
4434 DeactivateControl (ch
);
4436 SetControlMaximum (ch
, XINT (-1));
4438 bar
= XSCROLL_BAR (bar
)->next
;
4442 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4443 is set to something other than NO_EVENT, it is enqueued.
4445 This may be called from a signal handler, so we have to ignore GC
4449 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4450 struct scroll_bar
*bar
;
4453 struct input_event
*bufp
;
4455 int win_y
, top_range
;
4457 if (! GC_WINDOWP (bar
->window
))
4460 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4461 bufp
->frame_or_window
= bar
->window
;
4464 bar
->dragging
= Qnil
;
4468 case kControlUpButtonPart
:
4469 bufp
->part
= scroll_bar_up_arrow
;
4471 case kControlDownButtonPart
:
4472 bufp
->part
= scroll_bar_down_arrow
;
4474 case kControlPageUpPart
:
4475 bufp
->part
= scroll_bar_above_handle
;
4477 case kControlPageDownPart
:
4478 bufp
->part
= scroll_bar_below_handle
;
4480 #ifdef TARGET_API_MAC_CARBON
4483 case kControlIndicatorPart
:
4485 if (er
->what
== mouseDown
)
4486 bar
->dragging
= make_number (0);
4487 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4488 bufp
->part
= scroll_bar_handle
;
4492 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4493 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4495 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4499 if (! NILP (bar
->dragging
))
4500 win_y
-= XINT (bar
->dragging
);
4504 if (win_y
> top_range
)
4507 XSETINT (bufp
->x
, win_y
);
4508 XSETINT (bufp
->y
, top_range
);
4512 /* Handle some mouse motion while someone is dragging the scroll bar.
4514 This may be called from a signal handler, so we have to ignore GC
4518 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4519 struct scroll_bar
*bar
;
4523 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4525 last_mouse_movement_time
= t
;
4528 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4530 /* If we're dragging the bar, display it. */
4531 if (! GC_NILP (bar
->dragging
))
4533 /* Where should the handle be now? */
4534 int new_start
= y_pos
- 24;
4536 if (new_start
!= XINT (bar
->start
))
4538 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4540 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4546 /* Return information to the user about the current position of the
4547 mouse on the scroll bar. */
4550 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4552 Lisp_Object
*bar_window
;
4553 enum scroll_bar_part
*part
;
4555 unsigned long *time
;
4557 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4558 WindowPtr wp
= front_emacs_window ();
4560 struct frame
*f
= mac_window_to_frame (wp
);
4561 int win_y
, top_range
;
4563 SetPortWindowPort (wp
);
4565 GetMouse (&mouse_pos
);
4567 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4568 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4570 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4574 if (! NILP (bar
->dragging
))
4575 win_y
-= XINT (bar
->dragging
);
4579 if (win_y
> top_range
)
4583 *bar_window
= bar
->window
;
4585 if (! NILP (bar
->dragging
))
4586 *part
= scroll_bar_handle
;
4587 else if (win_y
< XINT (bar
->start
))
4588 *part
= scroll_bar_above_handle
;
4589 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4590 *part
= scroll_bar_handle
;
4592 *part
= scroll_bar_below_handle
;
4594 XSETINT (*x
, win_y
);
4595 XSETINT (*y
, top_range
);
4598 last_mouse_scroll_bar
= Qnil
;
4600 *time
= last_mouse_movement_time
;
4603 /***********************************************************************
4605 ***********************************************************************/
4607 /* Set clipping for output in glyph row ROW. W is the window in which
4608 we operate. GC is the graphics context to set clipping in.
4610 ROW may be a text row or, e.g., a mode line. Text rows must be
4611 clipped to the interior of the window dedicated to text display,
4612 mode lines must be clipped to the whole window. */
4615 x_clip_to_row (w
, row
, gc
)
4617 struct glyph_row
*row
;
4620 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4622 int window_y
, window_width
;
4624 window_box (w
, -1, 0, &window_y
, &window_width
, 0);
4626 clip_rect
.left
= WINDOW_TO_FRAME_PIXEL_X (w
, 0);
4627 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4628 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4629 clip_rect
.right
= clip_rect
.left
+ window_width
;
4630 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4632 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
), &clip_rect
);
4636 /* Draw a hollow box cursor on window W in glyph row ROW. */
4639 x_draw_hollow_cursor (w
, row
)
4641 struct glyph_row
*row
;
4643 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4644 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4645 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4648 struct glyph
*cursor_glyph
;
4651 /* Get the glyph the cursor is on. If we can't tell because
4652 the current matrix is invalid or such, give up. */
4653 cursor_glyph
= get_phys_cursor_glyph (w
);
4654 if (cursor_glyph
== NULL
)
4657 /* Compute the width of the rectangle to draw. If on a stretch
4658 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4659 rectangle as wide as the glyph, but use a canonical character
4661 wd
= cursor_glyph
->pixel_width
- 1;
4662 if (cursor_glyph
->type
== STRETCH_GLYPH
4663 && !x_stretch_cursor_p
)
4664 wd
= min (FRAME_COLUMN_WIDTH (f
), wd
);
4665 w
->phys_cursor_width
= wd
;
4667 /* Compute frame-relative coordinates from window-relative
4669 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
4670 y
= WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
);
4672 /* Compute the proper height and ascent of the rectangle, based
4673 on the actual glyph. Using the full height of the row looks
4674 bad when there are tall images on that row. */
4675 h
= max (min (FRAME_LINE_HEIGHT (f
), row
->height
),
4676 cursor_glyph
->ascent
+ cursor_glyph
->descent
);
4677 if (h
< row
->height
)
4678 y
+= row
->ascent
/* - w->phys_cursor_ascent */ + cursor_glyph
->descent
- h
;
4681 /* The foreground of cursor_gc is typically the same as the normal
4682 background color, which can cause the cursor box to be invisible. */
4683 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4684 if (dpyinfo
->scratch_cursor_gc
)
4685 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
4687 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
4688 GCForeground
, &xgcv
);
4689 gc
= dpyinfo
->scratch_cursor_gc
;
4691 /* Set clipping, draw the rectangle, and reset clipping again. */
4692 x_clip_to_row (w
, row
, gc
);
4693 mac_draw_rectangle (dpy
, FRAME_MAC_WINDOW (f
), gc
, x
, y
, wd
, h
);
4694 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4698 /* Draw a bar cursor on window W in glyph row ROW.
4700 Implementation note: One would like to draw a bar cursor with an
4701 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4702 Unfortunately, I didn't find a font yet that has this property set.
4706 x_draw_bar_cursor (w
, row
, width
, kind
)
4708 struct glyph_row
*row
;
4710 enum text_cursor_kinds kind
;
4712 struct frame
*f
= XFRAME (w
->frame
);
4713 struct glyph
*cursor_glyph
;
4715 /* If cursor is out of bounds, don't draw garbage. This can happen
4716 in mini-buffer windows when switching between echo area glyphs
4718 cursor_glyph
= get_phys_cursor_glyph (w
);
4719 if (cursor_glyph
== NULL
)
4722 /* If on an image, draw like a normal cursor. That's usually better
4723 visible than drawing a bar, esp. if the image is large so that
4724 the bar might not be in the window. */
4725 if (cursor_glyph
->type
== IMAGE_GLYPH
)
4727 struct glyph_row
*row
;
4728 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
4729 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
4733 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
4734 Window window
= FRAME_MAC_WINDOW (f
);
4735 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
4736 unsigned long mask
= GCForeground
| GCBackground
;
4737 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
4740 /* If the glyph's background equals the color we normally draw
4741 the bar cursor in, the bar cursor in its normal color is
4742 invisible. Use the glyph's foreground color instead in this
4743 case, on the assumption that the glyph's colors are chosen so
4744 that the glyph is legible. */
4745 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
4746 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
4748 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
4751 XChangeGC (dpy
, gc
, mask
, &xgcv
);
4754 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
4755 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
4759 width
= FRAME_CURSOR_WIDTH (f
);
4760 width
= min (cursor_glyph
->pixel_width
, width
);
4762 w
->phys_cursor_width
= width
;
4763 x_clip_to_row (w
, row
, gc
);
4765 if (kind
== BAR_CURSOR
)
4766 XFillRectangle (dpy
, window
, gc
,
4767 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4768 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
4769 width
, row
->height
);
4771 XFillRectangle (dpy
, window
, gc
,
4772 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
4773 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
4774 row
->height
- width
),
4775 cursor_glyph
->pixel_width
,
4778 mac_reset_clipping (dpy
, FRAME_MAC_WINDOW (f
));
4783 /* RIF: Define cursor CURSOR on frame F. */
4786 mac_define_frame_cursor (f
, cursor
)
4790 #if TARGET_API_MAC_CARBON
4791 SetThemeCursor (cursor
);
4793 SetCursor (*cursor
);
4798 /* RIF: Clear area on frame F. */
4801 mac_clear_frame_area (f
, x
, y
, width
, height
)
4803 int x
, y
, width
, height
;
4805 XClearArea (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
),
4806 x
, y
, width
, height
, 0);
4810 /* RIF: Draw cursor on window W. */
4813 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
4815 struct glyph_row
*glyph_row
;
4817 int cursor_type
, cursor_width
;
4822 w
->phys_cursor_type
= cursor_type
;
4823 w
->phys_cursor_on_p
= 1;
4825 if (glyph_row
->exact_window_width_line_p
4826 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
4828 glyph_row
->cursor_in_fringe_p
= 1;
4829 draw_fringe_bitmap (w
, glyph_row
, 0);
4832 switch (cursor_type
)
4834 case HOLLOW_BOX_CURSOR
:
4835 x_draw_hollow_cursor (w
, glyph_row
);
4838 case FILLED_BOX_CURSOR
:
4839 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
4843 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
4847 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
4851 w
->phys_cursor_width
= 0;
4863 #if 0 /* MAC_TODO: no icon support yet. */
4865 x_bitmap_icon (f
, icon
)
4871 if (FRAME_W32_WINDOW (f
) == 0)
4875 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
4876 else if (STRINGP (icon
))
4877 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
4878 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
4879 else if (SYMBOLP (icon
))
4883 if (EQ (icon
, intern ("application")))
4884 name
= (LPCTSTR
) IDI_APPLICATION
;
4885 else if (EQ (icon
, intern ("hand")))
4886 name
= (LPCTSTR
) IDI_HAND
;
4887 else if (EQ (icon
, intern ("question")))
4888 name
= (LPCTSTR
) IDI_QUESTION
;
4889 else if (EQ (icon
, intern ("exclamation")))
4890 name
= (LPCTSTR
) IDI_EXCLAMATION
;
4891 else if (EQ (icon
, intern ("asterisk")))
4892 name
= (LPCTSTR
) IDI_ASTERISK
;
4893 else if (EQ (icon
, intern ("winlogo")))
4894 name
= (LPCTSTR
) IDI_WINLOGO
;
4898 hicon
= LoadIcon (NULL
, name
);
4906 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
4911 #endif /* MAC_TODO */
4913 /************************************************************************
4915 ************************************************************************/
4917 /* Display Error Handling functions not used on W32. Listing them here
4918 helps diff stay in step when comparing w32term.c with xterm.c.
4920 x_error_catcher (display, error)
4921 x_catch_errors (dpy)
4922 x_catch_errors_unwind (old_val)
4923 x_check_errors (dpy, format)
4924 x_had_errors_p (dpy)
4925 x_clear_errors (dpy)
4926 x_uncatch_errors (dpy, count)
4928 x_connection_signal (signalnum)
4929 x_connection_closed (dpy, error_message)
4930 x_error_quitter (display, error)
4931 x_error_handler (display, error)
4932 x_io_error_quitter (display)
4937 /* Changing the font of the frame. */
4939 /* Give frame F the font named FONTNAME as its default font, and
4940 return the full name of that font. FONTNAME may be a wildcard
4941 pattern; in that case, we choose some font that fits the pattern.
4942 The return value shows which font we chose. */
4945 x_new_font (f
, fontname
)
4947 register char *fontname
;
4949 struct font_info
*fontp
4950 = FS_LOAD_FONT (f
, 0, fontname
, -1);
4955 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
4956 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
4957 FRAME_FONTSET (f
) = -1;
4959 FRAME_COLUMN_WIDTH (f
) = FONT_WIDTH (FRAME_FONT (f
));
4960 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
4962 compute_fringe_widths (f
, 1);
4964 /* Compute the scroll bar width in character columns. */
4965 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
4967 int wid
= FRAME_COLUMN_WIDTH (f
);
4968 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
4969 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
4973 int wid
= FRAME_COLUMN_WIDTH (f
);
4974 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
4977 /* Now make the frame display the given font. */
4978 if (FRAME_MAC_WINDOW (f
) != 0)
4980 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
4982 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
4984 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
4987 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
4988 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
4991 return build_string (fontp
->full_name
);
4994 /* Give frame F the fontset named FONTSETNAME as its default font, and
4995 return the full name of that fontset. FONTSETNAME may be a wildcard
4996 pattern; in that case, we choose some fontset that fits the pattern.
4997 The return value shows which fontset we chose. */
5000 x_new_fontset (f
, fontsetname
)
5004 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5010 if (FRAME_FONTSET (f
) == fontset
)
5011 /* This fontset is already set in frame F. There's nothing more
5013 return fontset_name (fontset
);
5015 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5017 if (!STRINGP (result
))
5018 /* Can't load ASCII font. */
5021 /* Since x_new_font doesn't update any fontset information, do it now. */
5022 FRAME_FONTSET(f
) = fontset
;
5024 return build_string (fontsetname
);
5028 /***********************************************************************
5029 TODO: W32 Input Methods
5030 ***********************************************************************/
5031 /* Listing missing functions from xterm.c helps diff stay in step.
5033 xim_destroy_callback (xim, client_data, call_data)
5034 xim_open_dpy (dpyinfo, resource_name)
5036 xim_instantiate_callback (display, client_data, call_data)
5037 xim_initialize (dpyinfo, resource_name)
5038 xim_close_dpy (dpyinfo)
5044 mac_get_window_bounds (f
, inner
, outer
)
5046 Rect
*inner
, *outer
;
5048 #if TARGET_API_MAC_CARBON
5049 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5050 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5051 #else /* not TARGET_API_MAC_CARBON */
5052 RgnHandle region
= NewRgn ();
5054 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5055 *inner
= (*region
)->rgnBBox
;
5056 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5057 *outer
= (*region
)->rgnBBox
;
5058 DisposeRgn (region
);
5059 #endif /* not TARGET_API_MAC_CARBON */
5063 /* Calculate the absolute position in frame F
5064 from its current recorded position values and gravity. */
5067 x_calc_absolute_position (f
)
5070 int width_diff
= 0, height_diff
= 0;
5071 int flags
= f
->size_hint_flags
;
5074 /* We have nothing to do if the current position
5075 is already for the top-left corner. */
5076 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5079 /* Find the offsets of the outside upper-left corner of
5080 the inner window, with respect to the outer window. */
5081 mac_get_window_bounds (f
, &inner
, &outer
);
5083 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5084 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5086 /* Treat negative positions as relative to the leftmost bottommost
5087 position that fits on the screen. */
5088 if (flags
& XNegative
)
5089 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5091 - FRAME_PIXEL_WIDTH (f
)
5094 if (flags
& YNegative
)
5095 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5097 - FRAME_PIXEL_HEIGHT (f
)
5100 /* The left_pos and top_pos
5101 are now relative to the top and left screen edges,
5102 so the flags should correspond. */
5103 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5106 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5107 to really change the position, and 0 when calling from
5108 x_make_frame_visible (in that case, XOFF and YOFF are the current
5109 position values). It is -1 when calling from x_set_frame_parameters,
5110 which means, do adjust for borders but don't change the gravity. */
5113 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5115 register int xoff
, yoff
;
5118 if (change_gravity
> 0)
5122 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5124 f
->size_hint_flags
|= XNegative
;
5126 f
->size_hint_flags
|= YNegative
;
5127 f
->win_gravity
= NorthWestGravity
;
5129 x_calc_absolute_position (f
);
5132 x_wm_set_size_hint (f
, (long) 0, 0);
5134 #if TARGET_API_MAC_CARBON
5135 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5136 /* If the title bar is completely outside the screen, adjust the
5138 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5139 kWindowConstrainMoveRegardlessOfFit
5140 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5141 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5144 Rect inner
, outer
, screen_rect
, dummy
;
5145 RgnHandle region
= NewRgn ();
5147 mac_get_window_bounds (f
, &inner
, &outer
);
5148 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5149 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5150 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5151 f
->top_pos
+ f
->y_pixels_diff
, false);
5153 /* If the title bar is completely outside the screen, adjust the
5154 position. The variable `outer' holds the title bar rectangle.
5155 The variable `inner' holds slightly smaller one than `outer',
5156 so that the calculation of overlapping may not become too
5158 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5159 outer
= (*region
)->rgnBBox
;
5160 DisposeRgn (region
);
5162 InsetRect (&inner
, 8, 8);
5163 screen_rect
= qd
.screenBits
.bounds
;
5164 screen_rect
.top
+= GetMBarHeight ();
5166 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5168 if (inner
.right
<= screen_rect
.left
)
5169 f
->left_pos
= screen_rect
.left
;
5170 else if (inner
.left
>= screen_rect
.right
)
5171 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5173 if (inner
.bottom
<= screen_rect
.top
)
5174 f
->top_pos
= screen_rect
.top
;
5175 else if (inner
.top
>= screen_rect
.bottom
)
5176 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5178 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5179 f
->top_pos
+ f
->y_pixels_diff
, false);
5187 /* Call this to change the size of frame F's x-window.
5188 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5189 for this size change and subsequent size changes.
5190 Otherwise we leave the window gravity unchanged. */
5193 x_set_window_size (f
, change_gravity
, cols
, rows
)
5198 int pixelwidth
, pixelheight
;
5202 check_frame_size (f
, &rows
, &cols
);
5203 f
->scroll_bar_actual_width
5204 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5206 compute_fringe_widths (f
, 0);
5208 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5209 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5211 f
->win_gravity
= NorthWestGravity
;
5212 x_wm_set_size_hint (f
, (long) 0, 0);
5214 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5216 /* Now, strictly speaking, we can't be sure that this is accurate,
5217 but the window manager will get around to dealing with the size
5218 change request eventually, and we'll hear how it went when the
5219 ConfigureNotify event gets here.
5221 We could just not bother storing any of this information here,
5222 and let the ConfigureNotify event set everything up, but that
5223 might be kind of confusing to the Lisp code, since size changes
5224 wouldn't be reported in the frame parameters until some random
5225 point in the future when the ConfigureNotify event arrives.
5227 We pass 1 for DELAY since we can't run Lisp code inside of
5229 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5230 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5231 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5233 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5234 receive in the ConfigureNotify event; if we get what we asked
5235 for, then the event won't cause the screen to become garbaged, so
5236 we have to make sure to do it here. */
5237 SET_FRAME_GARBAGED (f
);
5239 XFlush (FRAME_X_DISPLAY (f
));
5241 /* If cursor was outside the new size, mark it as off. */
5242 mark_window_cursors_off (XWINDOW (f
->root_window
));
5244 /* Clear out any recollection of where the mouse highlighting was,
5245 since it might be in a place that's outside the new frame size.
5246 Actually checking whether it is outside is a pain in the neck,
5247 so don't try--just let the highlighting be done afresh with new size. */
5248 cancel_mouse_face (f
);
5253 /* Mouse warping. */
5255 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5258 x_set_mouse_position (f
, x
, y
)
5264 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5265 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5267 if (pix_x
< 0) pix_x
= 0;
5268 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5270 if (pix_y
< 0) pix_y
= 0;
5271 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5273 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5277 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5281 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5284 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5285 0, 0, 0, 0, pix_x
, pix_y
);
5291 /* focus shifting, raising and lowering. */
5294 x_focus_on_frame (f
)
5297 #if 0 /* This proves to be unpleasant. */
5301 /* I don't think that the ICCCM allows programs to do things like this
5302 without the interaction of the window manager. Whatever you end up
5303 doing with this code, do it to x_unfocus_frame too. */
5304 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5305 RevertToPointerRoot
, CurrentTime
);
5315 /* Raise frame F. */
5320 if (f
->async_visible
)
5321 SelectWindow (FRAME_MAC_WINDOW (f
));
5324 /* Lower frame F. */
5329 if (f
->async_visible
)
5330 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5334 XTframe_raise_lower (f
, raise_flag
)
5344 /* Change of visibility. */
5346 /* This tries to wait until the frame is really visible.
5347 However, if the window manager asks the user where to position
5348 the frame, this will return before the user finishes doing that.
5349 The frame will not actually be visible at that time,
5350 but it will become visible later when the window manager
5351 finishes with it. */
5354 x_make_frame_visible (f
)
5358 int original_top
, original_left
;
5362 if (! FRAME_VISIBLE_P (f
))
5364 /* We test FRAME_GARBAGED_P here to make sure we don't
5365 call x_set_offset a second time
5366 if we get to x_make_frame_visible a second time
5367 before the window gets really visible. */
5368 if (! FRAME_ICONIFIED_P (f
)
5369 && ! f
->output_data
.mac
->asked_for_visible
)
5370 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5372 f
->output_data
.mac
->asked_for_visible
= 1;
5374 ShowWindow (FRAME_MAC_WINDOW (f
));
5377 XFlush (FRAME_MAC_DISPLAY (f
));
5379 /* Synchronize to ensure Emacs knows the frame is visible
5380 before we do anything else. We do this loop with input not blocked
5381 so that incoming events are handled. */
5386 /* This must come after we set COUNT. */
5389 XSETFRAME (frame
, f
);
5391 /* Wait until the frame is visible. Process X events until a
5392 MapNotify event has been seen, or until we think we won't get a
5393 MapNotify at all.. */
5394 for (count
= input_signal_count
+ 10;
5395 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5397 /* Force processing of queued events. */
5400 /* Machines that do polling rather than SIGIO have been
5401 observed to go into a busy-wait here. So we'll fake an
5402 alarm signal to let the handler know that there's something
5403 to be read. We used to raise a real alarm, but it seems
5404 that the handler isn't always enabled here. This is
5406 if (input_polling_used ())
5408 /* It could be confusing if a real alarm arrives while
5409 processing the fake one. Turn it off and let the
5410 handler reset it. */
5411 extern void poll_for_input_1
P_ ((void));
5412 int old_poll_suppress_count
= poll_suppress_count
;
5413 poll_suppress_count
= 1;
5414 poll_for_input_1 ();
5415 poll_suppress_count
= old_poll_suppress_count
;
5418 /* See if a MapNotify event has been processed. */
5419 FRAME_SAMPLE_VISIBILITY (f
);
5424 /* Change from mapped state to withdrawn state. */
5426 /* Make the frame visible (mapped and not iconified). */
5429 x_make_frame_invisible (f
)
5432 /* Don't keep the highlight on an invisible frame. */
5433 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5434 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5438 HideWindow (FRAME_MAC_WINDOW (f
));
5440 /* We can't distinguish this from iconification
5441 just by the event that we get from the server.
5442 So we can't win using the usual strategy of letting
5443 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5444 and synchronize with the server to make sure we agree. */
5446 FRAME_ICONIFIED_P (f
) = 0;
5447 f
->async_visible
= 0;
5448 f
->async_iconified
= 0;
5453 /* Change window state from mapped to iconified. */
5459 /* Don't keep the highlight on an invisible frame. */
5460 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5461 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5464 /* Review: Since window is still visible in dock, still allow updates? */
5465 if (f
->async_iconified
)
5471 CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5477 /* Free X resources of frame F. */
5480 x_free_frame_resources (f
)
5483 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5484 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5489 if (wp
== tip_window
)
5490 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5491 closed' event. So we reset tip_window here. */
5494 free_frame_menubar (f
);
5496 if (FRAME_FACE_CACHE (f
))
5497 free_frame_faces (f
);
5501 xfree (f
->output_data
.mac
);
5502 f
->output_data
.mac
= NULL
;
5504 if (f
== dpyinfo
->x_focus_frame
)
5505 dpyinfo
->x_focus_frame
= 0;
5506 if (f
== dpyinfo
->x_focus_event_frame
)
5507 dpyinfo
->x_focus_event_frame
= 0;
5508 if (f
== dpyinfo
->x_highlight_frame
)
5509 dpyinfo
->x_highlight_frame
= 0;
5511 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5513 dpyinfo
->mouse_face_beg_row
5514 = dpyinfo
->mouse_face_beg_col
= -1;
5515 dpyinfo
->mouse_face_end_row
5516 = dpyinfo
->mouse_face_end_col
= -1;
5517 dpyinfo
->mouse_face_window
= Qnil
;
5518 dpyinfo
->mouse_face_deferred_gc
= 0;
5519 dpyinfo
->mouse_face_mouse_frame
= 0;
5526 /* Destroy the X window of frame F. */
5529 x_destroy_window (f
)
5532 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5534 x_free_frame_resources (f
);
5536 dpyinfo
->reference_count
--;
5540 /* Setting window manager hints. */
5542 /* Set the normal size hints for the window manager, for frame F.
5543 FLAGS is the flags word to use--or 0 meaning preserve the flags
5544 that the window now has.
5545 If USER_POSITION is nonzero, we set the USPosition
5546 flag (this is useful when FLAGS is 0). */
5548 x_wm_set_size_hint (f
, flags
, user_position
)
5553 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5554 XSizeHints size_hints
;
5556 #ifdef USE_X_TOOLKIT
5559 Dimension widget_width
, widget_height
;
5560 Window window
= XtWindow (f
->output_data
.x
->widget
);
5561 #else /* not USE_X_TOOLKIT */
5562 Window window
= FRAME_X_WINDOW (f
);
5563 #endif /* not USE_X_TOOLKIT */
5565 /* Setting PMaxSize caused various problems. */
5566 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5568 size_hints
.x
= f
->left_pos
;
5569 size_hints
.y
= f
->top_pos
;
5571 #ifdef USE_X_TOOLKIT
5572 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5573 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5574 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5575 size_hints
.height
= widget_height
;
5576 size_hints
.width
= widget_width
;
5577 #else /* not USE_X_TOOLKIT */
5578 size_hints
.height
= FRAME_PIXEL_HEIGHT (f
);
5579 size_hints
.width
= FRAME_PIXEL_WIDTH (f
);
5580 #endif /* not USE_X_TOOLKIT */
5582 size_hints
.width_inc
= FRAME_COLUMN_WIDTH (f
);
5583 size_hints
.height_inc
= FRAME_LINE_HEIGHT (f
);
5584 size_hints
.max_width
5585 = FRAME_X_DISPLAY_INFO (f
)->width
- FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5586 size_hints
.max_height
5587 = FRAME_X_DISPLAY_INFO (f
)->height
- FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5589 /* Calculate the base and minimum sizes.
5591 (When we use the X toolkit, we don't do it here.
5592 Instead we copy the values that the widgets are using, below.) */
5593 #ifndef USE_X_TOOLKIT
5595 int base_width
, base_height
;
5596 int min_rows
= 0, min_cols
= 0;
5598 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
5599 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
5601 check_frame_size (f
, &min_rows
, &min_cols
);
5603 /* The window manager uses the base width hints to calculate the
5604 current number of rows and columns in the frame while
5605 resizing; min_width and min_height aren't useful for this
5606 purpose, since they might not give the dimensions for a
5607 zero-row, zero-column frame.
5609 We use the base_width and base_height members if we have
5610 them; otherwise, we set the min_width and min_height members
5611 to the size for a zero x zero frame. */
5614 size_hints
.flags
|= PBaseSize
;
5615 size_hints
.base_width
= base_width
;
5616 size_hints
.base_height
= base_height
;
5617 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5618 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5620 size_hints
.min_width
= base_width
;
5621 size_hints
.min_height
= base_height
;
5625 /* If we don't need the old flags, we don't need the old hint at all. */
5628 size_hints
.flags
|= flags
;
5631 #endif /* not USE_X_TOOLKIT */
5634 XSizeHints hints
; /* Sometimes I hate X Windows... */
5635 long supplied_return
;
5639 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
5642 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
5645 #ifdef USE_X_TOOLKIT
5646 size_hints
.base_height
= hints
.base_height
;
5647 size_hints
.base_width
= hints
.base_width
;
5648 size_hints
.min_height
= hints
.min_height
;
5649 size_hints
.min_width
= hints
.min_width
;
5653 size_hints
.flags
|= flags
;
5658 if (hints
.flags
& PSize
)
5659 size_hints
.flags
|= PSize
;
5660 if (hints
.flags
& PPosition
)
5661 size_hints
.flags
|= PPosition
;
5662 if (hints
.flags
& USPosition
)
5663 size_hints
.flags
|= USPosition
;
5664 if (hints
.flags
& USSize
)
5665 size_hints
.flags
|= USSize
;
5669 #ifndef USE_X_TOOLKIT
5674 size_hints
.win_gravity
= f
->win_gravity
;
5675 size_hints
.flags
|= PWinGravity
;
5679 size_hints
.flags
&= ~ PPosition
;
5680 size_hints
.flags
|= USPosition
;
5682 #endif /* PWinGravity */
5685 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5687 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
5689 #endif /* MAC_TODO */
5692 #if 0 /* MAC_TODO: hide application instead of iconify? */
5693 /* Used for IconicState or NormalState */
5696 x_wm_set_window_state (f
, state
)
5700 #ifdef USE_X_TOOLKIT
5703 XtSetArg (al
[0], XtNinitialState
, state
);
5704 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5705 #else /* not USE_X_TOOLKIT */
5706 Window window
= FRAME_X_WINDOW (f
);
5708 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
5709 f
->output_data
.x
->wm_hints
.initial_state
= state
;
5711 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5712 #endif /* not USE_X_TOOLKIT */
5716 x_wm_set_icon_pixmap (f
, pixmap_id
)
5722 #ifndef USE_X_TOOLKIT
5723 Window window
= FRAME_X_WINDOW (f
);
5728 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
5729 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
5733 /* It seems there is no way to turn off use of an icon pixmap.
5734 The following line does it, only if no icon has yet been created,
5735 for some window managers. But with mwm it crashes.
5736 Some people say it should clear the IconPixmapHint bit in this case,
5737 but that doesn't work, and the X consortium said it isn't the
5738 right thing at all. Since there is no way to win,
5739 best to explicitly give up. */
5741 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
5747 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5751 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
5752 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
5755 #else /* not USE_X_TOOLKIT */
5757 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
5758 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5760 #endif /* not USE_X_TOOLKIT */
5763 #endif /* MAC_TODO */
5766 x_wm_set_icon_position (f
, icon_x
, icon_y
)
5770 #if 0 /* MAC_TODO: no icons on Mac */
5771 #ifdef USE_X_TOOLKIT
5772 Window window
= XtWindow (f
->output_data
.x
->widget
);
5774 Window window
= FRAME_X_WINDOW (f
);
5777 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
5778 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
5779 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
5781 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
5782 #endif /* MAC_TODO */
5786 /***********************************************************************
5788 ***********************************************************************/
5790 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5793 x_get_font_info (f
, font_idx
)
5797 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
5800 /* the global font name table */
5801 char **font_name_table
= NULL
;
5802 int font_name_table_size
= 0;
5803 int font_name_count
= 0;
5806 /* compare two strings ignoring case */
5808 stricmp (const char *s
, const char *t
)
5810 for ( ; tolower (*s
) == tolower (*t
); s
++, t
++)
5813 return tolower (*s
) - tolower (*t
);
5816 /* compare two strings ignoring case and handling wildcard */
5818 wildstrieq (char *s1
, char *s2
)
5820 if (strcmp (s1
, "*") == 0 || strcmp (s2
, "*") == 0)
5823 return stricmp (s1
, s2
) == 0;
5826 /* Assume parameter 1 is fully qualified, no wildcards. */
5828 mac_font_pattern_match (fontname
, pattern
)
5832 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
5833 char *font_name_copy
= (char *) alloca (strlen (fontname
) + 1);
5836 /* Copy fontname so we can modify it during comparison. */
5837 strcpy (font_name_copy
, fontname
);
5842 /* Turn pattern into a regexp and do a regexp match. */
5843 for (; *pattern
; pattern
++)
5845 if (*pattern
== '?')
5847 else if (*pattern
== '*')
5858 return (fast_c_string_match_ignore_case (build_string (regex
),
5859 font_name_copy
) >= 0);
5862 /* Two font specs are considered to match if their foundry, family,
5863 weight, slant, and charset match. */
5865 mac_font_match (char *mf
, char *xf
)
5867 char m_foundry
[50], m_family
[50], m_weight
[20], m_slant
[2], m_charset
[20];
5868 char x_foundry
[50], x_family
[50], x_weight
[20], x_slant
[2], x_charset
[20];
5870 if (sscanf (mf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5871 m_foundry
, m_family
, m_weight
, m_slant
, m_charset
) != 5)
5872 return mac_font_pattern_match (mf
, xf
);
5874 if (sscanf (xf
, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5875 x_foundry
, x_family
, x_weight
, x_slant
, x_charset
) != 5)
5876 return mac_font_pattern_match (mf
, xf
);
5878 return (wildstrieq (m_foundry
, x_foundry
)
5879 && wildstrieq (m_family
, x_family
)
5880 && wildstrieq (m_weight
, x_weight
)
5881 && wildstrieq (m_slant
, x_slant
)
5882 && wildstrieq (m_charset
, x_charset
))
5883 || mac_font_pattern_match (mf
, xf
);
5887 static Lisp_Object Qbig5
, Qcn_gb
, Qsjis
, Qeuc_kr
;
5890 decode_mac_font_name (char *name
, int size
, short scriptcode
)
5892 Lisp_Object coding_system
;
5893 struct coding_system coding
;
5899 coding_system
= Qbig5
;
5902 coding_system
= Qcn_gb
;
5905 coding_system
= Qsjis
;
5908 coding_system
= Qeuc_kr
;
5914 setup_coding_system (coding_system
, &coding
);
5915 coding
.src_multibyte
= 0;
5916 coding
.dst_multibyte
= 1;
5917 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
5918 coding
.composing
= COMPOSITION_DISABLED
;
5919 buf
= (char *) alloca (size
);
5921 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
5922 bcopy (buf
, name
, coding
.produced
);
5923 name
[coding
.produced
] = '\0';
5928 mac_to_x_fontname (char *name
, int size
, Style style
, short scriptcode
)
5930 char foundry
[32], family
[32], cs
[32];
5931 char xf
[256], *result
, *p
;
5933 if (sscanf (name
, "%31[^-]-%31[^-]-%31s", foundry
, family
, cs
) != 3)
5935 strcpy(foundry
, "Apple");
5936 strcpy(family
, name
);
5941 strcpy(cs
, "big5-0");
5944 strcpy(cs
, "gb2312.1980-0");
5947 strcpy(cs
, "jisx0208.1983-sjis");
5950 /* Each Apple Japanese font is entered into the font table
5951 twice: once as a jisx0208.1983-sjis font and once as a
5952 jisx0201.1976-0 font. The latter can be used to display
5953 the ascii charset and katakana-jisx0201 charset. A
5954 negative script code signals that the name of this latter
5955 font is being built. */
5956 strcpy(cs
, "jisx0201.1976-0");
5959 strcpy(cs
, "ksc5601.1989-0");
5962 strcpy(cs
, "mac-roman");
5967 sprintf(xf
, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5968 foundry
, family
, style
& bold
? "bold" : "medium",
5969 style
& italic
? 'i' : 'r', size
, size
* 10, size
* 10, cs
);
5971 result
= (char *) xmalloc (strlen (xf
) + 1);
5972 strcpy (result
, xf
);
5973 for (p
= result
; *p
; p
++)
5979 /* Convert an X font spec to the corresponding mac font name, which
5980 can then be passed to GetFNum after conversion to a Pascal string.
5981 For ordinary Mac fonts, this should just be their names, like
5982 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5983 collection contain their charset designation in their names, like
5984 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5985 names are handled accordingly. */
5987 x_font_name_to_mac_font_name (char *xf
, char *mf
)
5989 char foundry
[32], family
[32], weight
[20], slant
[2], cs
[32];
5990 Lisp_Object coding_system
= Qnil
;
5991 struct coding_system coding
;
5995 if (sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5996 foundry
, family
, weight
, slant
, cs
) != 5 &&
5997 sscanf (xf
, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
5998 foundry
, family
, weight
, slant
, cs
) != 5)
6001 if (strcmp (cs
, "big5-0") == 0)
6002 coding_system
= Qbig5
;
6003 else if (strcmp (cs
, "gb2312.1980-0") == 0)
6004 coding_system
= Qcn_gb
;
6005 else if (strcmp (cs
, "jisx0208.1983-sjis") == 0
6006 || strcmp (cs
, "jisx0201.1976-0") == 0)
6007 coding_system
= Qsjis
;
6008 else if (strcmp (cs
, "ksc5601.1989-0") == 0)
6009 coding_system
= Qeuc_kr
;
6010 else if (strcmp (cs
, "mac-roman") == 0)
6011 strcpy (mf
, family
);
6013 sprintf (mf
, "%s-%s-%s", foundry
, family
, cs
);
6015 if (!NILP (coding_system
))
6017 setup_coding_system (coding_system
, &coding
);
6018 coding
.src_multibyte
= 1;
6019 coding
.dst_multibyte
= 1;
6020 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6021 encode_coding (&coding
, family
, mf
, strlen (family
), sizeof (Str32
) - 1);
6022 mf
[coding
.produced
] = '\0';
6028 add_font_name_table_entry (char *font_name
)
6030 if (font_name_table_size
== 0)
6032 font_name_table_size
= 16;
6033 font_name_table
= (char **)
6034 xmalloc (font_name_table_size
* sizeof (char *));
6036 else if (font_name_count
+ 1 >= font_name_table_size
)
6038 font_name_table_size
+= 16;
6039 font_name_table
= (char **)
6040 xrealloc (font_name_table
,
6041 font_name_table_size
* sizeof (char *));
6044 font_name_table
[font_name_count
++] = font_name
;
6047 /* Sets up the table font_name_table to contain the list of all fonts
6048 in the system the first time the table is used so that the Resource
6049 Manager need not be accessed every time this information is
6053 init_font_name_table ()
6055 #if TARGET_API_MAC_CARBON
6058 if (Gestalt (gestaltSystemVersion
, &sv
) == noErr
&& sv
>= 0x1000)
6060 FMFontFamilyIterator ffi
;
6061 FMFontFamilyInstanceIterator ffii
;
6064 /* Create a dummy instance iterator here to avoid creating and
6065 destroying it in the loop. */
6066 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6068 /* Create an iterator to enumerate the font families. */
6069 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6072 FMDisposeFontFamilyInstanceIterator (&ffii
);
6076 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6084 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6090 sc
= FontToScript (ff
);
6091 decode_mac_font_name (name
, sizeof (name
), sc
);
6093 /* Point the instance iterator at the current font family. */
6094 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6097 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6100 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6101 contained in Apple Japanese (SJIS) font. */
6105 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6107 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6109 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6111 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6116 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6118 if (sc
== smJapanese
)
6123 else if (sc
== -smJapanese
)
6128 /* Dispose of the iterators. */
6129 FMDisposeFontFamilyIterator (&ffi
);
6130 FMDisposeFontFamilyInstanceIterator (&ffii
);
6134 #endif /* TARGET_API_MAC_CARBON */
6136 SInt16 fontnum
, old_fontnum
;
6137 int num_mac_fonts
= CountResources('FOND');
6139 Handle font_handle
, font_handle_2
;
6140 short id
, scriptcode
;
6143 struct FontAssoc
*fat
;
6144 struct AsscEntry
*assc_entry
;
6146 GetPort (&port
); /* save the current font number used */
6147 #if TARGET_API_MAC_CARBON
6148 old_fontnum
= GetPortTextFont (port
);
6150 old_fontnum
= port
->txFont
;
6153 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6155 font_handle
= GetIndResource ('FOND', i
);
6159 GetResInfo (font_handle
, &id
, &type
, name
);
6160 GetFNum (name
, &fontnum
);
6166 scriptcode
= FontToScript (fontnum
);
6167 decode_mac_font_name (name
, sizeof (name
), scriptcode
);
6170 HLock (font_handle
);
6172 if (GetResourceSizeOnDisk (font_handle
)
6173 >= sizeof (struct FamRec
))
6175 fat
= (struct FontAssoc
*) (*font_handle
6176 + sizeof (struct FamRec
));
6178 = (struct AsscEntry
*) (*font_handle
6179 + sizeof (struct FamRec
)
6180 + sizeof (struct FontAssoc
));
6182 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6184 if (font_name_table_size
== 0)
6186 font_name_table_size
= 16;
6187 font_name_table
= (char **)
6188 xmalloc (font_name_table_size
* sizeof (char *));
6190 else if (font_name_count
>= font_name_table_size
)
6192 font_name_table_size
+= 16;
6193 font_name_table
= (char **)
6194 xrealloc (font_name_table
,
6195 font_name_table_size
* sizeof (char *));
6197 font_name_table
[font_name_count
++]
6198 = mac_to_x_fontname (name
,
6199 assc_entry
->fontSize
,
6200 assc_entry
->fontStyle
,
6202 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6203 parts are contained in Apple Japanese (SJIS)
6205 if (smJapanese
== scriptcode
)
6207 font_name_table
[font_name_count
++]
6208 = mac_to_x_fontname (name
,
6209 assc_entry
->fontSize
,
6210 assc_entry
->fontStyle
,
6216 HUnlock (font_handle
);
6217 font_handle_2
= GetNextFOND (font_handle
);
6218 ReleaseResource (font_handle
);
6219 font_handle
= font_handle_2
;
6221 while (ResError () == noErr
&& font_handle
);
6224 TextFont (old_fontnum
);
6225 #if TARGET_API_MAC_CARBON
6227 #endif /* TARGET_API_MAC_CARBON */
6231 enum xlfd_scalable_field_index
6233 XLFD_SCL_PIXEL_SIZE
,
6234 XLFD_SCL_POINT_SIZE
,
6239 static int xlfd_scalable_fields
[] =
6248 mac_do_list_fonts (pattern
, maxnames
)
6253 Lisp_Object font_list
= Qnil
, pattern_regex
, fontname
;
6254 char *regex
= (char *) alloca (strlen (pattern
) * 2 + 3);
6257 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6259 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
6262 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6263 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6264 fonts are scaled according to the specified size. */
6267 field
= xlfd_scalable_fields
;
6275 if ('1' <= *ptr
&& *ptr
<= '9')
6277 *val
= *ptr
++ - '0';
6278 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
6279 *val
= *val
* 10 + *ptr
++ - '0';
6286 ptr
= strchr (ptr
, '-');
6289 while (ptr
&& i
< 14);
6291 if (i
== 14 && ptr
== NULL
)
6293 if (scl_val
[XLFD_SCL_POINT_SIZE
] > 0)
6295 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_POINT_SIZE
] / 10;
6296 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_POINT_SIZE
];
6298 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0)
6300 scl_val
[XLFD_SCL_POINT_SIZE
] =
6301 scl_val
[XLFD_SCL_AVGWIDTH
] = scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10;
6303 else if (scl_val
[XLFD_SCL_AVGWIDTH
] > 0)
6305 scl_val
[XLFD_SCL_PIXEL_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
] / 10;
6306 scl_val
[XLFD_SCL_POINT_SIZE
] = scl_val
[XLFD_SCL_AVGWIDTH
];
6310 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
6315 /* Turn pattern into a regexp and do a regexp match. */
6316 for (; *pattern
; pattern
++)
6318 if (*pattern
== '?')
6320 else if (*pattern
== '*')
6326 *ptr
++ = tolower (*pattern
);
6331 pattern_regex
= build_string (regex
);
6333 for (i
= 0; i
< font_name_count
; i
++)
6335 fontname
= build_string (font_name_table
[i
]);
6336 if (fast_string_match (pattern_regex
, fontname
) >= 0)
6338 font_list
= Fcons (fontname
, font_list
);
6341 if (maxnames
> 0 && n_fonts
>= maxnames
)
6344 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
6345 && (ptr
= strstr (font_name_table
[i
], "-0-0-75-75-m-0-")))
6347 int former_len
= ptr
- font_name_table
[i
];
6349 memcpy (scaled
, font_name_table
[i
], former_len
);
6350 sprintf (scaled
+ former_len
,
6351 "-%d-%d-75-75-m-%d-%s",
6352 scl_val
[XLFD_SCL_PIXEL_SIZE
],
6353 scl_val
[XLFD_SCL_POINT_SIZE
],
6354 scl_val
[XLFD_SCL_AVGWIDTH
],
6355 ptr
+ sizeof ("-0-0-75-75-m-0-") - 1);
6356 fontname
= build_string (scaled
);
6357 if (fast_string_match (pattern_regex
, fontname
) >= 0)
6359 font_list
= Fcons (fontname
, font_list
);
6362 if (maxnames
> 0 && n_fonts
>= maxnames
)
6370 /* Return a list of at most MAXNAMES font specs matching the one in
6371 PATTERN. Cache matching fonts for patterns in
6372 dpyinfo->name_list_element to avoid looking them up again by
6373 calling mac_font_pattern_match (slow). Return as many matching
6374 fonts as possible if MAXNAMES = -1. */
6377 x_list_fonts (struct frame
*f
,
6378 Lisp_Object pattern
,
6382 Lisp_Object newlist
= Qnil
, tem
, key
;
6383 struct mac_display_info
*dpyinfo
= f
? FRAME_MAC_DISPLAY_INFO (f
) : NULL
;
6385 if (font_name_table
== NULL
) /* Initialize when first used. */
6386 init_font_name_table ();
6390 tem
= XCDR (dpyinfo
->name_list_element
);
6391 key
= Fcons (pattern
, make_number (maxnames
));
6393 newlist
= Fassoc (key
, tem
);
6394 if (!NILP (newlist
))
6396 newlist
= Fcdr_safe (newlist
);
6401 newlist
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
6403 /* MAC_TODO: add code for matching outline fonts here */
6407 XSETCDR (dpyinfo
->name_list_element
,
6408 Fcons (Fcons (key
, newlist
),
6409 XCDR (dpyinfo
->name_list_element
)));
6419 /* Check that FONT is valid on frame F. It is if it can be found in F's
6423 x_check_font (f
, font
)
6428 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6430 xassert (font
!= NULL
);
6432 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6433 if (dpyinfo
->font_table
[i
].name
6434 && font
== dpyinfo
->font_table
[i
].font
)
6437 xassert (i
< dpyinfo
->n_fonts
);
6440 #endif /* GLYPH_DEBUG != 0 */
6442 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6443 Note: There are (broken) X fonts out there with invalid XFontStruct
6444 min_bounds contents. For example, handa@etl.go.jp reports that
6445 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6446 have font->min_bounds.width == 0. */
6449 x_font_min_bounds (font
, w
, h
)
6450 MacFontStruct
*font
;
6454 * TODO: Windows does not appear to offer min bound, only
6455 * average and maximum width, and maximum height.
6457 *h
= FONT_HEIGHT (font
);
6458 *w
= FONT_WIDTH (font
);
6462 /* Compute the smallest character width and smallest font height over
6463 all fonts available on frame F. Set the members smallest_char_width
6464 and smallest_font_height in F's x_display_info structure to
6465 the values computed. Value is non-zero if smallest_font_height or
6466 smallest_char_width become smaller than they were before. */
6469 x_compute_min_glyph_bounds (f
)
6473 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6474 MacFontStruct
*font
;
6475 int old_width
= dpyinfo
->smallest_char_width
;
6476 int old_height
= dpyinfo
->smallest_font_height
;
6478 dpyinfo
->smallest_font_height
= 100000;
6479 dpyinfo
->smallest_char_width
= 100000;
6481 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6482 if (dpyinfo
->font_table
[i
].name
)
6484 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
6487 font
= (MacFontStruct
*) fontp
->font
;
6488 xassert (font
!= (MacFontStruct
*) ~0);
6489 x_font_min_bounds (font
, &w
, &h
);
6491 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
6492 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
6495 xassert (dpyinfo
->smallest_char_width
> 0
6496 && dpyinfo
->smallest_font_height
> 0);
6498 return (dpyinfo
->n_fonts
== 1
6499 || dpyinfo
->smallest_char_width
< old_width
6500 || dpyinfo
->smallest_font_height
< old_height
);
6504 /* Determine whether given string is a fully-specified XLFD: all 14
6505 fields are present, none is '*'. */
6508 is_fully_specified_xlfd (char *p
)
6516 for (i
= 0; i
< 13; i
++)
6518 q
= strchr (p
+ 1, '-');
6521 if (q
- p
== 2 && *(p
+ 1) == '*')
6526 if (strchr (p
+ 1, '-') != NULL
)
6529 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
6536 const int kDefaultFontSize
= 9;
6539 /* XLoadQueryFont creates and returns an internal representation for a
6540 font in a MacFontStruct struct. There is really no concept
6541 corresponding to "loading" a font on the Mac. But we check its
6542 existence and find the font number and all other information for it
6543 and store them in the returned MacFontStruct. */
6545 static MacFontStruct
*
6546 XLoadQueryFont (Display
*dpy
, char *fontname
)
6548 int i
, size
, is_two_byte_font
, char_width
;
6551 SInt16 old_fontnum
, old_fontsize
;
6555 Style fontface
= normal
;
6556 MacFontStruct
*font
;
6557 FontInfo the_fontinfo
;
6558 char s_weight
[7], c_slant
;
6560 if (is_fully_specified_xlfd (fontname
))
6564 Lisp_Object matched_fonts
;
6566 matched_fonts
= mac_do_list_fonts (fontname
, 1);
6567 if (NILP (matched_fonts
))
6569 name
= SDATA (XCAR (matched_fonts
));
6572 GetPort (&port
); /* save the current font number used */
6573 #if TARGET_API_MAC_CARBON
6574 old_fontnum
= GetPortTextFont (port
);
6575 old_fontsize
= GetPortTextSize (port
);
6576 old_fontface
= GetPortTextFace (port
);
6578 old_fontnum
= port
->txFont
;
6579 old_fontsize
= port
->txSize
;
6580 old_fontface
= port
->txFace
;
6583 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size
) != 1)
6584 size
= kDefaultFontSize
;
6586 if (sscanf (name
, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight
) == 1)
6587 if (strcmp (s_weight
, "bold") == 0)
6590 if (sscanf (name
, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant
) == 1)
6594 x_font_name_to_mac_font_name (name
, mfontname
);
6596 GetFNum (mfontname
, &fontnum
);
6600 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
6602 font
->fontname
= (char *) xmalloc (strlen (name
) + 1);
6603 bcopy (name
, font
->fontname
, strlen (name
) + 1);
6605 font
->mac_fontnum
= fontnum
;
6606 font
->mac_fontsize
= size
;
6607 font
->mac_fontface
= fontface
;
6608 font
->mac_scriptcode
= FontToScript (fontnum
);
6610 /* Apple Japanese (SJIS) font is listed as both
6611 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6612 (Roman script) in init_font_name_table (). The latter should be
6613 treated as a one-byte font. */
6618 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6620 && 0 == strcmp (cs
, "jisx0201.1976-0"))
6621 font
->mac_scriptcode
= smRoman
;
6624 is_two_byte_font
= font
->mac_scriptcode
== smJapanese
||
6625 font
->mac_scriptcode
== smTradChinese
||
6626 font
->mac_scriptcode
== smSimpChinese
||
6627 font
->mac_scriptcode
== smKorean
;
6631 TextFace (fontface
);
6633 GetFontInfo (&the_fontinfo
);
6635 font
->ascent
= the_fontinfo
.ascent
;
6636 font
->descent
= the_fontinfo
.descent
;
6638 font
->min_byte1
= 0;
6639 if (is_two_byte_font
)
6640 font
->max_byte1
= 1;
6642 font
->max_byte1
= 0;
6643 font
->min_char_or_byte2
= 0x20;
6644 font
->max_char_or_byte2
= 0xff;
6646 if (is_two_byte_font
)
6648 /* Use the width of an "ideographic space" of that font because
6649 the_fontinfo.widMax returns the wrong width for some fonts. */
6650 switch (font
->mac_scriptcode
)
6653 char_width
= StringWidth("\p\x81\x40");
6656 char_width
= StringWidth("\p\xa1\x40");
6659 char_width
= StringWidth("\p\xa1\xa1");
6662 char_width
= StringWidth("\p\xa1\xa1");
6667 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6668 returns 15 for 12-point Monaco! */
6669 char_width
= CharWidth ('m');
6671 font
->max_bounds
.rbearing
= char_width
;
6672 font
->max_bounds
.lbearing
= 0;
6673 font
->max_bounds
.width
= char_width
;
6674 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
6675 font
->max_bounds
.descent
= the_fontinfo
.descent
;
6677 font
->min_bounds
= font
->max_bounds
;
6679 if (is_two_byte_font
|| CharWidth ('m') == CharWidth ('i'))
6680 font
->per_char
= NULL
;
6683 font
->per_char
= (XCharStruct
*)
6684 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
6688 for (c
= 0x20; c
<= 0xff; c
++)
6690 font
->per_char
[c
- 0x20] = font
->max_bounds
;
6691 font
->per_char
[c
- 0x20].width
=
6692 font
->per_char
[c
- 0x20].rbearing
= CharWidth (c
);
6697 TextFont (old_fontnum
); /* restore previous font number, size and face */
6698 TextSize (old_fontsize
);
6699 TextFace (old_fontface
);
6705 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6706 pointer to the structure font_info while allocating it dynamically.
6707 If SIZE is 0, load any size of font.
6708 If loading is failed, return NULL. */
6711 x_load_font (f
, fontname
, size
)
6713 register char *fontname
;
6716 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6717 Lisp_Object font_names
;
6719 /* Get a list of all the fonts that match this name. Once we
6720 have a list of matching fonts, we compare them against the fonts
6721 we already have by comparing names. */
6722 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6724 if (!NILP (font_names
))
6729 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6730 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
6731 if (dpyinfo
->font_table
[i
].name
6732 && (!strcmp (dpyinfo
->font_table
[i
].name
,
6733 SDATA (XCAR (tail
)))
6734 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6735 SDATA (XCAR (tail
)))))
6736 return (dpyinfo
->font_table
+ i
);
6739 /* Load the font and add it to the table. */
6742 struct MacFontStruct
*font
;
6743 struct font_info
*fontp
;
6744 unsigned long value
;
6747 /* If we have found fonts by x_list_font, load one of them. If
6748 not, we still try to load a font by the name given as FONTNAME
6749 because XListFonts (called in x_list_font) of some X server has
6750 a bug of not finding a font even if the font surely exists and
6751 is loadable by XLoadQueryFont. */
6752 if (size
> 0 && !NILP (font_names
))
6753 fontname
= (char *) SDATA (XCAR (font_names
));
6755 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
6759 /* Find a free slot in the font table. */
6760 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
6761 if (dpyinfo
->font_table
[i
].name
== NULL
)
6764 /* If no free slot found, maybe enlarge the font table. */
6765 if (i
== dpyinfo
->n_fonts
6766 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
6769 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
6770 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
6772 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
6775 fontp
= dpyinfo
->font_table
+ i
;
6776 if (i
== dpyinfo
->n_fonts
)
6779 /* Now fill in the slots of *FONTP. */
6781 bzero (fontp
, sizeof (*fontp
));
6783 fontp
->font_idx
= i
;
6784 fontp
->name
= (char *) xmalloc (strlen (font
->fontname
) + 1);
6785 bcopy (font
->fontname
, fontp
->name
, strlen (font
->fontname
) + 1);
6787 fontp
->full_name
= fontp
->name
;
6789 fontp
->size
= font
->max_bounds
.width
;
6790 fontp
->height
= FONT_HEIGHT (font
);
6792 /* For some font, ascent and descent in max_bounds field is
6793 larger than the above value. */
6794 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6795 if (max_height
> fontp
->height
)
6796 fontp
->height
= max_height
;
6799 /* The slot `encoding' specifies how to map a character
6800 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6801 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6802 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6803 2:0xA020..0xFF7F). For the moment, we don't know which charset
6804 uses this font. So, we set information in fontp->encoding[1]
6805 which is never used by any charset. If mapping can't be
6806 decided, set FONT_ENCODING_NOT_DECIDED. */
6807 if (font
->mac_scriptcode
== smJapanese
)
6808 fontp
->encoding
[1] = 4;
6812 = (font
->max_byte1
== 0
6814 ? (font
->min_char_or_byte2
< 0x80
6815 ? (font
->max_char_or_byte2
< 0x80
6816 ? 0 /* 0x20..0x7F */
6817 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6818 : 1) /* 0xA0..0xFF */
6820 : (font
->min_byte1
< 0x80
6821 ? (font
->max_byte1
< 0x80
6822 ? (font
->min_char_or_byte2
< 0x80
6823 ? (font
->max_char_or_byte2
< 0x80
6824 ? 0 /* 0x2020..0x7F7F */
6825 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6826 : 3) /* 0x20A0..0x7FFF */
6827 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6828 : (font
->min_char_or_byte2
< 0x80
6829 ? (font
->max_char_or_byte2
< 0x80
6830 ? 2 /* 0xA020..0xFF7F */
6831 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6832 : 1))); /* 0xA0A0..0xFFFF */
6835 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6836 fontp
->baseline_offset
6837 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6838 ? (long) value
: 0);
6839 fontp
->relative_compose
6840 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6841 ? (long) value
: 0);
6842 fontp
->default_ascent
6843 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6844 ? (long) value
: 0);
6846 fontp
->baseline_offset
= 0;
6847 fontp
->relative_compose
= 0;
6848 fontp
->default_ascent
= 0;
6851 /* Set global flag fonts_changed_p to non-zero if the font loaded
6852 has a character with a smaller width than any other character
6853 before, or if the font loaded has a smalle>r height than any
6854 other font loaded before. If this happens, it will make a
6855 glyph matrix reallocation necessary. */
6856 fonts_changed_p
= x_compute_min_glyph_bounds (f
);
6863 /* Return a pointer to struct font_info of a font named FONTNAME for
6864 frame F. If no such font is loaded, return NULL. */
6867 x_query_font (f
, fontname
)
6869 register char *fontname
;
6871 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6874 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6875 if (dpyinfo
->font_table
[i
].name
6876 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6877 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
6878 return (dpyinfo
->font_table
+ i
);
6883 /* Find a CCL program for a font specified by FONTP, and set the member
6884 `encoder' of the structure. */
6887 x_find_ccl_program (fontp
)
6888 struct font_info
*fontp
;
6890 Lisp_Object list
, elt
;
6892 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
6896 && STRINGP (XCAR (elt
))
6897 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
6903 struct ccl_program
*ccl
6904 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6906 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
6909 fontp
->font_encoder
= ccl
;
6915 /* The Mac Event loop code */
6919 #include <Quickdraw.h>
6920 #include <Balloons.h>
6921 #include <Devices.h>
6923 #include <Gestalt.h>
6925 #include <Processes.h>
6927 #include <ToolUtils.h>
6928 #include <TextUtils.h>
6929 #include <Dialogs.h>
6932 #include <TextEncodingConverter.h>
6933 #include <Resources.h>
6938 #endif /* ! MAC_OSX */
6943 #define WINDOW_RESOURCE 128
6944 #define TERM_WINDOW_RESOURCE 129
6946 #define DEFAULT_NUM_COLS 80
6948 #define MIN_DOC_SIZE 64
6949 #define MAX_DOC_SIZE 32767
6951 /* sleep time for WaitNextEvent */
6952 #define WNE_SLEEP_AT_SUSPEND 10
6953 #define WNE_SLEEP_AT_RESUME 1
6955 /* true when cannot handle any Mac OS events */
6956 static int handling_window_update
= 0;
6959 /* the flag appl_is_suspended is used both for determining the sleep
6960 time to be passed to WaitNextEvent and whether the cursor should be
6961 drawn when updating the display. The cursor is turned off when
6962 Emacs is suspended. Redrawing it is unnecessary and what needs to
6963 be done depends on whether the cursor lies inside or outside the
6964 redraw region. So we might as well skip drawing it when Emacs is
6966 static Boolean app_is_suspended
= false;
6967 static long app_sleep_time
= WNE_SLEEP_AT_RESUME
;
6970 #define EXTRA_STACK_ALLOC (256 * 1024)
6972 #define ARGV_STRING_LIST_ID 129
6973 #define ABOUT_ALERT_ID 128
6974 #define RAM_TOO_LARGE_ALERT_ID 129
6976 Boolean terminate_flag
= false;
6978 /* Contains the string "reverse", which is a constant for mouse button emu.*/
6979 Lisp_Object Qreverse
;
6981 /* True if using command key as meta key. */
6982 Lisp_Object Vmac_command_key_is_meta
;
6984 /* True if the ctrl and meta keys should be reversed. */
6985 Lisp_Object Vmac_reverse_ctrl_meta
;
6987 /* True if the option and command modifiers should be used to emulate
6988 a three button mouse */
6989 Lisp_Object Vmac_emulate_three_button_mouse
;
6991 #if USE_CARBON_EVENTS
6992 /* True if the mouse wheel button (i.e. button 4) should map to
6993 mouse-2, instead of mouse-3. */
6994 Lisp_Object Vmac_wheel_button_is_mouse_2
;
6996 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
6997 for processing before Emacs sees it. */
6998 Lisp_Object Vmac_pass_command_to_system
;
7000 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7001 for processing before Emacs sees it. */
7002 Lisp_Object Vmac_pass_control_to_system
;
7005 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7006 to this text encoding */
7007 int mac_keyboard_text_encoding
;
7008 int current_mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
7010 /* Set in term/mac-win.el to indicate that event loop can now generate
7011 drag and drop events. */
7012 Lisp_Object Qmac_ready_for_drag_n_drop
;
7014 Lisp_Object drag_and_drop_file_list
;
7016 Point saved_menu_event_location
;
7018 #if !TARGET_API_MAC_CARBON
7019 /* Place holder for the default arrow cursor. */
7020 CursPtr arrow_cursor
;
7024 static void init_required_apple_events (void);
7026 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7028 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7029 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7030 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7033 static OSErr
init_mac_drag_n_drop ();
7034 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7036 #if USE_CARBON_EVENTS
7037 /* Preliminary Support for the OSX Services Menu */
7038 static OSStatus
mac_handle_service_event (EventHandlerCallRef
,EventRef
,void*);
7039 static void init_service_handler ();
7042 extern void init_emacs_passwd_dir ();
7043 extern int emacs_main (int, char **, char **);
7044 extern void check_alarm ();
7046 extern void initialize_applescript();
7047 extern void terminate_applescript();
7050 #if USE_CARBON_EVENTS
7051 mac_to_emacs_modifiers (UInt32 mods
)
7053 mac_to_emacs_modifiers (EventModifiers mods
)
7056 unsigned int result
= 0;
7057 if (mods
& macShiftKey
)
7058 result
|= shift_modifier
;
7059 if (mods
& macCtrlKey
)
7060 result
|= ctrl_modifier
;
7061 if (mods
& macMetaKey
)
7062 result
|= meta_modifier
;
7063 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
7064 result
|= alt_modifier
;
7069 mac_get_emulated_btn ( UInt32 modifiers
)
7072 if (!NILP (Vmac_emulate_three_button_mouse
)) {
7073 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
7074 if (modifiers
& cmdKey
)
7075 result
= cmdIs3
? 2 : 1;
7076 else if (modifiers
& optionKey
)
7077 result
= cmdIs3
? 1 : 2;
7082 #if USE_CARBON_EVENTS
7083 /* Obtains the event modifiers from the event ref and then calls
7084 mac_to_emacs_modifiers. */
7086 mac_event_to_emacs_modifiers (EventRef eventRef
)
7089 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7090 sizeof (UInt32
), NULL
, &mods
);
7091 if (!NILP (Vmac_emulate_three_button_mouse
) &&
7092 GetEventClass(eventRef
) == kEventClassMouse
)
7094 mods
&= ~(optionKey
| cmdKey
);
7096 return mac_to_emacs_modifiers (mods
);
7099 /* Given an event ref, return the code to use for the mouse button
7100 code in the emacs input_event. */
7102 mac_get_mouse_btn (EventRef ref
)
7104 EventMouseButton result
= kEventMouseButtonPrimary
;
7105 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
7106 sizeof (EventMouseButton
), NULL
, &result
);
7109 case kEventMouseButtonPrimary
:
7110 if (NILP (Vmac_emulate_three_button_mouse
))
7114 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
7115 sizeof (UInt32
), NULL
, &mods
);
7116 return mac_get_emulated_btn(mods
);
7118 case kEventMouseButtonSecondary
:
7119 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
7120 case kEventMouseButtonTertiary
:
7121 case 4: /* 4 is the number for the mouse wheel button */
7122 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
7128 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7129 events. However the click of the mouse wheel is not converted to a
7130 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7131 checks to see if it is a mouse up or down carbon event that has not
7132 been converted, and if so, converts it by hand (to be picked up in
7133 the XTread_socket loop). */
7134 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
7136 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
7137 /* Do special case for mouse wheel button. */
7138 if (!result
&& GetEventClass (eventRef
) == kEventClassMouse
)
7140 UInt32 kind
= GetEventKind (eventRef
);
7141 if (kind
== kEventMouseDown
&& !(eventRec
->what
== mouseDown
))
7143 eventRec
->what
= mouseDown
;
7146 if (kind
== kEventMouseUp
&& !(eventRec
->what
== mouseUp
))
7148 eventRec
->what
= mouseUp
;
7153 /* Need where and when. */
7155 GetEventParameter (eventRef
, kEventParamMouseLocation
,
7156 typeQDPoint
, NULL
, sizeof (Point
),
7157 NULL
, &eventRec
->where
);
7158 /* Use two step process because new event modifiers are
7159 32-bit and old are 16-bit. Currently, only loss is
7161 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
7162 typeUInt32
, NULL
, sizeof (UInt32
),
7164 eventRec
->modifiers
= mods
;
7166 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
7177 Handle menubar_handle
;
7178 MenuHandle menu_handle
;
7180 menubar_handle
= GetNewMBar (128);
7181 if(menubar_handle
== NULL
)
7183 SetMenuBar (menubar_handle
);
7186 menu_handle
= GetMenuHandle (M_APPLE
);
7187 if(menu_handle
!= NULL
)
7188 AppendResMenu (menu_handle
,'DRVR');
7195 do_init_managers (void)
7197 #if !TARGET_API_MAC_CARBON
7198 InitGraf (&qd
.thePort
);
7200 FlushEvents (everyEvent
, 0);
7205 #endif /* !TARGET_API_MAC_CARBON */
7208 #if !TARGET_API_MAC_CARBON
7209 arrow_cursor
= &qd
.arrow
;
7211 /* set up some extra stack space for use by emacs */
7212 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
7214 /* MaxApplZone must be called for AppleScript to execute more
7215 complicated scripts */
7218 #endif /* !TARGET_API_MAC_CARBON */
7222 do_check_ram_size (void)
7224 SInt32 physical_ram_size
, logical_ram_size
;
7226 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
7227 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
7228 || physical_ram_size
> (1 << VALBITS
)
7229 || logical_ram_size
> (1 << VALBITS
))
7231 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
7237 do_window_update (WindowPtr win
)
7239 struct frame
*f
= mac_window_to_frame (win
);
7241 if (win
== tip_window
)
7242 /* The tooltip has been drawn already. Avoid the
7243 SET_FRAME_GARBAGED below. */
7248 if (f
->async_visible
== 0)
7250 f
->async_visible
= 1;
7251 f
->async_iconified
= 0;
7252 SET_FRAME_GARBAGED (f
);
7254 /* An update event is equivalent to MapNotify on X, so report
7255 visibility changes properly. */
7256 if (! NILP(Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
7257 /* Force a redisplay sooner or later to update the
7258 frame titles in case this is the second frame. */
7259 record_asynch_buffer_change ();
7264 handling_window_update
= 1;
7266 XClearWindow (FRAME_MAC_DISPLAY (f
), FRAME_MAC_WINDOW (f
));
7268 expose_frame (f
, 0, 0, 0, 0);
7270 handling_window_update
= 0;
7277 is_emacs_window (WindowPtr win
)
7279 Lisp_Object tail
, frame
;
7284 FOR_EACH_FRAME (tail
, frame
)
7285 if (FRAME_MAC_P (XFRAME (frame
)))
7286 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
7295 /* Window-activate events will do the job. */
7300 wp
= front_emacs_window ();
7303 f
= mac_window_to_frame (wp
);
7307 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), f
);
7308 activate_scroll_bars (f
);
7312 app_is_suspended
= false;
7313 app_sleep_time
= WNE_SLEEP_AT_RESUME
;
7320 /* Window-deactivate events will do the job. */
7325 wp
= front_emacs_window ();
7328 f
= mac_window_to_frame (wp
);
7330 if (f
== FRAME_MAC_DISPLAY_INFO (f
)->x_focus_frame
)
7332 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f
), 0);
7333 deactivate_scroll_bars (f
);
7337 app_is_suspended
= true;
7338 app_sleep_time
= WNE_SLEEP_AT_SUSPEND
;
7344 do_mouse_moved (mouse_pos
, f
)
7348 WindowPtr wp
= front_emacs_window ();
7349 struct x_display_info
*dpyinfo
;
7353 *f
= mac_window_to_frame (wp
);
7354 dpyinfo
= FRAME_MAC_DISPLAY_INFO (*f
);
7356 if (dpyinfo
->mouse_face_hidden
)
7358 dpyinfo
->mouse_face_hidden
= 0;
7359 clear_mouse_face (dpyinfo
);
7362 SetPortWindowPort (wp
);
7364 GlobalToLocal (&mouse_pos
);
7366 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
7367 x_scroll_bar_note_movement (tracked_scroll_bar
,
7369 - XINT (tracked_scroll_bar
->top
),
7370 TickCount() * (1000 / 60));
7372 note_mouse_movement (*f
, &mouse_pos
);
7378 do_apple_menu (SInt16 menu_item
)
7380 #if !TARGET_API_MAC_CARBON
7382 SInt16 da_driver_refnum
;
7384 if (menu_item
== I_ABOUT
)
7385 NoteAlert (ABOUT_ALERT_ID
, NULL
);
7388 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
7389 da_driver_refnum
= OpenDeskAcc (item_name
);
7391 #endif /* !TARGET_API_MAC_CARBON */
7395 do_menu_choice (SInt32 menu_choice
)
7397 SInt16 menu_id
, menu_item
;
7399 menu_id
= HiWord (menu_choice
);
7400 menu_item
= LoWord (menu_choice
);
7408 do_apple_menu (menu_item
);
7413 struct frame
*f
= mac_window_to_frame (front_emacs_window ());
7414 MenuHandle menu
= GetMenuHandle (menu_id
);
7419 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
7420 menubar_selection_callback (f
, refcon
);
7429 /* Handle drags in size box. Based on code contributed by Ben
7430 Mesander and IM - Window Manager A. */
7433 do_grow_window (WindowPtr w
, EventRecord
*e
)
7438 struct frame
*f
= mac_window_to_frame (w
);
7440 SetRect(&limit_rect
, MIN_DOC_SIZE
, MIN_DOC_SIZE
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
7442 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
7444 /* see if it really changed size */
7447 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, HiWord (grow_size
));
7448 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, LoWord (grow_size
));
7450 x_set_window_size (f
, 0, columns
, rows
);
7455 /* Handle clicks in zoom box. Calculation of "standard state" based
7456 on code in IM - Window Manager A and code contributed by Ben
7457 Mesander. The standard state of an Emacs window is 80-characters
7458 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7461 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
7464 Rect zoom_rect
, port_rect
;
7466 int w_title_height
, columns
, rows
;
7467 struct frame
*f
= mac_window_to_frame (w
);
7469 #if TARGET_API_MAC_CARBON
7471 Point standard_size
;
7473 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7474 standard_size
.v
= FRAME_MAC_DISPLAY_INFO (f
)->height
;
7476 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
7477 zoom_in_or_out
= inZoomIn
;
7480 /* Adjust the standard size according to character boundaries. */
7482 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
7483 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7484 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
7485 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7486 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
7487 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
7488 && port_rect
.left
== zoom_rect
.left
7489 && port_rect
.top
== zoom_rect
.top
)
7490 zoom_in_or_out
= inZoomIn
;
7492 zoom_in_or_out
= inZoomOut
;
7495 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
7497 #else /* not TARGET_API_MAC_CARBON */
7498 GetPort (&save_port
);
7500 SetPortWindowPort (w
);
7502 /* Clear window to avoid flicker. */
7503 EraseRect (&(w
->portRect
));
7504 if (zoom_in_or_out
== inZoomOut
)
7506 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
7507 LocalToGlobal (&top_left
);
7509 /* calculate height of window's title bar */
7510 w_title_height
= top_left
.v
- 1
7511 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
7513 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7514 zoom_rect
= qd
.screenBits
.bounds
;
7515 zoom_rect
.top
+= w_title_height
;
7516 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
7518 zoom_rect
.right
= zoom_rect
.left
7519 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
7521 /* Adjust the standard size according to character boundaries. */
7522 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
7524 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
7526 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
7530 ZoomWindow (w
, zoom_in_or_out
, w
== front_emacs_window ());
7532 SetPort (save_port
);
7533 #endif /* not TARGET_API_MAC_CARBON */
7535 /* retrieve window size and update application values */
7536 #if TARGET_API_MAC_CARBON
7537 GetWindowPortBounds (w
, &port_rect
);
7539 port_rect
= w
->portRect
;
7541 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, port_rect
.bottom
- port_rect
.top
);
7542 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, port_rect
.right
- port_rect
.left
);
7543 x_set_window_size (f
, 0, columns
, rows
);
7544 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
7547 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7549 init_mac_drag_n_drop ()
7551 OSErr result
= InstallReceiveHandler (mac_do_receive_drag
, 0L, NULL
);
7555 /* Intialize AppleEvent dispatcher table for the required events. */
7557 init_required_apple_events ()
7562 /* Make sure we have apple events before starting. */
7563 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
7567 if (!(result
& (1 << gestaltAppleEventsPresent
)))
7570 #if TARGET_API_MAC_CARBON
7571 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7572 NewAEEventHandlerUPP
7573 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7576 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
7577 NewAEEventHandlerProc
7578 ((AEEventHandlerProcPtr
) do_ae_open_application
),
7584 #if TARGET_API_MAC_CARBON
7585 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7586 NewAEEventHandlerUPP
7587 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7590 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
7591 NewAEEventHandlerProc
7592 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
7598 #if TARGET_API_MAC_CARBON
7599 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7600 NewAEEventHandlerUPP
7601 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7604 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
7605 NewAEEventHandlerProc
7606 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
7612 #if TARGET_API_MAC_CARBON
7613 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7614 NewAEEventHandlerUPP
7615 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7618 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
7619 NewAEEventHandlerProc
7620 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
7627 #if USE_CARBON_EVENTS
7630 init_service_handler ()
7632 EventTypeSpec specs
[] = {{kEventClassService
, kEventServiceGetTypes
},
7633 {kEventClassService
, kEventServiceCopy
},
7634 {kEventClassService
, kEventServicePaste
}};
7635 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event
),
7636 3, specs
, NULL
, NULL
);
7640 MAC_TODO: Check to see if this is called by AEProcessDesc...
7643 mac_handle_service_event (EventHandlerCallRef callRef
,
7644 EventRef event
, void *data
)
7646 OSStatus err
= noErr
;
7647 switch (GetEventKind (event
))
7649 case kEventServiceGetTypes
:
7651 CFMutableArrayRef copyTypes
, pasteTypes
;
7653 Boolean selection
= true;
7655 GetEventParameter(event, kEventParamServicePasteTypes,
7656 typeCFMutableArrayRef, NULL,
7657 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7659 GetEventParameter(event
, kEventParamServiceCopyTypes
,
7660 typeCFMutableArrayRef
, NULL
,
7661 sizeof (CFMutableArrayRef
), NULL
, ©Types
);
7662 type
= CreateTypeStringWithOSType (kScrapFlavorTypeText
);
7664 CFArrayAppendValue (copyTypes
, type
);
7665 //CFArrayAppendValue (pasteTypes, type);
7669 case kEventServiceCopy
:
7671 ScrapRef currentScrap
, specificScrap
;
7675 GetCurrentScrap (¤tScrap
);
7677 err
= GetScrapFlavorSize (currentScrap
, kScrapFlavorTypeText
, &byteCount
);
7680 void *buffer
= xmalloc (byteCount
);
7683 GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
, NULL
,
7684 sizeof (ScrapRef
), NULL
, &specificScrap
);
7686 err
= GetScrapFlavorData (currentScrap
, kScrapFlavorTypeText
,
7687 &byteCount
, buffer
);
7689 PutScrapFlavor (specificScrap
, kScrapFlavorTypeText
,
7690 kScrapFlavorMaskNone
, byteCount
, buffer
);
7696 case kEventServicePaste
:
7699 // Get the current location
7701 ScrapRef specificScrap;
7702 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7703 sizeof(ScrapRef), NULL, &specificScrap);
7704 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7706 void * buffer = xmalloc(byteCount);
7707 if (buffer != NULL ) {
7708 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7709 &byteCount, buffer);
7711 // Actually place in the buffer
7713 // Get the current "selection" string here
7726 /* Open Application Apple Event */
7728 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
7734 /* Defined in mac.c. */
7736 path_from_vol_dir_name (char *, int, short, long, char *);
7739 /* Called when we receive an AppleEvent with an ID of
7740 "kAEOpenDocuments". This routine gets the direct parameter,
7741 extracts the FSSpecs in it, and puts their names on a list. */
7743 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
7748 DescType actual_type
;
7751 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
7753 goto descriptor_error_exit
;
7755 /* Check to see that we got all of the required parameters from the
7756 event descriptor. For an 'odoc' event this should just be the
7758 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
7759 &actual_type
, (Ptr
) &keyword
,
7760 sizeof (keyword
), &actual_size
);
7761 /* No error means that we found some unused parameters.
7762 errAEDescNotFound means that there are no more parameters. If we
7763 get an error code other than that, flag it. */
7764 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
7766 err
= errAEEventNotHandled
;
7771 /* Got all the parameters we need. Now, go through the direct
7772 object list and parse it up. */
7774 long num_files_to_open
;
7776 err
= AECountItems (&the_desc
, &num_files_to_open
);
7781 /* AE file list is one based so just use that for indexing here. */
7782 for (i
= 1; (err
== noErr
) && (i
<= num_files_to_open
); i
++)
7785 Str255 path_name
, unix_path_name
;
7790 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
7791 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
7792 if (err
!= noErr
) break;
7795 err
= FSpMakeFSRef (&fs
, &fref
);
7796 if (err
!= noErr
) break;
7798 if (FSRefMakePath (&fref
, unix_path_name
, 255) == noErr
)
7800 if (path_from_vol_dir_name (path_name
, 255, fs
.vRefNum
, fs
.parID
,
7802 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
7804 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
7805 drag_and_drop_file_list
);
7811 /* Nuke the coerced file list in any case */
7812 err2
= AEDisposeDesc(&the_desc
);
7814 descriptor_error_exit
:
7815 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7821 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
7822 DragReference theDrag
)
7826 FlavorFlags theFlags
;
7829 ItemReference theItem
;
7832 Size size
= sizeof (HFSFlavor
);
7834 drag_and_drop_file_list
= Qnil
;
7835 GetDragMouse (theDrag
, &mouse
, 0L);
7836 CountDragItems (theDrag
, &items
);
7837 for (index
= 1; index
<= items
; index
++)
7839 /* Only handle file references. */
7840 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
7841 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
7842 if (result
== noErr
)
7849 Str255 unix_path_name
;
7850 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
7852 /* Use Carbon routines, otherwise it converts the file name
7853 to /Macintosh HD/..., which is not correct. */
7854 FSpMakeFSRef (&data
.fileSpec
, &fref
);
7855 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
7857 if (path_from_vol_dir_name (path_name
, 255, data
.fileSpec
.vRefNum
,
7858 data
.fileSpec
.parID
, data
.fileSpec
.name
) &&
7859 mac_to_posix_pathname (path_name
, unix_path_name
, 255))
7861 drag_and_drop_file_list
= Fcons (build_string (unix_path_name
),
7862 drag_and_drop_file_list
);
7867 /* If there are items in the list, construct an event and post it to
7868 the queue like an interrupt using kbd_buffer_store_event. */
7869 if (!NILP (drag_and_drop_file_list
))
7871 struct input_event event
;
7873 struct frame
*f
= mac_window_to_frame (window
);
7874 SetPortWindowPort (window
);
7875 GlobalToLocal (&mouse
);
7877 event
.kind
= DRAG_N_DROP_EVENT
;
7879 event
.modifiers
= 0;
7880 event
.timestamp
= TickCount () * (1000 / 60);
7881 XSETINT (event
.x
, mouse
.h
);
7882 XSETINT (event
.y
, mouse
.v
);
7883 XSETFRAME (frame
, f
);
7884 event
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
7886 /* Post to the interrupt queue */
7887 kbd_buffer_store_event (&event
);
7888 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7890 ProcessSerialNumber psn
;
7891 GetCurrentProcess (&psn
);
7892 SetFrontProcess (&psn
);
7898 /* Print Document Apple Event */
7900 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
7902 return errAEEventNotHandled
;
7907 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
7909 /* FixMe: Do we need an unwind-protect or something here? And what
7910 do we do about unsaved files. Currently just forces quit rather
7911 than doing recursive callback to get user input. */
7913 terminate_flag
= true;
7915 /* Fkill_emacs doesn't return. We have to return. (TI) */
7922 profiler_exit_proc ()
7924 ProfilerDump ("\pEmacs.prof");
7929 /* These few functions implement Emacs as a normal Mac application
7930 (almost): set up the heap and the Toolbox, handle necessary
7931 system events plus a few simple menu events. They also set up
7932 Emacs's access to functions defined in the rest of this file.
7933 Emacs uses function hooks to perform all its terminal I/O. A
7934 complete list of these functions appear in termhooks.h. For what
7935 they do, read the comments there and see also w32term.c and
7936 xterm.c. What's noticeably missing here is the event loop, which
7937 is normally present in most Mac application. After performing the
7938 necessary Mac initializations, main passes off control to
7939 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7940 mac_read_socket (defined further below) to read input. This is
7941 where WaitNextEvent is called to process Mac events. This is also
7942 where check_alarm in sysdep.c is called to simulate alarm signals.
7943 This makes the cursor jump back to its correct position after
7944 briefly jumping to that of the matching parenthesis, print useful
7945 hints and prompts in the minibuffer after the user stops typing for
7948 #if !TARGET_API_MAC_CARBON
7953 #if __profile__ /* is the profiler on? */
7954 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
7959 /* set creator and type for files created by MSL */
7964 do_init_managers ();
7969 do_check_ram_size ();
7972 init_emacs_passwd_dir ();
7976 initialize_applescript ();
7978 init_required_apple_events ();
7984 /* set up argv array from STR# resource */
7985 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
7989 /* free up AppleScript resources on exit */
7990 atexit (terminate_applescript
);
7992 #if __profile__ /* is the profiler on? */
7993 atexit (profiler_exit_proc
);
7996 /* 3rd param "envp" never used in emacs_main */
7997 (void) emacs_main (argc
, argv
, 0);
8000 /* Never reached - real exit in Fkill_emacs */
8005 /* Table for translating Mac keycode to X keysym values. Contributed
8006 by Sudhir Shenoy. */
8007 static unsigned char keycode_to_xkeysym_table
[] = {
8008 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8009 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8010 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8012 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8013 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8014 /*0x38*/ 0, 0, 0, 0,
8015 /*0x3C*/ 0, 0, 0, 0,
8017 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8018 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8019 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8020 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8022 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8023 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8024 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8025 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8027 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8028 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8029 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8030 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8032 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8033 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8034 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8035 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8039 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
8041 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
8042 return *xKeySym
!= 0;
8045 /* Emacs calls this whenever it wants to read an input event from the
8048 XTread_socket (sd
, expected
, hold_quit
)
8050 struct input_event
*hold_quit
;
8052 struct input_event inev
;
8054 #if USE_CARBON_EVENTS
8056 EventTargetRef toolbox_dispatcher
= GetEventDispatcherTarget ();
8058 EventMask event_mask
;
8061 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8063 if (interrupt_input_blocked
)
8065 interrupt_input_pending
= 1;
8069 interrupt_input_pending
= 0;
8072 /* So people can tell when we have read the available input. */
8073 input_signal_count
++;
8075 /* Don't poll for events to process (specifically updateEvt) if
8076 window update currently already in progress. A call to redisplay
8077 (in do_window_update) can be preempted by another call to
8078 redisplay, causing blank regions to be left on the screen and the
8079 cursor to be left at strange places. */
8080 if (handling_window_update
)
8087 Fkill_emacs (make_number (1));
8089 #if !USE_CARBON_EVENTS
8090 event_mask
= everyEvent
;
8091 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
8092 event_mask
-= highLevelEventMask
;
8094 while (WaitNextEvent (event_mask
, &er
, 0L, NULL
))
8095 #else /* USE_CARBON_EVENTS */
8096 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
8097 kEventRemoveFromQueue
, &eventRef
))
8098 #endif /* USE_CARBON_EVENTS */
8103 /* It is necessary to set this (additional) argument slot of an
8104 event to nil because keyboard.c protects incompletely
8105 processed event from being garbage collected by placing them
8106 in the kbd_buffer_gcpro vector. */
8108 inev
.kind
= NO_EVENT
;
8111 #if USE_CARBON_EVENTS
8112 /* Handle new events */
8113 if (!mac_convert_event_ref (eventRef
, &er
))
8114 switch (GetEventClass (eventRef
))
8116 case kEventClassWindow
:
8117 if (GetEventKind (eventRef
) == kEventWindowBoundsChanged
)
8119 WindowPtr window_ptr
;
8120 GetEventParameter(eventRef
, kEventParamDirectObject
,
8121 typeWindowRef
, NULL
, sizeof(WindowPtr
),
8123 f
= mac_window_to_frame (window_ptr
);
8124 if (f
&& !f
->async_iconified
)
8125 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8126 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8129 case kEventClassMouse
:
8130 if (GetEventKind (eventRef
) == kEventMouseWheelMoved
)
8134 WindowPtr window_ptr
= front_emacs_window ();
8136 if (!IsValidWindowPtr (window_ptr
))
8142 GetEventParameter(eventRef
, kEventParamMouseWheelDelta
,
8143 typeSInt32
, NULL
, sizeof (SInt32
),
8145 GetEventParameter(eventRef
, kEventParamMouseLocation
,
8146 typeQDPoint
, NULL
, sizeof (Point
),
8148 inev
.kind
= WHEEL_EVENT
;
8150 inev
.modifiers
= (mac_event_to_emacs_modifiers (eventRef
)
8151 | ((delta
< 0) ? down_modifier
8153 SetPortWindowPort (window_ptr
);
8154 GlobalToLocal (&point
);
8155 XSETINT (inev
.x
, point
.h
);
8156 XSETINT (inev
.y
, point
.v
);
8157 XSETFRAME (inev
.frame_or_window
,
8158 mac_window_to_frame (window_ptr
));
8159 inev
.timestamp
= EventTimeToTicks (GetEventTime (eventRef
))*(1000/60);
8162 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8166 /* Send the event to the appropriate receiver. */
8167 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
8170 #endif /* USE_CARBON_EVENTS */
8176 WindowPtr window_ptr
;
8180 #if USE_CARBON_EVENTS
8181 /* This is needed to send mouse events like aqua window
8182 buttons to the correct handler. */
8183 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8184 != eventNotHandledErr
)
8188 if (dpyinfo
->grabbed
&& last_mouse_frame
8189 && FRAME_LIVE_P (last_mouse_frame
))
8191 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
8192 part_code
= inContent
;
8196 part_code
= FindWindow (er
.where
, &window_ptr
);
8197 if (tip_window
&& window_ptr
== tip_window
)
8199 HideWindow (tip_window
);
8200 part_code
= FindWindow (er
.where
, &window_ptr
);
8204 if (er
.what
!= mouseDown
&& part_code
!= inContent
)
8210 f
= mac_window_to_frame (front_emacs_window ());
8211 saved_menu_event_location
= er
.where
;
8212 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
8213 XSETFRAME (inev
.frame_or_window
, f
);
8217 if (window_ptr
!= front_emacs_window ())
8218 SelectWindow (window_ptr
);
8221 SInt16 control_part_code
;
8223 Point mouse_loc
= er
.where
;
8225 f
= mac_window_to_frame (window_ptr
);
8226 /* convert to local coordinates of new window */
8227 SetPortWindowPort (window_ptr
);
8229 GlobalToLocal (&mouse_loc
);
8230 #if TARGET_API_MAC_CARBON
8231 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
8232 &control_part_code
);
8234 control_part_code
= FindControl (mouse_loc
, window_ptr
,
8238 #if USE_CARBON_EVENTS
8239 inev
.code
= mac_get_mouse_btn (eventRef
);
8240 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8242 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
8243 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8245 XSETINT (inev
.x
, mouse_loc
.h
);
8246 XSETINT (inev
.y
, mouse_loc
.v
);
8247 inev
.timestamp
= er
.when
* (1000 / 60);
8248 /* ticks to milliseconds */
8250 if (dpyinfo
->grabbed
&& tracked_scroll_bar
8251 #if TARGET_API_MAC_CARBON
8254 || control_part_code
!= 0
8258 struct scroll_bar
*bar
;
8260 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
8262 bar
= tracked_scroll_bar
;
8263 control_part_code
= kControlIndicatorPart
;
8266 bar
= (struct scroll_bar
*) GetControlReference (ch
);
8267 x_scroll_bar_handle_click (bar
, control_part_code
,
8269 if (er
.what
== mouseDown
8270 && control_part_code
== kControlIndicatorPart
)
8271 tracked_scroll_bar
= bar
;
8273 tracked_scroll_bar
= NULL
;
8278 int x
= mouse_loc
.h
;
8279 int y
= mouse_loc
.v
;
8281 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
8282 if (EQ (window
, f
->tool_bar_window
))
8284 if (er
.what
== mouseDown
)
8285 handle_tool_bar_click (f
, x
, y
, 1, 0);
8287 handle_tool_bar_click (f
, x
, y
, 0,
8293 XSETFRAME (inev
.frame_or_window
, f
);
8294 inev
.kind
= MOUSE_CLICK_EVENT
;
8298 if (er
.what
== mouseDown
)
8300 dpyinfo
->grabbed
|= (1 << inev
.code
);
8301 last_mouse_frame
= f
;
8302 /* Ignore any mouse motion that happened
8303 before this event; any subsequent
8304 mouse-movement Emacs events should reflect
8305 only motion after the ButtonPress. */
8310 last_tool_bar_item
= -1;
8314 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
8315 /* If a button is released though it was not
8316 previously pressed, that would be because
8317 of multi-button emulation. */
8318 dpyinfo
->grabbed
= 0;
8320 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
8326 inev
.modifiers
|= down_modifier
;
8329 inev
.modifiers
|= up_modifier
;
8336 #if TARGET_API_MAC_CARBON
8337 DragWindow (window_ptr
, er
.where
, NULL
);
8338 #else /* not TARGET_API_MAC_CARBON */
8339 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
8340 #endif /* not TARGET_API_MAC_CARBON */
8341 /* Update the frame parameters. */
8343 struct frame
*f
= mac_window_to_frame (window_ptr
);
8345 if (f
&& !f
->async_iconified
)
8346 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8351 if (TrackGoAway (window_ptr
, er
.where
))
8353 inev
.kind
= DELETE_WINDOW_EVENT
;
8354 XSETFRAME (inev
.frame_or_window
,
8355 mac_window_to_frame (window_ptr
));
8359 /* window resize handling added --ben */
8361 do_grow_window (window_ptr
, &er
);
8364 /* window zoom handling added --ben */
8367 if (TrackBox (window_ptr
, er
.where
, part_code
))
8368 do_zoom_window (window_ptr
, part_code
);
8378 #if USE_CARBON_EVENTS
8379 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8380 != eventNotHandledErr
)
8383 do_window_update ((WindowPtr
) er
.message
);
8387 #if USE_CARBON_EVENTS
8388 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8389 != eventNotHandledErr
)
8392 switch ((er
.message
>> 24) & 0x000000FF)
8394 case suspendResumeMessage
:
8395 if ((er
.message
& resumeFlag
) == 1)
8401 case mouseMovedMessage
:
8402 previous_help_echo_string
= help_echo_string
;
8403 help_echo_string
= help_echo_object
= help_echo_window
= Qnil
;
8406 do_mouse_moved (er
.where
, &f
);
8408 /* If the contents of the global variable
8409 help_echo_string has changed, generate a
8411 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
8419 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
8421 #if USE_CARBON_EVENTS
8422 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8423 != eventNotHandledErr
)
8426 if (window_ptr
== tip_window
)
8428 HideWindow (tip_window
);
8432 if (!is_emacs_window (window_ptr
))
8435 f
= mac_window_to_frame (window_ptr
);
8437 if ((er
.modifiers
& activeFlag
) != 0)
8439 /* A window has been activated */
8440 Point mouse_loc
= er
.where
;
8442 x_new_focus_frame (dpyinfo
, f
);
8443 activate_scroll_bars (f
);
8445 SetPortWindowPort (window_ptr
);
8446 GlobalToLocal (&mouse_loc
);
8447 /* Window-activated event counts as mouse movement,
8448 so update things that depend on mouse position. */
8449 note_mouse_movement (mac_window_to_frame (window_ptr
),
8454 /* A window has been deactivated */
8455 dpyinfo
->grabbed
= 0;
8457 if (f
== dpyinfo
->x_focus_frame
)
8459 x_new_focus_frame (dpyinfo
, 0);
8460 deactivate_scroll_bars (f
);
8464 if (f
== dpyinfo
->mouse_face_mouse_frame
)
8466 /* If we move outside the frame, then we're
8467 certainly no longer on any text in the
8469 clear_mouse_face (dpyinfo
);
8470 dpyinfo
->mouse_face_mouse_frame
= 0;
8473 /* Generate a nil HELP_EVENT to cancel a help-echo.
8474 Do it only if there's something to cancel.
8475 Otherwise, the startup message is cleared when the
8476 mouse leaves the frame. */
8477 if (any_help_event_p
)
8486 int keycode
= (er
.message
& keyCodeMask
) >> 8;
8489 #if USE_CARBON_EVENTS
8490 /* When using Carbon Events, we need to pass raw keyboard
8491 events to the TSM ourselves. If TSM handles it, it
8492 will pass back noErr, otherwise it will pass back
8493 "eventNotHandledErr" and we can process it
8495 if ((!NILP (Vmac_pass_command_to_system
)
8496 || !(er
.modifiers
& cmdKey
))
8497 && (!NILP (Vmac_pass_control_to_system
)
8498 || !(er
.modifiers
& controlKey
)))
8499 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
8500 != eventNotHandledErr
)
8504 #if TARGET_API_MAC_CARBON
8505 if (!IsValidWindowPtr (front_emacs_window ()))
8514 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
8516 clear_mouse_face (dpyinfo
);
8517 dpyinfo
->mouse_face_hidden
= 1;
8520 if (keycode_to_xkeysym (keycode
, &xkeysym
))
8522 inev
.code
= 0xff00 | xkeysym
;
8523 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
8527 if (er
.modifiers
& (controlKey
|
8528 (NILP (Vmac_command_key_is_meta
) ? optionKey
8531 /* This code comes from Keyboard Resource,
8532 Appendix C of IM - Text. This is necessary
8533 since shift is ignored in KCHR table
8534 translation when option or command is pressed.
8535 It also does not translate correctly
8536 control-shift chars like C-% so mask off shift
8538 int new_modifiers
= er
.modifiers
& 0xe600;
8539 /* mask off option and command */
8540 int new_keycode
= keycode
| new_modifiers
;
8541 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
8542 unsigned long some_state
= 0;
8543 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
8544 &some_state
) & 0xff;
8547 inev
.code
= er
.message
& charCodeMask
;
8548 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
8552 /* If variable mac-convert-keyboard-input-to-latin-1 is
8553 non-nil, convert non-ASCII characters typed at the Mac
8554 keyboard (presumed to be in the Mac Roman encoding) to
8555 iso-latin-1 encoding before they are passed to Emacs.
8556 This enables the Mac keyboard to be used to enter
8557 non-ASCII iso-latin-1 characters directly. */
8558 if (mac_keyboard_text_encoding
!= kTextEncodingMacRoman
8559 && inev
.kind
== ASCII_KEYSTROKE_EVENT
&& inev
.code
>= 128)
8561 static TECObjectRef converter
= NULL
;
8562 OSStatus the_err
= noErr
;
8563 OSStatus convert_status
= noErr
;
8565 if (converter
== NULL
)
8567 the_err
= TECCreateConverter (&converter
,
8568 kTextEncodingMacRoman
,
8569 mac_keyboard_text_encoding
);
8570 current_mac_keyboard_text_encoding
8571 = mac_keyboard_text_encoding
;
8573 else if (mac_keyboard_text_encoding
8574 != current_mac_keyboard_text_encoding
)
8576 /* Free the converter for the current encoding
8577 before creating a new one. */
8578 TECDisposeConverter (converter
);
8579 the_err
= TECCreateConverter (&converter
,
8580 kTextEncodingMacRoman
,
8581 mac_keyboard_text_encoding
);
8582 current_mac_keyboard_text_encoding
8583 = mac_keyboard_text_encoding
;
8586 if (the_err
== noErr
)
8588 unsigned char ch
= inev
.code
;
8589 ByteCount actual_input_length
, actual_output_length
;
8590 unsigned char outch
;
8592 convert_status
= TECConvertText (converter
, &ch
, 1,
8593 &actual_input_length
,
8595 &actual_output_length
);
8596 if (convert_status
== noErr
8597 && actual_input_length
== 1
8598 && actual_output_length
== 1)
8603 #if USE_CARBON_EVENTS
8604 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8606 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8608 XSETFRAME (inev
.frame_or_window
,
8609 mac_window_to_frame (front_emacs_window ()));
8610 inev
.timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
8613 case kHighLevelEvent
:
8614 drag_and_drop_file_list
= Qnil
;
8616 AEProcessAppleEvent(&er
);
8618 /* Build a DRAG_N_DROP_EVENT type event as is done in
8619 constuct_drag_n_drop in w32term.c. */
8620 if (!NILP (drag_and_drop_file_list
))
8622 struct frame
*f
= NULL
;
8626 wp
= front_emacs_window ();
8630 struct frame
*f
= XFRAME (XCAR (Vframe_list
));
8631 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
8632 wp
= front_emacs_window ();
8636 f
= mac_window_to_frame (wp
);
8638 inev
.kind
= DRAG_N_DROP_EVENT
;
8640 inev
.timestamp
= er
.when
* (1000 / 60);
8641 /* ticks to milliseconds */
8642 #if USE_CARBON_EVENTS
8643 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
8645 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
8648 XSETINT (inev
.x
, 0);
8649 XSETINT (inev
.y
, 0);
8651 XSETFRAME (frame
, f
);
8652 inev
.frame_or_window
= Fcons (frame
, drag_and_drop_file_list
);
8654 /* Regardless of whether Emacs was suspended or in the
8655 foreground, ask it to redraw its entire screen.
8656 Otherwise parts of the screen can be left in an
8657 inconsistent state. */
8659 #if TARGET_API_MAC_CARBON
8663 GetWindowPortBounds (wp
, &r
);
8664 InvalWindowRect (wp
, &r
);
8666 #else /* not TARGET_API_MAC_CARBON */
8667 InvalRect (&(wp
->portRect
));
8668 #endif /* not TARGET_API_MAC_CARBON */
8673 #if USE_CARBON_EVENTS
8674 ReleaseEvent (eventRef
);
8677 if (inev
.kind
!= NO_EVENT
)
8679 kbd_buffer_store_event_hold (&inev
, hold_quit
);
8684 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
8689 XSETFRAME (frame
, f
);
8695 any_help_event_p
= 1;
8696 gen_help_event (help_echo_string
, frame
, help_echo_window
,
8697 help_echo_object
, help_echo_pos
);
8701 help_echo_string
= Qnil
;
8702 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
8709 /* If the focus was just given to an autoraising frame,
8711 /* ??? This ought to be able to handle more than one such frame. */
8712 if (pending_autoraise_frame
)
8714 x_raise_frame (pending_autoraise_frame
);
8715 pending_autoraise_frame
= 0;
8718 #if !TARGET_API_MAC_CARBON
8719 check_alarm (); /* simulate the handling of a SIGALRM */
8727 /* Need to override CodeWarrior's input function so no conversion is
8728 done on newlines Otherwise compiled functions in .elc files will be
8729 read incorrectly. Defined in ...:MSL C:MSL
8730 Common:Source:buffer_io.c. */
8733 __convert_to_newlines (unsigned char * p
, size_t * n
)
8739 __convert_from_newlines (unsigned char * p
, size_t * n
)
8746 /* Initialize the struct pointed to by MW to represent a new COLS x
8747 ROWS Macintosh window, using font with name FONTNAME and size
8750 make_mac_frame (FRAME_PTR fp
)
8753 #if TARGET_API_MAC_CARBON
8754 static int making_terminal_window
= 0;
8756 static int making_terminal_window
= 1;
8759 mwp
= fp
->output_data
.mac
;
8761 if (making_terminal_window
)
8763 if (!(mwp
->mWP
= GetNewCWindow (TERM_WINDOW_RESOURCE
, NULL
,
8766 making_terminal_window
= 0;
8770 #if TARGET_API_MAC_CARBON
8773 SetRect (&r
, 0, 0, 1, 1);
8774 if (CreateNewWindow (kDocumentWindowClass
,
8775 kWindowStandardDocumentAttributes
8776 /* | kWindowToolbarButtonAttribute */,
8777 &r
, &mwp
->mWP
) != noErr
)
8779 if (!(mwp
->mWP
= GetNewCWindow (WINDOW_RESOURCE
, NULL
, (WindowPtr
) -1)))
8784 SetWRefCon (mwp
->mWP
, (long) mwp
);
8785 /* so that update events can find this mac_output struct */
8786 mwp
->mFP
= fp
; /* point back to emacs frame */
8788 SetPortWindowPort (mwp
->mWP
);
8790 SizeWindow (mwp
->mWP
, FRAME_PIXEL_WIDTH (fp
), FRAME_PIXEL_HEIGHT (fp
), false);
8795 make_mac_terminal_frame (struct frame
*f
)
8799 XSETFRAME (frame
, f
);
8801 f
->output_method
= output_mac
;
8802 f
->output_data
.mac
= (struct mac_output
*)
8803 xmalloc (sizeof (struct mac_output
));
8804 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
8806 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
8808 FRAME_COLS (f
) = 96;
8809 FRAME_LINES (f
) = 4;
8811 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
8812 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
8814 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
8816 f
->output_data
.mac
->cursor_pixel
= 0;
8817 f
->output_data
.mac
->border_pixel
= 0x00ff00;
8818 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
8819 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
8821 FRAME_FONTSET (f
) = -1;
8822 f
->output_data
.mac
->explicit_parent
= 0;
8825 f
->border_width
= 0;
8827 f
->internal_border_width
= 0;
8832 f
->new_text_cols
= 0;
8833 f
->new_text_lines
= 0;
8839 /* Need to be initialized for unshow_buffer in window.c. */
8840 selected_window
= f
->selected_window
;
8842 Fmodify_frame_parameters (frame
,
8843 Fcons (Fcons (Qfont
,
8844 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
8845 Fmodify_frame_parameters (frame
,
8846 Fcons (Fcons (Qforeground_color
,
8847 build_string ("black")), Qnil
));
8848 Fmodify_frame_parameters (frame
,
8849 Fcons (Fcons (Qbackground_color
,
8850 build_string ("white")), Qnil
));
8852 ShowWindow (f
->output_data
.mac
->mWP
);
8856 /***********************************************************************
8858 ***********************************************************************/
8860 int mac_initialized
= 0;
8863 mac_initialize_display_info ()
8865 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
8866 GDHandle main_device_handle
;
8868 bzero (dpyinfo
, sizeof (*dpyinfo
));
8870 /* Put it on x_display_name_list. */
8871 x_display_name_list
= Fcons (Fcons (build_string ("Mac"), Qnil
),
8872 x_display_name_list
);
8873 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
8876 dpyinfo
->mac_id_name
8877 = (char *) xmalloc (SCHARS (Vinvocation_name
)
8878 + SCHARS (Vsystem_name
)
8880 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
8881 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
8883 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
8884 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
8887 main_device_handle
= LMGetMainDevice();
8889 dpyinfo
->reference_count
= 0;
8890 dpyinfo
->resx
= 75.0;
8891 dpyinfo
->resy
= 75.0;
8892 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
8894 /* HasDepth returns true if it is possible to have a 32 bit display,
8895 but this may not be what is actually used. Mac OSX can do better.
8896 CGMainDisplayID is only available on OSX 10.2 and higher, but the
8897 header for CGGetActiveDisplayList says that the first display returned
8898 is the active one, so we use that. */
8900 CGDirectDisplayID disp_id
[1];
8901 CGDisplayCount disp_count
;
8902 CGDisplayErr error_code
;
8904 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
8905 if (error_code
!= 0)
8906 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
8908 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
8911 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
8912 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
8913 gdDevType
, dpyinfo
->color_p
))
8916 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
8917 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
8918 dpyinfo
->grabbed
= 0;
8919 dpyinfo
->root_window
= NULL
;
8920 dpyinfo
->image_cache
= make_image_cache ();
8922 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
8923 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
8924 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
8925 dpyinfo
->mouse_face_window
= Qnil
;
8926 dpyinfo
->mouse_face_overlay
= Qnil
;
8927 dpyinfo
->mouse_face_hidden
= 0;
8930 struct mac_display_info
*
8931 mac_term_init (display_name
, xrm_option
, resource_name
)
8932 Lisp_Object display_name
;
8934 char *resource_name
;
8936 struct mac_display_info
*dpyinfo
;
8937 GDHandle main_device_handle
;
8939 if (!mac_initialized
)
8942 mac_initialized
= 1;
8945 mac_initialize_display_info (display_name
);
8947 dpyinfo
= &one_mac_display_info
;
8949 main_device_handle
= LMGetMainDevice();
8951 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
8952 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
8961 extern int inhibit_window_system
;
8962 extern int noninteractive
;
8963 CFBundleRef appsBundle
;
8966 /* No need to test if already -nw*/
8967 if (inhibit_window_system
|| noninteractive
)
8970 appsBundle
= CFBundleGetMainBundle();
8971 if (appsBundle
!= NULL
)
8973 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
8974 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
8975 /* We found the bundle identifier, now we know we are valid. */
8982 /* MAC_TODO: Have this start the bundled executable */
8984 /* For now, prevent the fatal error by bringing it up in the terminal */
8985 inhibit_window_system
= 1;
8989 MakeMeTheFrontProcess ()
8991 ProcessSerialNumber psn
;
8994 err
= GetCurrentProcess (&psn
);
8996 (void) SetFrontProcess (&psn
);
8999 /***** Code to handle C-g testing *****/
9001 /* Contains the Mac modifier formed from quit_char */
9002 static mac_quit_char_modifiers
= 0;
9003 static mac_quit_char_keycode
;
9004 extern int quit_char
;
9007 mac_determine_quit_char_modifiers()
9009 /* Todo: Determine modifiers from quit_char. */
9010 UInt32 qc_modifiers
= ctrl_modifier
;
9013 mac_quit_char_modifiers
= 0;
9014 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
9015 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
9016 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
9017 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
9021 init_quit_char_handler ()
9023 /* TODO: Let this support keys other the 'g' */
9024 mac_quit_char_keycode
= 5;
9025 /* Look at <architecture/adb_kb_map.h> for details */
9026 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9028 mac_determine_quit_char_modifiers();
9032 quit_char_comp (EventRef inEvent
, void *inCompData
)
9034 if (GetEventClass(inEvent
) != kEventClassKeyboard
)
9036 if (GetEventKind(inEvent
) != kEventRawKeyDown
)
9040 UInt32 keyModifiers
;
9041 GetEventParameter(inEvent
, kEventParamKeyCode
,
9042 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
9043 if (keyCode
!= mac_quit_char_keycode
)
9045 GetEventParameter(inEvent
, kEventParamKeyModifiers
,
9046 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyModifiers
);
9047 if (keyModifiers
!= mac_quit_char_modifiers
)
9054 mac_check_for_quit_char ()
9057 static EMACS_TIME last_check_time
= { 0, 0 };
9058 static EMACS_TIME one_second
= { 1, 0 };
9061 /* If windows are not initialized, return immediately (keep it bouncin'). */
9062 if (!mac_quit_char_modifiers
)
9065 /* Don't check if last check is less than a second ago. */
9066 EMACS_GET_TIME (now
);
9067 EMACS_SUB_TIME (t
, now
, last_check_time
);
9068 if (EMACS_TIME_LT (t
, one_second
))
9070 last_check_time
= now
;
9072 /* Redetermine modifiers because they are based on lisp variables */
9073 mac_determine_quit_char_modifiers ();
9075 /* Fill the queue with events */
9077 ReceiveNextEvent (0, NULL
, kEventDurationNoWait
, false, &event
);
9078 event
= FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp
,
9083 struct input_event e
;
9085 /* Use an input_event to emulate what the interrupt handler does. */
9087 e
.kind
= ASCII_KEYSTROKE_EVENT
;
9091 e
.timestamp
= EventTimeToTicks (GetEventTime (event
)) * (1000/60);
9092 XSETFRAME (e
.frame_or_window
, mac_window_to_frame (front_emacs_window ()));
9093 /* Remove event from queue to prevent looping. */
9094 RemoveEventFromQueue (GetMainEventQueue (), event
);
9095 ReleaseEvent (event
);
9096 kbd_buffer_store_event (&e
);
9100 #endif /* MAC_OSX */
9102 /* Set up use of X before we make the first connection. */
9104 extern frame_parm_handler mac_frame_parm_handlers
[];
9106 static struct redisplay_interface x_redisplay_interface
=
9108 mac_frame_parm_handlers
,
9112 x_clear_end_of_line
,
9114 x_after_update_window_line
,
9115 x_update_window_begin
,
9116 x_update_window_end
,
9120 x_clear_window_mouse_face
,
9121 x_get_glyph_overhangs
,
9122 x_fix_overlapping_area
,
9123 x_draw_fringe_bitmap
,
9124 0, /* define_fringe_bitmap */
9125 0, /* destroy_fringe_bitmap */
9126 mac_per_char_metric
,
9128 NULL
, /* mac_compute_glyph_string_overhangs */
9129 x_draw_glyph_string
,
9130 mac_define_frame_cursor
,
9131 mac_clear_frame_area
,
9132 mac_draw_window_cursor
,
9133 mac_draw_vertical_window_border
,
9134 mac_shift_glyphs_for_insert
9140 rif
= &x_redisplay_interface
;
9142 clear_frame_hook
= x_clear_frame
;
9143 ins_del_lines_hook
= x_ins_del_lines
;
9144 delete_glyphs_hook
= x_delete_glyphs
;
9145 ring_bell_hook
= XTring_bell
;
9146 reset_terminal_modes_hook
= XTreset_terminal_modes
;
9147 set_terminal_modes_hook
= XTset_terminal_modes
;
9148 update_begin_hook
= x_update_begin
;
9149 update_end_hook
= x_update_end
;
9150 set_terminal_window_hook
= XTset_terminal_window
;
9151 read_socket_hook
= XTread_socket
;
9152 frame_up_to_date_hook
= XTframe_up_to_date
;
9153 mouse_position_hook
= XTmouse_position
;
9154 frame_rehighlight_hook
= XTframe_rehighlight
;
9155 frame_raise_lower_hook
= XTframe_raise_lower
;
9157 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
9158 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
9159 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
9160 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
9162 scroll_region_ok
= 1; /* we'll scroll partial frames */
9163 char_ins_del_ok
= 1;
9164 line_ins_del_ok
= 1; /* we'll just blt 'em */
9165 fast_clear_end_of_line
= 1; /* X does this well */
9166 memory_below_frame
= 0; /* we don't remember what scrolls
9171 last_tool_bar_item
= -1;
9172 any_help_event_p
= 0;
9174 /* Try to use interrupt input; if we can't, then start polling. */
9175 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
9177 #ifdef USE_X_TOOLKIT
9178 XtToolkitInitialize ();
9179 Xt_app_con
= XtCreateApplicationContext ();
9180 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
9182 /* Install an asynchronous timer that processes Xt timeout events
9183 every 0.1s. This is necessary because some widget sets use
9184 timeouts internally, for example the LessTif menu bar, or the
9185 Xaw3d scroll bar. When Xt timouts aren't processed, these
9186 widgets don't behave normally. */
9188 EMACS_TIME interval
;
9189 EMACS_SET_SECS_USECS (interval
, 0, 100000);
9190 start_atimer (ATIMER_CONTINUOUS
, interval
, x_process_timeouts
, 0);
9194 #if USE_TOOLKIT_SCROLL_BARS
9195 xaw3d_arrow_scroll
= False
;
9196 xaw3d_pick_top
= True
;
9200 /* Note that there is no real way portable across R3/R4 to get the
9201 original error handler. */
9202 XSetErrorHandler (x_error_handler
);
9203 XSetIOErrorHandler (x_io_error_quitter
);
9205 /* Disable Window Change signals; they are handled by X events. */
9207 signal (SIGWINCH
, SIG_DFL
);
9208 #endif /* ! defined (SIGWINCH) */
9210 signal (SIGPIPE
, x_connection_signal
);
9213 mac_initialize_display_info ();
9215 #if TARGET_API_MAC_CARBON
9216 init_required_apple_events ();
9218 init_mac_drag_n_drop ();
9220 #if USE_CARBON_EVENTS
9221 init_service_handler ();
9223 init_quit_char_handler ();
9226 DisableMenuCommand (NULL
, kHICommandQuit
);
9228 if (!inhibit_window_system
)
9229 MakeMeTheFrontProcess ();
9238 staticpro (&x_error_message_string
);
9239 x_error_message_string
= Qnil
;
9242 Fprovide (intern ("mac-carbon"), Qnil
);
9244 staticpro (&Qreverse
);
9245 Qreverse
= intern ("reverse");
9247 staticpro (&x_display_name_list
);
9248 x_display_name_list
= Qnil
;
9250 staticpro (&last_mouse_scroll_bar
);
9251 last_mouse_scroll_bar
= Qnil
;
9253 staticpro (&Qvendor_specific_keysyms
);
9254 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
9256 staticpro (&last_mouse_press_frame
);
9257 last_mouse_press_frame
= Qnil
;
9259 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
9260 staticpro (&Qmac_ready_for_drag_n_drop
);
9262 Qbig5
= intern ("big5");
9265 Qcn_gb
= intern ("cn-gb");
9266 staticpro (&Qcn_gb
);
9268 Qsjis
= intern ("sjis");
9271 Qeuc_kr
= intern ("euc-kr");
9272 staticpro (&Qeuc_kr
);
9274 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p
,
9275 doc
: /* *Non-nil means autoselect window with mouse pointer. */);
9276 x_autoselect_window_p
= 0;
9278 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
9279 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
9280 Vx_toolkit_scroll_bars
= Qt
;
9282 DEFVAR_BOOL ("x-use-underline-position-properties",
9283 &x_use_underline_position_properties
,
9284 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9285 nil means ignore them. If you encounter fonts with bogus
9286 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9287 to 4.1, set this to nil. */);
9288 x_use_underline_position_properties
= 0;
9290 staticpro (&last_mouse_motion_frame
);
9291 last_mouse_motion_frame
= Qnil
;
9293 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
9294 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
9295 Otherwise the option key is used. */);
9296 Vmac_command_key_is_meta
= Qt
;
9298 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
9299 doc
: /* Non-nil means that the control and meta keys are reversed. This is
9300 useful for non-standard keyboard layouts. */);
9301 Vmac_reverse_ctrl_meta
= Qnil
;
9303 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9304 &Vmac_emulate_three_button_mouse
,
9305 doc
: /* t means that when the option-key is held down while pressing the
9306 mouse button, the click will register as mouse-2 and while the
9307 command-key is held down, the click will register as mouse-3.
9308 'reverse means that the the option-key will register for mouse-3
9309 and the command-key will register for mouse-2. nil means that
9310 not emulation should be done and the modifiers should be placed
9311 on the mouse-1 event. */);
9312 Vmac_emulate_three_button_mouse
= Qnil
;
9314 #if USE_CARBON_EVENTS
9315 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
9316 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
9317 the right click will be mouse-3.
9318 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9319 Vmac_wheel_button_is_mouse_2
= Qt
;
9321 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
9322 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9323 Toolbox for processing before Emacs sees it. */);
9324 Vmac_pass_command_to_system
= Qt
;
9326 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
9327 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9328 Toolbox for processing before Emacs sees it. */);
9329 Vmac_pass_control_to_system
= Qt
;
9332 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding
,
9333 doc
: /* One of the Text Encoding Base constant values defined in the
9334 Basic Text Constants section of Inside Macintosh - Text Encoding
9335 Conversion Manager. Its value determines the encoding characters
9336 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9337 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9338 its default value, no conversion takes place. If it is set to
9339 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9340 characters typed on Mac keyboard are first converted into the
9341 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9342 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9343 command, this enables the Mac keyboard to be used to enter non-ASCII
9344 characters directly. */);
9345 mac_keyboard_text_encoding
= kTextEncodingMacRoman
;
9348 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9349 (do not change this comment) */