1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
71 #include <sys/param.h>
76 #include "dispextern.h"
78 #include "termhooks.h"
86 #include "intervals.h"
90 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
91 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
92 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
93 #define macShiftKey (shiftKey)
94 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
95 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
97 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
100 /* Non-nil means Emacs uses toolkit scroll bars. */
102 Lisp_Object Vx_toolkit_scroll_bars
;
104 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
105 Lisp_Object Vmac_use_core_graphics
;
108 /* Non-zero means that a HELP_EVENT has been generated since Emacs
111 static int any_help_event_p
;
113 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
114 static Lisp_Object last_window
;
116 /* This is a chain of structures for all the X displays currently in
119 struct x_display_info
*x_display_list
;
121 /* This is a list of cons cells, each of the form (NAME
122 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
123 x_display_list and in the same order. NAME is the name of the
124 frame. FONT-LIST-CACHE records previous values returned by
125 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
126 equivalent, which is implemented with a Lisp object, for the
129 Lisp_Object x_display_name_list
;
131 /* This is display since Mac does not support multiple ones. */
132 struct mac_display_info one_mac_display_info
;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the XT functions.
136 It is zero while not inside an update. In that case, the XT
137 functions assume that `selected_frame' is the frame to apply to. */
139 extern struct frame
*updating_frame
;
141 /* This is a frame waiting to be auto-raised, within XTread_socket. */
143 struct frame
*pending_autoraise_frame
;
147 Formerly, we used PointerMotionHintMask (in standard_event_mask)
148 so that we would have to call XQueryPointer after each MotionNotify
149 event to ask for another such event. However, this made mouse tracking
150 slow, and there was a bug that made it eventually stop.
152 Simply asking for MotionNotify all the time seems to work better.
154 In order to avoid asking for motion events and then throwing most
155 of them away or busy-polling the server for mouse positions, we ask
156 the server for pointer motion hints. This means that we get only
157 one event per group of mouse movements. "Groups" are delimited by
158 other kinds of events (focus changes and button clicks, for
159 example), or by XQueryPointer calls; when one of these happens, we
160 get another MotionNotify event the next time the mouse moves. This
161 is at least as efficient as getting motion events when mouse
162 tracking is on, and I suspect only negligibly worse when tracking
165 /* Where the mouse was last time we reported a mouse event. */
167 static Rect last_mouse_glyph
;
168 static FRAME_PTR last_mouse_glyph_frame
;
170 /* The scroll bar in which the last X motion event occurred.
172 If the last X motion event occurred in a scroll bar, we set this so
173 XTmouse_position can know whether to report a scroll bar motion or
176 If the last X motion event didn't occur in a scroll bar, we set
177 this to Qnil, to tell XTmouse_position to return an ordinary motion
180 static Lisp_Object last_mouse_scroll_bar
;
182 /* This is a hack. We would really prefer that XTmouse_position would
183 return the time associated with the position it returns, but there
184 doesn't seem to be any way to wrest the time-stamp from the server
185 along with the position query. So, we just keep track of the time
186 of the last movement we received, and return that in hopes that
187 it's somewhat accurate. */
189 static Time last_mouse_movement_time
;
191 struct scroll_bar
*tracked_scroll_bar
= NULL
;
193 /* Incremented by XTread_socket whenever it really tries to read
197 static int volatile input_signal_count
;
199 static int input_signal_count
;
202 extern Lisp_Object Vsystem_name
;
204 /* A mask of extra modifier bits to put into every keyboard char. */
206 extern EMACS_INT extra_keyboard_modifiers
;
208 /* The keysyms to use for the various modifiers. */
210 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qmodifier_value
;
212 extern int inhibit_window_system
;
214 #if __MRC__ && !TARGET_API_MAC_CARBON
215 QDGlobals qd
; /* QuickDraw global information structure. */
218 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
220 struct mac_display_info
*mac_display_info_for_display (Display
*);
221 static void x_update_window_end
P_ ((struct window
*, int, int));
222 static int x_io_error_quitter
P_ ((Display
*));
223 int x_catch_errors
P_ ((Display
*));
224 void x_uncatch_errors
P_ ((Display
*, int));
225 void x_lower_frame
P_ ((struct frame
*));
226 void x_scroll_bar_clear
P_ ((struct frame
*));
227 int x_had_errors_p
P_ ((Display
*));
228 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
229 void x_raise_frame
P_ ((struct frame
*));
230 void x_set_window_size
P_ ((struct frame
*, int, int, int));
231 void x_wm_set_window_state
P_ ((struct frame
*, int));
232 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
233 void mac_initialize
P_ ((void));
234 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
235 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
236 static void x_update_end
P_ ((struct frame
*));
237 static void XTframe_up_to_date
P_ ((struct frame
*));
238 static void XTset_terminal_modes
P_ ((void));
239 static void XTreset_terminal_modes
P_ ((void));
240 static void x_clear_frame
P_ ((void));
241 static void frame_highlight
P_ ((struct frame
*));
242 static void frame_unhighlight
P_ ((struct frame
*));
243 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
244 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
245 struct frame
*, struct input_event
*));
246 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
247 EventRecord
*, struct input_event
*));
248 static void XTframe_rehighlight
P_ ((struct frame
*));
249 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
250 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
251 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
252 enum text_cursor_kinds
));
254 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
255 static void x_flush
P_ ((struct frame
*f
));
256 static void x_update_begin
P_ ((struct frame
*));
257 static void x_update_window_begin
P_ ((struct window
*));
258 static void x_after_update_window_line
P_ ((struct glyph_row
*));
259 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
260 enum scroll_bar_part
*,
261 Lisp_Object
*, Lisp_Object
*,
264 static int is_emacs_window
P_ ((WindowPtr
));
266 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
268 /* Defined in macmenu.h. */
269 extern void menubar_selection_callback (FRAME_PTR
, int);
271 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
272 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
273 #define GC_FONT(gc) ((gc)->xgcv.font)
274 #define GC_CLIP_REGION(gc) ((gc)->clip_region)
275 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
277 static RgnHandle saved_port_clip_region
= NULL
;
280 mac_begin_clip (region
)
283 static RgnHandle new_region
= NULL
;
285 if (saved_port_clip_region
== NULL
)
286 saved_port_clip_region
= NewRgn ();
287 if (new_region
== NULL
)
288 new_region
= NewRgn ();
292 GetClip (saved_port_clip_region
);
293 SectRgn (saved_port_clip_region
, region
, new_region
);
294 SetClip (new_region
);
299 mac_end_clip (region
)
303 SetClip (saved_port_clip_region
);
307 /* X display function emulation */
310 XFreePixmap (display
, pixmap
)
311 Display
*display
; /* not used */
314 DisposeGWorld (pixmap
);
318 /* Mac version of XDrawLine. */
321 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
326 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
328 RGBForeColor (GC_FORE_COLOR (gc
));
330 mac_begin_clip (GC_CLIP_REGION (gc
));
333 mac_end_clip (GC_CLIP_REGION (gc
));
337 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
346 GetGWorld (&old_port
, &old_gdh
);
349 RGBForeColor (GC_FORE_COLOR (gc
));
351 LockPixels (GetGWorldPixMap (p
));
354 UnlockPixels (GetGWorldPixMap (p
));
356 SetGWorld (old_port
, old_gdh
);
361 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
365 unsigned int width
, height
;
369 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
371 RGBBackColor (GC_BACK_COLOR (gc
));
372 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
374 mac_begin_clip (GC_CLIP_REGION (gc
));
376 mac_end_clip (GC_CLIP_REGION (gc
));
378 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
382 /* Mac version of XClearArea. */
385 mac_clear_area (f
, x
, y
, width
, height
)
388 unsigned int width
, height
;
390 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
393 /* Mac version of XClearWindow. */
399 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
401 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
403 #if TARGET_API_MAC_CARBON
407 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
410 #else /* not TARGET_API_MAC_CARBON */
411 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
412 #endif /* not TARGET_API_MAC_CARBON */
416 /* Mac replacement for XCopyArea. */
419 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
422 int x
, y
, width
, height
;
423 unsigned short *bits
;
429 bitmap
.rowBytes
= sizeof(unsigned short);
430 bitmap
.baseAddr
= (char *)bits
;
431 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
433 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
435 RGBForeColor (GC_FORE_COLOR (gc
));
436 RGBBackColor (GC_BACK_COLOR (gc
));
437 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
439 mac_begin_clip (GC_CLIP_REGION (gc
));
440 #if TARGET_API_MAC_CARBON
446 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
447 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
448 UnlockPortBits (port
);
450 #else /* not TARGET_API_MAC_CARBON */
451 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
452 overlay_p
? srcOr
: srcCopy
, 0);
453 #endif /* not TARGET_API_MAC_CARBON */
454 mac_end_clip (GC_CLIP_REGION (gc
));
456 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
460 /* Mac replacement for XCreateBitmapFromBitmapData. */
463 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
468 static unsigned char swap_nibble
[16]
469 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
470 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
471 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
472 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
476 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
477 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
478 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
479 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
480 for (i
= 0; i
< h
; i
++)
482 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
483 for (j
= 0; j
< w1
; j
++)
485 /* Bitswap XBM bytes to match how Mac does things. */
486 unsigned char c
= *bits
++;
487 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
488 | (swap_nibble
[(c
>>4) & 0xf]));;
492 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
497 mac_free_bitmap (bitmap
)
500 xfree (bitmap
->baseAddr
);
505 XCreatePixmap (display
, w
, width
, height
, depth
)
506 Display
*display
; /* not used */
508 unsigned int width
, height
;
515 SetPortWindowPort (w
);
517 SetRect (&r
, 0, 0, width
, height
);
518 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
526 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
527 Display
*display
; /* not used */
530 unsigned int width
, height
;
531 unsigned long fg
, bg
;
538 static GC gc
= NULL
; /* not reentrant */
541 gc
= XCreateGC (display
, w
, 0, NULL
);
543 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
547 GetGWorld (&old_port
, &old_gdh
);
548 SetGWorld (pixmap
, NULL
);
549 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
550 XSetForeground (display
, gc
, fg
);
551 XSetBackground (display
, gc
, bg
);
552 RGBForeColor (GC_FORE_COLOR (gc
));
553 RGBBackColor (GC_BACK_COLOR (gc
));
554 LockPixels (GetGWorldPixMap (pixmap
));
555 #if TARGET_API_MAC_CARBON
556 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
557 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
558 #else /* not TARGET_API_MAC_CARBON */
559 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
560 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
561 #endif /* not TARGET_API_MAC_CARBON */
562 UnlockPixels (GetGWorldPixMap (pixmap
));
563 SetGWorld (old_port
, old_gdh
);
564 mac_free_bitmap (&bitmap
);
570 /* Mac replacement for XFillRectangle. */
573 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
577 unsigned int width
, height
;
581 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
583 RGBForeColor (GC_FORE_COLOR (gc
));
584 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
586 mac_begin_clip (GC_CLIP_REGION (gc
));
587 PaintRect (&r
); /* using foreground color of gc */
588 mac_end_clip (GC_CLIP_REGION (gc
));
592 /* Mac replacement for XDrawRectangle: dest is a window. */
595 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
599 unsigned int width
, height
;
603 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
605 RGBForeColor (GC_FORE_COLOR (gc
));
606 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
608 mac_begin_clip (GC_CLIP_REGION (gc
));
609 FrameRect (&r
); /* using foreground color of gc */
610 mac_end_clip (GC_CLIP_REGION (gc
));
616 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
617 ConstUniCharArrayPtr text
;
618 UniCharCount text_length
;
620 ATSUTextLayout
*text_layout
;
623 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
625 if (saved_text_layout
== NULL
)
627 UniCharCount lengths
[] = {kATSUToTextEnd
};
628 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
629 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
630 static ATSLineLayoutOptions line_layout
=
631 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
632 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
634 kATSLineIsDisplayOnly
| kATSLineFractDisable
637 ATSUAttributeValuePtr values
[] = {&line_layout
};
639 err
= ATSUCreateTextLayoutWithTextPtr (text
,
640 kATSUFromTextBeginning
,
646 err
= ATSUSetLayoutControls (saved_text_layout
,
647 sizeof (tags
) / sizeof (tags
[0]),
648 tags
, sizes
, values
);
649 /* XXX: Should we do this? */
651 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
655 err
= ATSUSetRunStyle (saved_text_layout
, style
,
656 kATSUFromTextBeginning
, kATSUToTextEnd
);
658 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
659 kATSUFromTextBeginning
,
665 *text_layout
= saved_text_layout
;
672 mac_invert_rectangle (f
, x
, y
, width
, height
)
675 unsigned int width
, height
;
679 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
681 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
688 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, mode
, bytes_per_char
)
693 int nchars
, mode
, bytes_per_char
;
695 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
696 UInt32 textFlags
, savedFlags
;
697 if (!NILP(Vmac_use_core_graphics
)) {
698 textFlags
= kQDUseCGTextRendering
;
699 savedFlags
= SwapQDTextFlags(textFlags
);
703 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
705 RGBForeColor (GC_FORE_COLOR (gc
));
707 RGBBackColor (GC_BACK_COLOR (gc
));
710 if (GC_FONT (gc
)->mac_style
)
713 ATSUTextLayout text_layout
;
715 xassert (bytes_per_char
== 2);
717 #ifndef WORDS_BIG_ENDIAN
720 UniChar
*text
= (UniChar
*)buf
;
722 for (i
= 0; i
< nchars
; i
++)
723 text
[i
] = EndianU16_BtoN (text
[i
]);
726 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
728 GC_FONT (gc
)->mac_style
,
733 if (NILP (Vmac_use_core_graphics
))
736 mac_begin_clip (GC_CLIP_REGION (gc
));
738 ATSUDrawText (text_layout
,
739 kATSUFromTextBeginning
, kATSUToTextEnd
,
740 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
741 mac_end_clip (GC_CLIP_REGION (gc
));
747 CGContextRef context
;
748 float port_height
= FRAME_PIXEL_HEIGHT (f
);
749 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
750 ByteCount sizes
[] = {sizeof (CGContextRef
)};
751 ATSUAttributeValuePtr values
[] = {&context
};
754 QDBeginCGContext (port
, &context
);
755 if (gc
->n_clip_rects
)
757 CGContextTranslateCTM (context
, 0, port_height
);
758 CGContextScaleCTM (context
, 1, -1);
759 CGContextClipToRects (context
, gc
->clip_rects
,
761 CGContextScaleCTM (context
, 1, -1);
762 CGContextTranslateCTM (context
, 0, -port_height
);
764 CGContextSetRGBFillColor
766 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
767 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
768 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
770 err
= ATSUSetLayoutControls (text_layout
,
771 sizeof (tags
) / sizeof (tags
[0]),
772 tags
, sizes
, values
);
774 ATSUDrawText (text_layout
,
775 kATSUFromTextBeginning
, kATSUToTextEnd
,
776 Long2Fix (x
), Long2Fix (port_height
- y
));
777 CGContextSynchronize (context
);
778 QDEndCGContext (port
, &context
);
780 /* This doesn't work on Mac OS X 10.1. */
781 ATSUClearLayoutControls (text_layout
,
782 sizeof (tags
) / sizeof (tags
[0]),
785 ATSUSetLayoutControls (text_layout
,
786 sizeof (tags
) / sizeof (tags
[0]),
787 tags
, sizes
, values
);
796 TextFont (GC_FONT (gc
)->mac_fontnum
);
797 TextSize (GC_FONT (gc
)->mac_fontsize
);
798 TextFace (GC_FONT (gc
)->mac_fontface
);
801 mac_begin_clip (GC_CLIP_REGION (gc
));
803 DrawText (buf
, 0, nchars
* bytes_per_char
);
804 mac_end_clip (GC_CLIP_REGION (gc
));
810 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
811 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
812 if (!NILP(Vmac_use_core_graphics
))
813 SwapQDTextFlags(savedFlags
);
818 /* Mac replacement for XDrawString. */
821 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
828 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
832 /* Mac replacement for XDrawString16. */
835 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
842 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
, 2);
846 /* Mac replacement for XDrawImageString. */
849 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
)
856 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
860 /* Mac replacement for XDrawString16. */
863 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
)
870 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
, 2);
874 /* Mac replacement for XCopyArea: dest must be window. */
877 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
882 unsigned int width
, height
;
887 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
889 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
890 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
892 ForeColor (blackColor
);
893 BackColor (whiteColor
);
895 mac_begin_clip (GC_CLIP_REGION (gc
));
896 LockPixels (GetGWorldPixMap (src
));
897 #if TARGET_API_MAC_CARBON
903 CopyBits (GetPortBitMapForCopyBits (src
),
904 GetPortBitMapForCopyBits (port
),
905 &src_r
, &dest_r
, srcCopy
, 0);
906 UnlockPortBits (port
);
908 #else /* not TARGET_API_MAC_CARBON */
909 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
910 &src_r
, &dest_r
, srcCopy
, 0);
911 #endif /* not TARGET_API_MAC_CARBON */
912 UnlockPixels (GetGWorldPixMap (src
));
913 mac_end_clip (GC_CLIP_REGION (gc
));
915 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
920 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
921 width
, height
, dest_x
, dest_y
)
926 unsigned int width
, height
;
931 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
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
);
936 ForeColor (blackColor
);
937 BackColor (whiteColor
);
939 mac_begin_clip (GC_CLIP_REGION (gc
));
940 LockPixels (GetGWorldPixMap (src
));
941 LockPixels (GetGWorldPixMap (mask
));
942 #if TARGET_API_MAC_CARBON
948 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
949 GetPortBitMapForCopyBits (port
),
950 &src_r
, &src_r
, &dest_r
);
951 UnlockPortBits (port
);
953 #else /* not TARGET_API_MAC_CARBON */
954 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
955 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
956 #endif /* not TARGET_API_MAC_CARBON */
957 UnlockPixels (GetGWorldPixMap (mask
));
958 UnlockPixels (GetGWorldPixMap (src
));
959 mac_end_clip (GC_CLIP_REGION (gc
));
961 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
965 /* Mac replacement for XCopyArea: used only for scrolling. */
968 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
972 unsigned int width
, height
;
975 #if TARGET_API_MAC_CARBON
977 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
979 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
980 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
981 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
982 kScrollWindowNoOptions
, dummy
);
984 #else /* not TARGET_API_MAC_CARBON */
986 WindowPtr w
= FRAME_MAC_WINDOW (f
);
990 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
991 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
993 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
994 color mapping in CopyBits. Otherwise, it will be slow. */
995 ForeColor (blackColor
);
996 BackColor (whiteColor
);
997 mac_begin_clip (GC_CLIP_REGION (gc
));
998 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
999 mac_end_clip (GC_CLIP_REGION (gc
));
1001 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1002 #endif /* not TARGET_API_MAC_CARBON */
1006 /* Mac replacement for XChangeGC. */
1009 XChangeGC (display
, gc
, mask
, xgcv
)
1015 if (mask
& GCForeground
)
1016 XSetForeground (display
, gc
, xgcv
->foreground
);
1017 if (mask
& GCBackground
)
1018 XSetBackground (display
, gc
, xgcv
->background
);
1020 XSetFont (display
, gc
, xgcv
->font
);
1024 /* Mac replacement for XCreateGC. */
1027 XCreateGC (display
, window
, mask
, xgcv
)
1033 GC gc
= xmalloc (sizeof (*gc
));
1037 bzero (gc
, sizeof (*gc
));
1038 XChangeGC (display
, gc
, mask
, xgcv
);
1045 /* Used in xfaces.c. */
1048 XFreeGC (display
, gc
)
1052 if (gc
->clip_region
)
1053 DisposeRgn (gc
->clip_region
);
1058 /* Mac replacement for XGetGCValues. */
1061 XGetGCValues (display
, gc
, mask
, xgcv
)
1067 if (mask
& GCForeground
)
1068 xgcv
->foreground
= gc
->xgcv
.foreground
;
1069 if (mask
& GCBackground
)
1070 xgcv
->background
= gc
->xgcv
.background
;
1072 xgcv
->font
= gc
->xgcv
.font
;
1076 /* Mac replacement for XSetForeground. */
1079 XSetForeground (display
, gc
, color
)
1082 unsigned long color
;
1084 if (gc
->xgcv
.foreground
!= color
)
1086 gc
->xgcv
.foreground
= color
;
1087 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1088 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1089 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1094 /* Mac replacement for XSetBackground. */
1097 XSetBackground (display
, gc
, color
)
1100 unsigned long color
;
1102 if (gc
->xgcv
.background
!= color
)
1104 gc
->xgcv
.background
= color
;
1105 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1106 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1107 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1112 /* Mac replacement for XSetFont. */
1115 XSetFont (display
, gc
, font
)
1120 gc
->xgcv
.font
= font
;
1124 /* Mac replacement for XSetClipRectangles. */
1127 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1135 if (n
< 0 || n
> MAX_CLIP_RECTS
)
1139 if (gc
->clip_region
)
1141 DisposeRgn (gc
->clip_region
);
1142 gc
->clip_region
= NULL
;
1147 if (gc
->clip_region
== NULL
)
1148 gc
->clip_region
= NewRgn ();
1149 RectRgn (gc
->clip_region
, rectangles
);
1152 RgnHandle region
= NewRgn ();
1154 for (i
= 1; i
< n
; i
++)
1156 RectRgn (region
, rectangles
+ i
);
1157 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1159 DisposeRgn (region
);
1162 #if defined (MAC_OSX) && USE_ATSUI
1163 gc
->n_clip_rects
= n
;
1165 for (i
= 0; i
< n
; i
++)
1167 Rect
*rect
= rectangles
+ i
;
1169 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1170 rect
->right
- rect
->left
,
1171 rect
->bottom
- rect
->top
);
1177 /* Mac replacement for XSetClipMask. */
1180 mac_reset_clip_rectangles (display
, gc
)
1184 mac_set_clip_rectangles (display
, gc
, NULL
, 0);
1188 /* Mac replacement for XSetWindowBackground. */
1191 XSetWindowBackground (display
, w
, color
)
1194 unsigned long color
;
1196 #if !TARGET_API_MAC_CARBON
1197 AuxWinHandle aw_handle
;
1198 CTabHandle ctab_handle
;
1199 ColorSpecPtr ct_table
;
1204 bg_color
.red
= RED16_FROM_ULONG (color
);
1205 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1206 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1208 #if TARGET_API_MAC_CARBON
1209 SetWindowContentColor (w
, &bg_color
);
1211 if (GetAuxWin (w
, &aw_handle
))
1213 ctab_handle
= (*aw_handle
)->awCTable
;
1214 HandToHand ((Handle
*) &ctab_handle
);
1215 ct_table
= (*ctab_handle
)->ctTable
;
1216 ct_size
= (*ctab_handle
)->ctSize
;
1217 while (ct_size
> -1)
1219 if (ct_table
->value
== 0)
1221 ct_table
->rgb
= bg_color
;
1222 CTabChanged (ctab_handle
);
1223 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1231 /* x_sync is a no-op on Mac. */
1239 /* Flush display of frame F, or of all frames if F is null. */
1245 #if TARGET_API_MAC_CARBON
1248 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1250 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1256 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1257 Calls to XFlush should be unnecessary because the X output buffer
1258 is flushed automatically as needed by calls to XPending,
1259 XNextEvent, or XWindowEvent according to the XFlush man page.
1260 XTread_socket calls XPending. Removing XFlush improves
1263 #define XFlush(DISPLAY) (void) 0
1266 /* Return the struct mac_display_info corresponding to DPY. There's
1269 struct mac_display_info
*
1270 mac_display_info_for_display (dpy
)
1273 return &one_mac_display_info
;
1278 /***********************************************************************
1279 Starting and ending an update
1280 ***********************************************************************/
1282 /* Start an update of frame F. This function is installed as a hook
1283 for update_begin, i.e. it is called when update_begin is called.
1284 This function is called prior to calls to x_update_window_begin for
1285 each window being updated. */
1291 #if TARGET_API_MAC_CARBON
1292 /* During update of a frame, availability of input events is
1293 periodically checked with ReceiveNextEvent if
1294 redisplay-dont-pause is nil. That normally flushes window buffer
1295 changes for every check, and thus screen update looks waving even
1296 if no input is available. So we disable screen updates during
1297 update of a frame. */
1299 DisableScreenUpdates ();
1305 /* Start update of window W. Set the global variable updated_window
1306 to the window being updated and set output_cursor to the cursor
1310 x_update_window_begin (w
)
1313 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1314 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1317 set_output_cursor (&w
->cursor
);
1321 if (f
== display_info
->mouse_face_mouse_frame
)
1323 /* Don't do highlighting for mouse motion during the update. */
1324 display_info
->mouse_face_defer
= 1;
1326 /* If F needs to be redrawn, simply forget about any prior mouse
1328 if (FRAME_GARBAGED_P (f
))
1329 display_info
->mouse_face_window
= Qnil
;
1331 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1332 their mouse_face_p flag set, which means that they are always
1333 unequal to rows in a desired matrix which never have that
1334 flag set. So, rows containing mouse-face glyphs are never
1335 scrolled, and we don't have to switch the mouse highlight off
1336 here to prevent it from being scrolled. */
1338 /* Can we tell that this update does not affect the window
1339 where the mouse highlight is? If so, no need to turn off.
1340 Likewise, don't do anything if the frame is garbaged;
1341 in that case, the frame's current matrix that we would use
1342 is all wrong, and we will redisplay that line anyway. */
1343 if (!NILP (display_info
->mouse_face_window
)
1344 && w
== XWINDOW (display_info
->mouse_face_window
))
1348 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1349 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1352 if (i
< w
->desired_matrix
->nrows
)
1353 clear_mouse_face (display_info
);
1362 /* Draw a vertical window border from (x,y0) to (x,y1) */
1365 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1369 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1372 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1374 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1377 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1380 /* End update of window W (which is equal to updated_window).
1382 Draw vertical borders between horizontally adjacent windows, and
1383 display W's cursor if CURSOR_ON_P is non-zero.
1385 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1386 glyphs in mouse-face were overwritten. In that case we have to
1387 make sure that the mouse-highlight is properly redrawn.
1389 W may be a menu bar pseudo-window in case we don't have X toolkit
1390 support. Such windows don't have a cursor, so don't display it
1394 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1396 int cursor_on_p
, mouse_face_overwritten_p
;
1398 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1400 if (!w
->pseudo_window_p
)
1405 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1407 output_cursor
.x
, output_cursor
.y
);
1409 if (draw_window_fringes (w
, 1))
1410 x_draw_vertical_border (w
);
1415 /* If a row with mouse-face was overwritten, arrange for
1416 XTframe_up_to_date to redisplay the mouse highlight. */
1417 if (mouse_face_overwritten_p
)
1419 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1420 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1421 dpyinfo
->mouse_face_window
= Qnil
;
1424 updated_window
= NULL
;
1428 /* End update of frame F. This function is installed as a hook in
1435 /* Mouse highlight may be displayed again. */
1436 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1439 #if TARGET_API_MAC_CARBON
1440 EnableScreenUpdates ();
1442 XFlush (FRAME_MAC_DISPLAY (f
));
1447 /* This function is called from various places in xdisp.c whenever a
1448 complete update has been performed. The global variable
1449 updated_window is not available here. */
1452 XTframe_up_to_date (f
)
1455 if (FRAME_MAC_P (f
))
1457 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1459 if (dpyinfo
->mouse_face_deferred_gc
1460 || f
== dpyinfo
->mouse_face_mouse_frame
)
1463 if (dpyinfo
->mouse_face_mouse_frame
)
1464 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1465 dpyinfo
->mouse_face_mouse_x
,
1466 dpyinfo
->mouse_face_mouse_y
);
1467 dpyinfo
->mouse_face_deferred_gc
= 0;
1474 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1475 arrow bitmaps, or clear the fringes if no bitmaps are required
1476 before DESIRED_ROW is made current. The window being updated is
1477 found in updated_window. This function is called from
1478 update_window_line only if it is known that there are differences
1479 between bitmaps to be drawn between current row and DESIRED_ROW. */
1482 x_after_update_window_line (desired_row
)
1483 struct glyph_row
*desired_row
;
1485 struct window
*w
= updated_window
;
1491 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1492 desired_row
->redraw_fringe_bitmaps_p
= 1;
1494 /* When a window has disappeared, make sure that no rest of
1495 full-width rows stays visible in the internal border. Could
1496 check here if updated_window is the leftmost/rightmost window,
1497 but I guess it's not worth doing since vertically split windows
1498 are almost never used, internal border is rarely set, and the
1499 overhead is very small. */
1500 if (windows_or_buffers_changed
1501 && desired_row
->full_width_p
1502 && (f
= XFRAME (w
->frame
),
1503 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1505 && (height
= desired_row
->visible_height
,
1508 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1510 /* Internal border is drawn below the tool bar. */
1511 if (WINDOWP (f
->tool_bar_window
)
1512 && w
== XWINDOW (f
->tool_bar_window
))
1516 mac_clear_area (f
, 0, y
, width
, height
);
1517 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1523 /* Draw the bitmap WHICH in one of the left or right fringes of
1524 window W. ROW is the glyph row for which to display the bitmap; it
1525 determines the vertical position at which the bitmap has to be
1529 x_draw_fringe_bitmap (w
, row
, p
)
1531 struct glyph_row
*row
;
1532 struct draw_fringe_bitmap_params
*p
;
1534 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1535 Display
*display
= FRAME_MAC_DISPLAY (f
);
1536 struct face
*face
= p
->face
;
1539 /* Must clip because of partially visible lines. */
1540 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1543 /* Adjust position of "bottom aligned" bitmap on partially
1544 visible last row. */
1546 int oldVH
= row
->visible_height
;
1547 row
->visible_height
= p
->h
;
1548 row
->y
-= rowY
- p
->y
;
1549 x_clip_to_row (w
, row
, -1, face
->gc
);
1551 row
->visible_height
= oldVH
;
1554 x_clip_to_row (w
, row
, -1, face
->gc
);
1556 if (p
->bx
>= 0 && !p
->overlay_p
)
1558 #if 0 /* MAC_TODO: stipple */
1559 /* In case the same realized face is used for fringes and
1560 for something displayed in the text (e.g. face `region' on
1561 mono-displays, the fill style may have been changed to
1562 FillSolid in x_draw_glyph_string_background. */
1564 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1566 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1569 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1571 #if 0 /* MAC_TODO: stipple */
1573 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1579 unsigned short *bits
= p
->bits
+ p
->dh
;
1582 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1583 XSetForeground (display
, face
->gc
,
1585 ? (p
->overlay_p
? face
->background
1586 : f
->output_data
.mac
->cursor_pixel
)
1587 : face
->foreground
));
1588 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1589 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1590 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1593 mac_reset_clip_rectangles (display
, face
->gc
);
1598 /* This is called when starting Emacs and when restarting after
1599 suspend. When starting Emacs, no window is mapped. And nothing
1600 must be done to Emacs's own window if it is suspended (though that
1604 XTset_terminal_modes ()
1608 /* This is called when exiting or suspending Emacs. Exiting will make
1609 the windows go away, and suspending requires no action. */
1612 XTreset_terminal_modes ()
1618 /***********************************************************************
1620 ***********************************************************************/
1622 /* Function prototypes of this page. */
1624 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1625 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1628 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1629 is not contained in the font. */
1631 static INLINE XCharStruct
*
1632 x_per_char_metric (font
, char2b
)
1636 /* The result metric information. */
1637 XCharStruct
*pcm
= NULL
;
1639 xassert (font
&& char2b
);
1642 if (font
->mac_style
)
1644 if (char2b
->byte1
>= font
->min_byte1
1645 && char2b
->byte1
<= font
->max_byte1
1646 && char2b
->byte2
>= font
->min_char_or_byte2
1647 && char2b
->byte2
<= font
->max_char_or_byte2
)
1649 pcm
= (font
->per_char
1650 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1651 * (char2b
->byte1
- font
->min_byte1
))
1652 + (char2b
->byte2
- font
->min_char_or_byte2
));
1655 if (pcm
&& !pcm
->valid_p
)
1658 ATSUTextLayout text_layout
;
1661 ATSTrapezoid glyph_bounds
;
1664 c
= (char2b
->byte1
<< 8) + char2b
->byte2
;
1666 err
= atsu_get_text_layout_with_text_ptr (&c
, 1,
1670 err
= ATSUMeasureTextImage (text_layout
,
1671 kATSUFromTextBeginning
, kATSUToTextEnd
,
1672 0, 0, &char_bounds
);
1675 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
1676 kATSUFromTextBeginning
, kATSUToTextEnd
,
1677 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1678 kATSUseFractionalOrigins
,
1680 kATSUseDeviceOrigins
,
1682 1, &glyph_bounds
, NULL
);
1688 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
1689 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
1691 char_width
= Fix2Long (glyph_bounds
.upperRight
.x
1692 - glyph_bounds
.upperLeft
.x
);
1693 STORE_XCHARSTRUCT (*pcm
, char_width
, char_bounds
);
1700 if (font
->per_char
!= NULL
)
1702 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1704 /* min_char_or_byte2 specifies the linear character index
1705 corresponding to the first element of the per_char array,
1706 max_char_or_byte2 is the index of the last character. A
1707 character with non-zero CHAR2B->byte1 is not in the font.
1708 A character with byte2 less than min_char_or_byte2 or
1709 greater max_char_or_byte2 is not in the font. */
1710 if (char2b
->byte1
== 0
1711 && char2b
->byte2
>= font
->min_char_or_byte2
1712 && char2b
->byte2
<= font
->max_char_or_byte2
)
1713 pcm
= font
->per_char
+ char2b
->byte2
- font
->min_char_or_byte2
;
1717 /* If either min_byte1 or max_byte1 are nonzero, both
1718 min_char_or_byte2 and max_char_or_byte2 are less than
1719 256, and the 2-byte character index values corresponding
1720 to the per_char array element N (counting from 0) are:
1722 byte1 = N/D + min_byte1
1723 byte2 = N\D + min_char_or_byte2
1727 D = max_char_or_byte2 - min_char_or_byte2 + 1
1728 / = integer division
1729 \ = integer modulus */
1730 if (char2b
->byte1
>= font
->min_byte1
1731 && char2b
->byte1
<= font
->max_byte1
1732 && char2b
->byte2
>= font
->min_char_or_byte2
1733 && char2b
->byte2
<= font
->max_char_or_byte2
)
1735 pcm
= (font
->per_char
1736 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1737 * (char2b
->byte1
- font
->min_byte1
))
1738 + (char2b
->byte2
- font
->min_char_or_byte2
));
1744 /* If the per_char pointer is null, all glyphs between the first
1745 and last character indexes inclusive have the same
1746 information, as given by both min_bounds and max_bounds. */
1747 if (char2b
->byte2
>= font
->min_char_or_byte2
1748 && char2b
->byte2
<= font
->max_char_or_byte2
)
1749 pcm
= &font
->max_bounds
;
1755 return ((pcm
== NULL
1756 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1763 static XCharStruct
*
1764 mac_per_char_metric (font
, char2b
, font_type
)
1769 return x_per_char_metric (font
, char2b
);
1773 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1774 the two-byte form of C. Encoding is returned in *CHAR2B. */
1777 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1780 struct font_info
*font_info
;
1783 int charset
= CHAR_CHARSET (c
);
1784 XFontStruct
*font
= font_info
->font
;
1786 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1787 This may be either a program in a special encoder language or a
1789 if (font_info
->font_encoder
)
1791 /* It's a program. */
1792 struct ccl_program
*ccl
= font_info
->font_encoder
;
1794 check_ccl_update (ccl
);
1795 if (CHARSET_DIMENSION (charset
) == 1)
1797 ccl
->reg
[0] = charset
;
1798 ccl
->reg
[1] = char2b
->byte2
;
1803 ccl
->reg
[0] = charset
;
1804 ccl
->reg
[1] = char2b
->byte1
;
1805 ccl
->reg
[2] = char2b
->byte2
;
1808 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
1810 /* We assume that MSBs are appropriately set/reset by CCL
1812 if (font
->max_byte1
== 0) /* 1-byte font */
1813 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
1815 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
1817 else if (font_info
->encoding
[charset
])
1819 /* Fixed encoding scheme. See fontset.h for the meaning of the
1820 encoding numbers. */
1821 int enc
= font_info
->encoding
[charset
];
1823 if ((enc
== 1 || enc
== 2)
1824 && CHARSET_DIMENSION (charset
) == 2)
1825 char2b
->byte1
|= 0x80;
1827 if (enc
== 1 || enc
== 3)
1828 char2b
->byte2
|= 0x80;
1834 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
1835 char2b
->byte1
= sjis1
;
1836 char2b
->byte2
= sjis2
;
1841 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
1843 return FONT_TYPE_UNKNOWN
;
1848 /***********************************************************************
1850 ***********************************************************************/
1854 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
1855 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
1856 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
1858 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
1859 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
1860 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
1861 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
1862 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
1863 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
1864 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
1865 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
1866 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1867 unsigned long *, double, int));*/
1868 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
1869 double, int, unsigned long));
1870 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
1871 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
1872 static void x_draw_image_relief
P_ ((struct glyph_string
*));
1873 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
1874 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
1875 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
1877 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
1878 int, int, int, int, int, int,
1880 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
1881 int, int, int, Rect
*));
1884 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
1888 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1893 struct glyph_string
*s
;
1895 if (s
->font
== FRAME_FONT (s
->f
)
1896 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
1897 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
1899 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
1902 /* Cursor on non-default face: must merge. */
1906 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
1907 xgcv
.foreground
= s
->face
->background
;
1909 /* If the glyph would be invisible, try a different foreground. */
1910 if (xgcv
.foreground
== xgcv
.background
)
1911 xgcv
.foreground
= s
->face
->foreground
;
1912 if (xgcv
.foreground
== xgcv
.background
)
1913 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
1914 if (xgcv
.foreground
== xgcv
.background
)
1915 xgcv
.foreground
= s
->face
->foreground
;
1917 /* Make sure the cursor is distinct from text in this face. */
1918 if (xgcv
.background
== s
->face
->background
1919 && xgcv
.foreground
== s
->face
->foreground
)
1921 xgcv
.background
= s
->face
->foreground
;
1922 xgcv
.foreground
= s
->face
->background
;
1925 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1926 xgcv
.font
= s
->font
;
1927 mask
= GCForeground
| GCBackground
| GCFont
;
1929 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1930 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1933 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1934 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1936 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1941 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1944 x_set_mouse_face_gc (s
)
1945 struct glyph_string
*s
;
1950 /* What face has to be used last for the mouse face? */
1951 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
1952 face
= FACE_FROM_ID (s
->f
, face_id
);
1954 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
1956 if (s
->first_glyph
->type
== CHAR_GLYPH
)
1957 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
1959 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
1960 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
1961 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
1963 /* If font in this face is same as S->font, use it. */
1964 if (s
->font
== s
->face
->font
)
1965 s
->gc
= s
->face
->gc
;
1968 /* Otherwise construct scratch_cursor_gc with values from FACE
1973 xgcv
.background
= s
->face
->background
;
1974 xgcv
.foreground
= s
->face
->foreground
;
1975 IF_DEBUG (x_check_font (s
->f
, s
->font
));
1976 xgcv
.font
= s
->font
;
1977 mask
= GCForeground
| GCBackground
| GCFont
;
1979 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
1980 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
1983 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
1984 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
1986 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
1989 xassert (s
->gc
!= 0);
1993 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1994 Faces to use in the mode line have already been computed when the
1995 matrix was built, so there isn't much to do, here. */
1998 x_set_mode_line_face_gc (s
)
1999 struct glyph_string
*s
;
2001 s
->gc
= s
->face
->gc
;
2005 /* Set S->gc of glyph string S for drawing that glyph string. Set
2006 S->stippled_p to a non-zero value if the face of S has a stipple
2010 x_set_glyph_string_gc (s
)
2011 struct glyph_string
*s
;
2013 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2015 if (s
->hl
== DRAW_NORMAL_TEXT
)
2017 s
->gc
= s
->face
->gc
;
2018 s
->stippled_p
= s
->face
->stipple
!= 0;
2020 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2022 x_set_mode_line_face_gc (s
);
2023 s
->stippled_p
= s
->face
->stipple
!= 0;
2025 else if (s
->hl
== DRAW_CURSOR
)
2027 x_set_cursor_gc (s
);
2030 else if (s
->hl
== DRAW_MOUSE_FACE
)
2032 x_set_mouse_face_gc (s
);
2033 s
->stippled_p
= s
->face
->stipple
!= 0;
2035 else if (s
->hl
== DRAW_IMAGE_RAISED
2036 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2038 s
->gc
= s
->face
->gc
;
2039 s
->stippled_p
= s
->face
->stipple
!= 0;
2043 s
->gc
= s
->face
->gc
;
2044 s
->stippled_p
= s
->face
->stipple
!= 0;
2047 /* GC must have been set. */
2048 xassert (s
->gc
!= 0);
2052 /* Set clipping for output of glyph string S. S may be part of a mode
2053 line or menu if we don't have X toolkit support. */
2056 x_set_glyph_string_clipping (s
)
2057 struct glyph_string
*s
;
2059 Rect rects
[MAX_CLIP_RECTS
];
2062 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2063 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2068 Compute left and right overhang of glyph string S. If S is a glyph
2069 string for a composition, assume overhangs don't exist. */
2072 mac_compute_glyph_string_overhangs (s
)
2073 struct glyph_string
*s
;
2076 && s
->first_glyph
->type
== CHAR_GLYPH
)
2079 MacFontStruct
*font
= s
->font
;
2082 if (font
->mac_style
)
2085 ATSUTextLayout text_layout
;
2089 SetRect (&r
, 0, 0, 0, 0);
2090 buf
= xmalloc (sizeof (UniChar
) * s
->nchars
);
2093 for (i
= 0; i
< s
->nchars
; i
++)
2094 buf
[i
] = (s
->char2b
[i
].byte1
<< 8) + s
->char2b
[i
].byte2
;
2096 err
= atsu_get_text_layout_with_text_ptr (buf
, s
->nchars
,
2100 err
= ATSUMeasureTextImage (text_layout
,
2101 kATSUFromTextBeginning
,
2110 TextFont (font
->mac_fontnum
);
2111 TextSize (font
->mac_fontsize
);
2112 TextFace (font
->mac_fontface
);
2115 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2119 char *buf
= xmalloc (s
->nchars
);
2122 SetRect (&r
, 0, 0, 0, 0);
2125 for (i
= 0; i
< s
->nchars
; ++i
)
2126 buf
[i
] = s
->char2b
[i
].byte2
;
2127 QDTextBounds (s
->nchars
, buf
, &r
);
2135 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2136 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2141 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2144 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2145 struct glyph_string
*s
;
2148 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2152 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2153 on Mac OS X because:
2154 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2155 into an offscreen graphics world first. So performance gain
2156 cannot be expected.)
2157 - It lowers rendering quality.
2158 - Some fonts leave garbage on cursor movement. */
2160 /* Draw the background of glyph_string S. If S->background_filled_p
2161 is non-zero don't draw it. FORCE_P non-zero means draw the
2162 background even if it wouldn't be drawn normally. This is used
2163 when a string preceding S draws into the background of S, or S
2164 contains the first component of a composition. */
2167 x_draw_glyph_string_background (s
, force_p
)
2168 struct glyph_string
*s
;
2171 /* Nothing to do if background has already been drawn or if it
2172 shouldn't be drawn in the first place. */
2173 if (!s
->background_filled_p
)
2175 int box_line_width
= max (s
->face
->box_line_width
, 0);
2177 #if 0 /* MAC_TODO: stipple */
2180 /* Fill background with a stipple pattern. */
2181 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2182 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2183 s
->y
+ box_line_width
,
2184 s
->background_width
,
2185 s
->height
- 2 * box_line_width
);
2186 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2187 s
->background_filled_p
= 1;
2191 #if defined (MAC_OS8) && !USE_ATSUI
2192 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2193 || s
->font_not_found_p
2194 || s
->extends_to_end_of_line_p
2198 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2199 s
->background_width
,
2200 s
->height
- 2 * box_line_width
);
2201 s
->background_filled_p
= 1;
2207 /* Draw the foreground of glyph string S. */
2210 x_draw_glyph_string_foreground (s
)
2211 struct glyph_string
*s
;
2215 /* If first glyph of S has a left box line, start drawing the text
2216 of S to the right of that box line. */
2217 if (s
->face
->box
!= FACE_NO_BOX
2218 && s
->first_glyph
->left_box_line_p
)
2219 x
= s
->x
+ abs (s
->face
->box_line_width
);
2223 /* Draw characters of S as rectangles if S's font could not be
2225 if (s
->font_not_found_p
)
2227 for (i
= 0; i
< s
->nchars
; ++i
)
2229 struct glyph
*g
= s
->first_glyph
+ i
;
2230 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2231 g
->pixel_width
- 1, s
->height
- 1);
2232 x
+= g
->pixel_width
;
2237 char *char1b
= (char *) s
->char2b
;
2238 int boff
= s
->font_info
->baseline_offset
;
2240 if (s
->font_info
->vertical_centering
)
2241 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2243 /* If we can use 8-bit functions, condense S->char2b. */
2246 && GC_FONT (s
->gc
)->mac_style
== NULL
2249 for (i
= 0; i
< s
->nchars
; ++i
)
2250 char1b
[i
] = s
->char2b
[i
].byte2
;
2252 #if defined (MAC_OS8) && !USE_ATSUI
2253 /* Draw text with XDrawString if background has already been
2254 filled. Otherwise, use XDrawImageString. (Note that
2255 XDrawImageString is usually faster than XDrawString.) Always
2256 use XDrawImageString when drawing the cursor so that there is
2257 no chance that characters under a box cursor are invisible. */
2259 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2262 /* Draw characters with 16-bit or 8-bit functions. */
2265 || GC_FONT (s
->gc
)->mac_style
2268 mac_draw_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2269 s
->char2b
, s
->nchars
);
2271 mac_draw_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2274 #if defined (MAC_OS8) && !USE_ATSUI
2278 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2279 s
->char2b
, s
->nchars
);
2281 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2288 /* Draw the foreground of composite glyph string S. */
2291 x_draw_composite_glyph_string_foreground (s
)
2292 struct glyph_string
*s
;
2296 /* If first glyph of S has a left box line, start drawing the text
2297 of S to the right of that box line. */
2298 if (s
->face
->box
!= FACE_NO_BOX
2299 && s
->first_glyph
->left_box_line_p
)
2300 x
= s
->x
+ abs (s
->face
->box_line_width
);
2304 /* S is a glyph string for a composition. S->gidx is the index of
2305 the first character drawn for glyphs of this composition.
2306 S->gidx == 0 means we are drawing the very first character of
2307 this composition. */
2309 /* Draw a rectangle for the composition if the font for the very
2310 first character of the composition could not be loaded. */
2311 if (s
->font_not_found_p
)
2314 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2315 s
->width
- 1, s
->height
- 1);
2319 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2320 mac_draw_string_16 (s
->f
, s
->gc
,
2321 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2322 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2328 #ifdef USE_X_TOOLKIT
2330 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2333 /* Return the frame on which widget WIDGET is used.. Abort if frame
2334 cannot be determined. */
2336 static struct frame
*
2337 x_frame_of_widget (widget
)
2340 struct x_display_info
*dpyinfo
;
2344 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2346 /* Find the top-level shell of the widget. Note that this function
2347 can be called when the widget is not yet realized, so XtWindow
2348 (widget) == 0. That's the reason we can't simply use
2349 x_any_window_to_frame. */
2350 while (!XtIsTopLevelShell (widget
))
2351 widget
= XtParent (widget
);
2353 /* Look for a frame with that top-level widget. Allocate the color
2354 on that frame to get the right gamma correction value. */
2355 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2356 if (GC_FRAMEP (XCAR (tail
))
2357 && (f
= XFRAME (XCAR (tail
)),
2358 (f
->output_data
.nothing
!= 1
2359 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2360 && f
->output_data
.x
->widget
== widget
)
2367 /* Allocate the color COLOR->pixel on the screen and display of
2368 widget WIDGET in colormap CMAP. If an exact match cannot be
2369 allocated, try the nearest color available. Value is non-zero
2370 if successful. This is called from lwlib. */
2373 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2378 struct frame
*f
= x_frame_of_widget (widget
);
2379 return x_alloc_nearest_color (f
, cmap
, color
);
2383 #endif /* USE_X_TOOLKIT */
2385 #if 0 /* MAC_TODO */
2387 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2388 CMAP. If an exact match can't be allocated, try the nearest color
2389 available. Value is non-zero if successful. Set *COLOR to the
2393 x_alloc_nearest_color (f
, cmap
, color
)
2398 Display
*display
= FRAME_X_DISPLAY (f
);
2399 Screen
*screen
= FRAME_X_SCREEN (f
);
2402 gamma_correct (f
, color
);
2403 rc
= XAllocColor (display
, cmap
, color
);
2406 /* If we got to this point, the colormap is full, so we're going
2407 to try to get the next closest color. The algorithm used is
2408 a least-squares matching, which is what X uses for closest
2409 color matching with StaticColor visuals. */
2411 unsigned long nearest_delta
= ~0;
2412 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2413 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2415 for (i
= 0; i
< ncells
; ++i
)
2417 XQueryColors (display
, cmap
, cells
, ncells
);
2419 for (nearest
= i
= 0; i
< ncells
; ++i
)
2421 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2422 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2423 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2424 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2426 if (delta
< nearest_delta
)
2429 nearest_delta
= delta
;
2433 color
->red
= cells
[nearest
].red
;
2434 color
->green
= cells
[nearest
].green
;
2435 color
->blue
= cells
[nearest
].blue
;
2436 rc
= XAllocColor (display
, cmap
, color
);
2439 #ifdef DEBUG_X_COLORS
2441 register_color (color
->pixel
);
2442 #endif /* DEBUG_X_COLORS */
2448 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2449 It's necessary to do this instead of just using PIXEL directly to
2450 get color reference counts right. */
2453 x_copy_color (f
, pixel
)
2455 unsigned long pixel
;
2459 color
.pixel
= pixel
;
2461 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2462 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2464 #ifdef DEBUG_X_COLORS
2465 register_color (pixel
);
2471 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2472 It's necessary to do this instead of just using PIXEL directly to
2473 get color reference counts right. */
2476 x_copy_dpy_color (dpy
, cmap
, pixel
)
2479 unsigned long pixel
;
2483 color
.pixel
= pixel
;
2485 XQueryColor (dpy
, cmap
, &color
);
2486 XAllocColor (dpy
, cmap
, &color
);
2488 #ifdef DEBUG_X_COLORS
2489 register_color (pixel
);
2494 #endif /* MAC_TODO */
2497 /* Brightness beyond which a color won't have its highlight brightness
2500 Nominally, highlight colors for `3d' faces are calculated by
2501 brightening an object's color by a constant scale factor, but this
2502 doesn't yield good results for dark colors, so for colors who's
2503 brightness is less than this value (on a scale of 0-255) have to
2504 use an additional additive factor.
2506 The value here is set so that the default menu-bar/mode-line color
2507 (grey75) will not have its highlights changed at all. */
2508 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2511 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2512 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2513 If this produces the same color as COLOR, try a color where all RGB
2514 values have DELTA added. Return the allocated color in *COLOR.
2515 DISPLAY is the X display, CMAP is the colormap to operate on.
2516 Value is non-zero if successful. */
2519 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2521 unsigned long *color
;
2528 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2531 /* Change RGB values by specified FACTOR. Avoid overflow! */
2532 xassert (factor
>= 0);
2533 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2534 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2535 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2537 /* Calculate brightness of COLOR. */
2538 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2539 + BLUE_FROM_ULONG (*color
)) / 6;
2541 /* We only boost colors that are darker than
2542 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2543 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2544 /* Make an additive adjustment to NEW, because it's dark enough so
2545 that scaling by FACTOR alone isn't enough. */
2547 /* How far below the limit this color is (0 - 1, 1 being darker). */
2548 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2549 /* The additive adjustment. */
2550 int min_delta
= delta
* dimness
* factor
/ 2;
2553 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2554 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2555 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2557 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2558 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2559 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2563 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2564 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2565 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2567 /* MAC_TODO: Map to palette and retry with delta if same? */
2568 /* MAC_TODO: Free colors (if using palette)? */
2579 /* Set up the foreground color for drawing relief lines of glyph
2580 string S. RELIEF is a pointer to a struct relief containing the GC
2581 with which lines will be drawn. Use a color that is FACTOR or
2582 DELTA lighter or darker than the relief's background which is found
2583 in S->f->output_data.x->relief_background. If such a color cannot
2584 be allocated, use DEFAULT_PIXEL, instead. */
2587 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2589 struct relief
*relief
;
2592 unsigned long default_pixel
;
2595 struct mac_output
*di
= f
->output_data
.mac
;
2596 unsigned long mask
= GCForeground
;
2597 unsigned long pixel
;
2598 unsigned long background
= di
->relief_background
;
2599 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2601 /* MAC_TODO: Free colors (if using palette)? */
2603 /* Allocate new color. */
2604 xgcv
.foreground
= default_pixel
;
2606 if (dpyinfo
->n_planes
!= 1
2607 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2609 relief
->allocated_p
= 1;
2610 xgcv
.foreground
= relief
->pixel
= pixel
;
2613 if (relief
->gc
== 0)
2615 #if 0 /* MAC_TODO: stipple */
2616 xgcv
.stipple
= dpyinfo
->gray
;
2619 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2622 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2626 /* Set up colors for the relief lines around glyph string S. */
2629 x_setup_relief_colors (s
)
2630 struct glyph_string
*s
;
2632 struct mac_output
*di
= s
->f
->output_data
.mac
;
2633 unsigned long color
;
2635 if (s
->face
->use_box_color_for_shadows_p
)
2636 color
= s
->face
->box_color
;
2637 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2639 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2640 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2645 /* Get the background color of the face. */
2646 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2647 color
= xgcv
.background
;
2650 if (di
->white_relief
.gc
== 0
2651 || color
!= di
->relief_background
)
2653 di
->relief_background
= color
;
2654 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2655 WHITE_PIX_DEFAULT (s
->f
));
2656 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2657 BLACK_PIX_DEFAULT (s
->f
));
2662 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2663 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2664 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2665 relief. LEFT_P non-zero means draw a relief on the left side of
2666 the rectangle. RIGHT_P non-zero means draw a relief on the right
2667 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2671 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2672 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2674 int left_x
, top_y
, right_x
, bottom_y
, width
;
2675 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2678 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2683 gc
= f
->output_data
.mac
->white_relief
.gc
;
2685 gc
= f
->output_data
.mac
->black_relief
.gc
;
2686 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2690 for (i
= 0; i
< width
; ++i
)
2691 mac_draw_line (f
, gc
,
2692 left_x
+ i
* left_p
, top_y
+ i
,
2693 right_x
- i
* right_p
, top_y
+ i
);
2697 for (i
= 0; i
< width
; ++i
)
2698 mac_draw_line (f
, gc
,
2699 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2701 mac_reset_clip_rectangles (dpy
, gc
);
2703 gc
= f
->output_data
.mac
->black_relief
.gc
;
2705 gc
= f
->output_data
.mac
->white_relief
.gc
;
2706 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2710 for (i
= 0; i
< width
; ++i
)
2711 mac_draw_line (f
, gc
,
2712 left_x
+ i
* left_p
, bottom_y
- i
,
2713 right_x
- i
* right_p
, bottom_y
- i
);
2717 for (i
= 0; i
< width
; ++i
)
2718 mac_draw_line (f
, gc
,
2719 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2721 mac_reset_clip_rectangles (dpy
, gc
);
2725 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2726 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2727 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2728 left side of the rectangle. RIGHT_P non-zero means draw a line
2729 on the right side of the rectangle. CLIP_RECT is the clipping
2730 rectangle to use when drawing. */
2733 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2734 left_p
, right_p
, clip_rect
)
2735 struct glyph_string
*s
;
2736 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2741 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2742 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2743 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2746 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2747 right_x
- left_x
+ 1, width
);
2751 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2752 width
, bottom_y
- top_y
+ 1);
2755 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2756 right_x
- left_x
+ 1, width
);
2760 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2761 top_y
, width
, bottom_y
- top_y
+ 1);
2763 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2764 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2768 /* Draw a box around glyph string S. */
2771 x_draw_glyph_string_box (s
)
2772 struct glyph_string
*s
;
2774 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2775 int left_p
, right_p
;
2776 struct glyph
*last_glyph
;
2779 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2780 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2781 : window_box_right (s
->w
, s
->area
));
2783 /* The glyph that may have a right box line. */
2784 last_glyph
= (s
->cmp
|| s
->img
2786 : s
->first_glyph
+ s
->nchars
- 1);
2788 width
= abs (s
->face
->box_line_width
);
2789 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2791 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2793 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2795 bottom_y
= top_y
+ s
->height
- 1;
2797 left_p
= (s
->first_glyph
->left_box_line_p
2798 || (s
->hl
== DRAW_MOUSE_FACE
2800 || s
->prev
->hl
!= s
->hl
)));
2801 right_p
= (last_glyph
->right_box_line_p
2802 || (s
->hl
== DRAW_MOUSE_FACE
2804 || s
->next
->hl
!= s
->hl
)));
2806 get_glyph_string_clip_rect (s
, &clip_rect
);
2808 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2809 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2810 left_p
, right_p
, &clip_rect
);
2813 x_setup_relief_colors (s
);
2814 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2815 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2820 /* Draw foreground of image glyph string S. */
2823 x_draw_image_foreground (s
)
2824 struct glyph_string
*s
;
2827 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2829 /* If first glyph of S has a left box line, start drawing it to the
2830 right of that line. */
2831 if (s
->face
->box
!= FACE_NO_BOX
2832 && s
->first_glyph
->left_box_line_p
2834 x
+= abs (s
->face
->box_line_width
);
2836 /* If there is a margin around the image, adjust x- and y-position
2838 if (s
->slice
.x
== 0)
2839 x
+= s
->img
->hmargin
;
2840 if (s
->slice
.y
== 0)
2841 y
+= s
->img
->vmargin
;
2845 x_set_glyph_string_clipping (s
);
2848 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
2849 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2850 s
->slice
.width
, s
->slice
.height
, x
, y
);
2853 mac_copy_area (s
->img
->pixmap
,
2854 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
2855 s
->slice
.width
, s
->slice
.height
, x
, y
);
2857 /* When the image has a mask, we can expect that at
2858 least part of a mouse highlight or a block cursor will
2859 be visible. If the image doesn't have a mask, make
2860 a block cursor visible by drawing a rectangle around
2861 the image. I believe it's looking better if we do
2862 nothing here for mouse-face. */
2863 if (s
->hl
== DRAW_CURSOR
)
2865 int r
= s
->img
->relief
;
2867 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
2868 s
->slice
.width
+ r
*2 - 1,
2869 s
->slice
.height
+ r
*2 - 1);
2874 /* Draw a rectangle if image could not be loaded. */
2875 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
2876 s
->slice
.width
- 1, s
->slice
.height
- 1);
2880 /* Draw a relief around the image glyph string S. */
2883 x_draw_image_relief (s
)
2884 struct glyph_string
*s
;
2886 int x0
, y0
, x1
, y1
, thick
, raised_p
;
2889 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
2891 /* If first glyph of S has a left box line, start drawing it to the
2892 right of that line. */
2893 if (s
->face
->box
!= FACE_NO_BOX
2894 && s
->first_glyph
->left_box_line_p
2896 x
+= abs (s
->face
->box_line_width
);
2898 /* If there is a margin around the image, adjust x- and y-position
2900 if (s
->slice
.x
== 0)
2901 x
+= s
->img
->hmargin
;
2902 if (s
->slice
.y
== 0)
2903 y
+= s
->img
->vmargin
;
2905 if (s
->hl
== DRAW_IMAGE_SUNKEN
2906 || s
->hl
== DRAW_IMAGE_RAISED
)
2908 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2909 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
2913 thick
= abs (s
->img
->relief
);
2914 raised_p
= s
->img
->relief
> 0;
2919 x1
= x
+ s
->slice
.width
+ thick
- 1;
2920 y1
= y
+ s
->slice
.height
+ thick
- 1;
2922 x_setup_relief_colors (s
);
2923 get_glyph_string_clip_rect (s
, &r
);
2924 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
2926 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
2928 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
2933 /* Draw part of the background of glyph string S. X, Y, W, and H
2934 give the rectangle to draw. */
2937 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
2938 struct glyph_string
*s
;
2941 #if 0 /* MAC_TODO: stipple */
2944 /* Fill background with a stipple pattern. */
2945 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2946 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
2947 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2950 #endif /* MAC_TODO */
2951 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
2955 /* Draw image glyph string S.
2958 s->x +-------------------------
2961 | +-------------------------
2964 | | +-------------------
2970 x_draw_image_glyph_string (s
)
2971 struct glyph_string
*s
;
2974 int box_line_hwidth
= abs (s
->face
->box_line_width
);
2975 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2979 height
= s
->height
- 2 * box_line_vwidth
;
2982 /* Fill background with face under the image. Do it only if row is
2983 taller than image or if image has a clip mask to reduce
2985 s
->stippled_p
= s
->face
->stipple
!= 0;
2986 if (height
> s
->slice
.height
2990 || s
->img
->pixmap
== 0
2991 || s
->width
!= s
->background_width
)
2994 if (s
->first_glyph
->left_box_line_p
2996 x
+= box_line_hwidth
;
2999 if (s
->slice
.y
== 0)
3000 y
+= box_line_vwidth
;
3002 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3004 s
->background_filled_p
= 1;
3007 /* Draw the foreground. */
3008 x_draw_image_foreground (s
);
3010 /* If we must draw a relief around the image, do it. */
3012 || s
->hl
== DRAW_IMAGE_RAISED
3013 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3014 x_draw_image_relief (s
);
3018 /* Draw stretch glyph string S. */
3021 x_draw_stretch_glyph_string (s
)
3022 struct glyph_string
*s
;
3024 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3025 s
->stippled_p
= s
->face
->stipple
!= 0;
3027 if (s
->hl
== DRAW_CURSOR
3028 && !x_stretch_cursor_p
)
3030 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3031 as wide as the stretch glyph. */
3032 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3035 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3037 /* Clear rest using the GC of the original non-cursor face. */
3038 if (width
< s
->background_width
)
3040 int x
= s
->x
+ width
, y
= s
->y
;
3041 int w
= s
->background_width
- width
, h
= s
->height
;
3045 if (s
->row
->mouse_face_p
3046 && cursor_in_mouse_face_p (s
->w
))
3048 x_set_mouse_face_gc (s
);
3054 get_glyph_string_clip_rect (s
, &r
);
3055 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3057 #if 0 /* MAC_TODO: stipple */
3058 if (s
->face
->stipple
)
3060 /* Fill background with a stipple pattern. */
3061 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3062 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3063 XSetFillStyle (s
->display
, gc
, FillSolid
);
3066 #endif /* MAC_TODO */
3067 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3070 else if (!s
->background_filled_p
)
3071 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3074 s
->background_filled_p
= 1;
3078 /* Draw glyph string S. */
3081 x_draw_glyph_string (s
)
3082 struct glyph_string
*s
;
3084 int relief_drawn_p
= 0;
3086 /* If S draws into the background of its successor that does not
3087 draw a cursor, draw the background of the successor first so that
3088 S can draw into it. This makes S->next use XDrawString instead
3089 of XDrawImageString. */
3090 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3091 && s
->next
->hl
!= DRAW_CURSOR
)
3093 xassert (s
->next
->img
== NULL
);
3094 x_set_glyph_string_gc (s
->next
);
3095 x_set_glyph_string_clipping (s
->next
);
3096 x_draw_glyph_string_background (s
->next
, 1);
3099 /* Set up S->gc, set clipping and draw S. */
3100 x_set_glyph_string_gc (s
);
3102 /* Draw relief (if any) in advance for char/composition so that the
3103 glyph string can be drawn over it. */
3104 if (!s
->for_overlaps
3105 && s
->face
->box
!= FACE_NO_BOX
3106 && (s
->first_glyph
->type
== CHAR_GLYPH
3107 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3110 x_set_glyph_string_clipping (s
);
3111 x_draw_glyph_string_background (s
, 1);
3112 x_draw_glyph_string_box (s
);
3113 x_set_glyph_string_clipping (s
);
3117 x_set_glyph_string_clipping (s
);
3119 switch (s
->first_glyph
->type
)
3122 x_draw_image_glyph_string (s
);
3126 x_draw_stretch_glyph_string (s
);
3130 if (s
->for_overlaps
)
3131 s
->background_filled_p
= 1;
3133 x_draw_glyph_string_background (s
, 0);
3134 x_draw_glyph_string_foreground (s
);
3137 case COMPOSITE_GLYPH
:
3138 if (s
->for_overlaps
|| s
->gidx
> 0)
3139 s
->background_filled_p
= 1;
3141 x_draw_glyph_string_background (s
, 1);
3142 x_draw_composite_glyph_string_foreground (s
);
3149 if (!s
->for_overlaps
)
3151 /* Draw underline. */
3152 if (s
->face
->underline_p
)
3154 unsigned long h
= 1;
3155 unsigned long dy
= s
->height
- h
;
3157 if (s
->face
->underline_defaulted_p
)
3158 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3163 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3164 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3165 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3167 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3171 /* Draw overline. */
3172 if (s
->face
->overline_p
)
3174 unsigned long dy
= 0, h
= 1;
3176 if (s
->face
->overline_color_defaulted_p
)
3177 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3182 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3183 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3184 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3186 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3190 /* Draw strike-through. */
3191 if (s
->face
->strike_through_p
)
3193 unsigned long h
= 1;
3194 unsigned long dy
= (s
->height
- h
) / 2;
3196 if (s
->face
->strike_through_color_defaulted_p
)
3197 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3202 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3203 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3204 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3206 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3210 /* Draw relief if not yet drawn. */
3211 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3212 x_draw_glyph_string_box (s
);
3215 /* Reset clipping. */
3216 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3219 /* Shift display to make room for inserted glyphs. */
3222 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3224 int x
, y
, width
, height
, shift_by
;
3226 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3227 x
, y
, width
, height
,
3231 /* Delete N glyphs at the nominal cursor position. Not implemented
3242 /* Clear entire frame. If updating_frame is non-null, clear that
3243 frame. Otherwise clear the selected frame. */
3253 f
= SELECTED_FRAME ();
3255 /* Clearing the frame will erase any cursor, so mark them all as no
3257 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3258 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3259 output_cursor
.x
= -1;
3261 /* We don't set the output cursor here because there will always
3262 follow an explicit cursor_to. */
3264 mac_clear_window (f
);
3266 /* We have to clear the scroll bars, too. If we have changed
3267 colors or something like that, then they should be notified. */
3268 x_scroll_bar_clear (f
);
3270 XFlush (FRAME_MAC_DISPLAY (f
));
3276 /* Invert the middle quarter of the frame for .15 sec. */
3278 /* We use the select system call to do the waiting, so we have to make
3279 sure it's available. If it isn't, we just won't do visual bells. */
3281 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3284 /* Subtract the `struct timeval' values X and Y, storing the result in
3285 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3288 timeval_subtract (result
, x
, y
)
3289 struct timeval
*result
, x
, y
;
3291 /* Perform the carry for the later subtraction by updating y. This
3292 is safer because on some systems the tv_sec member is unsigned. */
3293 if (x
.tv_usec
< y
.tv_usec
)
3295 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3296 y
.tv_usec
-= 1000000 * nsec
;
3300 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3302 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3303 y
.tv_usec
+= 1000000 * nsec
;
3307 /* Compute the time remaining to wait. tv_usec is certainly
3309 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3310 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3312 /* Return indication of whether the result should be considered
3314 return x
.tv_sec
< y
.tv_sec
;
3321 /* Get the height not including a menu bar widget. */
3322 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3323 /* Height of each line to flash. */
3324 int flash_height
= FRAME_LINE_HEIGHT (f
);
3325 /* These will be the left and right margins of the rectangles. */
3326 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3327 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3331 /* Don't flash the area between a scroll bar and the frame
3332 edge it is next to. */
3333 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3335 case vertical_scroll_bar_left
:
3336 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3339 case vertical_scroll_bar_right
:
3340 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3347 width
= flash_right
- flash_left
;
3351 /* If window is tall, flash top and bottom line. */
3352 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3354 mac_invert_rectangle (f
, flash_left
,
3355 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3356 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3357 width
, flash_height
);
3358 mac_invert_rectangle (f
, flash_left
,
3359 (height
- flash_height
3360 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3361 width
, flash_height
);
3364 /* If it is short, flash it all. */
3365 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3366 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3371 struct timeval wakeup
;
3373 EMACS_GET_TIME (wakeup
);
3375 /* Compute time to wait until, propagating carry from usecs. */
3376 wakeup
.tv_usec
+= 150000;
3377 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3378 wakeup
.tv_usec
%= 1000000;
3380 /* Keep waiting until past the time wakeup or any input gets
3382 while (! detect_input_pending ())
3384 struct timeval current
;
3385 struct timeval timeout
;
3387 EMACS_GET_TIME (current
);
3389 /* Break if result would be negative. */
3390 if (timeval_subtract (¤t
, wakeup
, current
))
3393 /* How long `select' should wait. */
3395 timeout
.tv_usec
= 10000;
3397 /* Try to wait that long--but we might wake up sooner. */
3398 select (0, NULL
, NULL
, NULL
, &timeout
);
3402 /* If window is tall, flash top and bottom line. */
3403 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3405 mac_invert_rectangle (f
, flash_left
,
3406 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3407 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3408 width
, flash_height
);
3409 mac_invert_rectangle (f
, flash_left
,
3410 (height
- flash_height
3411 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3412 width
, flash_height
);
3415 /* If it is short, flash it all. */
3416 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3417 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3424 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3427 /* Make audible bell. */
3432 struct frame
*f
= SELECTED_FRAME ();
3434 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3442 XFlush (FRAME_MAC_DISPLAY (f
));
3448 /* Specify how many text lines, from the top of the window,
3449 should be affected by insert-lines and delete-lines operations.
3450 This, and those operations, are used only within an update
3451 that is bounded by calls to x_update_begin and x_update_end. */
3454 XTset_terminal_window (n
)
3457 /* This function intentionally left blank. */
3462 /***********************************************************************
3464 ***********************************************************************/
3466 /* Perform an insert-lines or delete-lines operation, inserting N
3467 lines or deleting -N lines at vertical position VPOS. */
3470 x_ins_del_lines (vpos
, n
)
3477 /* Scroll part of the display as described by RUN. */
3480 x_scroll_run (w
, run
)
3484 struct frame
*f
= XFRAME (w
->frame
);
3485 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3487 /* Get frame-relative bounding box of the text display area of W,
3488 without mode lines. Include in this box the left and right
3490 window_box (w
, -1, &x
, &y
, &width
, &height
);
3492 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3493 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3494 bottom_y
= y
+ height
;
3498 /* Scrolling up. Make sure we don't copy part of the mode
3499 line at the bottom. */
3500 if (from_y
+ run
->height
> bottom_y
)
3501 height
= bottom_y
- from_y
;
3503 height
= run
->height
;
3507 /* Scolling down. Make sure we don't copy over the mode line.
3509 if (to_y
+ run
->height
> bottom_y
)
3510 height
= bottom_y
- to_y
;
3512 height
= run
->height
;
3517 /* Cursor off. Will be switched on again in x_update_window_end. */
3521 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3531 /***********************************************************************
3533 ***********************************************************************/
3541 ControlRef root_control
;
3544 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3546 ActivateControl (root_control
);
3548 x_update_cursor (f
, 1);
3552 frame_unhighlight (f
)
3556 ControlRef root_control
;
3559 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3561 DeactivateControl (root_control
);
3563 x_update_cursor (f
, 1);
3566 /* The focus has changed. Update the frames as necessary to reflect
3567 the new situation. Note that we can't change the selected frame
3568 here, because the Lisp code we are interrupting might become confused.
3569 Each event gets marked with the frame in which it occurred, so the
3570 Lisp code can tell when the switch took place by examining the events. */
3573 x_new_focus_frame (dpyinfo
, frame
)
3574 struct x_display_info
*dpyinfo
;
3575 struct frame
*frame
;
3577 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3579 if (frame
!= dpyinfo
->x_focus_frame
)
3581 /* Set this before calling other routines, so that they see
3582 the correct value of x_focus_frame. */
3583 dpyinfo
->x_focus_frame
= frame
;
3585 if (old_focus
&& old_focus
->auto_lower
)
3586 x_lower_frame (old_focus
);
3589 selected_frame
= frame
;
3590 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3592 Fselect_window (selected_frame
->selected_window
, Qnil
);
3593 choose_minibuf_frame ();
3596 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3597 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3599 pending_autoraise_frame
= 0;
3602 x_frame_rehighlight (dpyinfo
);
3605 /* Handle FocusIn and FocusOut state changes for FRAME.
3606 If FRAME has focus and there exists more than one frame, puts
3607 a FOCUS_IN_EVENT into *BUFP. */
3610 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3612 struct mac_display_info
*dpyinfo
;
3613 struct frame
*frame
;
3614 struct input_event
*bufp
;
3616 if (type
== activeFlag
)
3618 if (dpyinfo
->x_focus_event_frame
!= frame
)
3620 x_new_focus_frame (dpyinfo
, frame
);
3621 dpyinfo
->x_focus_event_frame
= frame
;
3623 /* Don't stop displaying the initial startup message
3624 for a switch-frame event we don't need. */
3625 if (GC_NILP (Vterminal_frame
)
3626 && GC_CONSP (Vframe_list
)
3627 && !GC_NILP (XCDR (Vframe_list
)))
3629 bufp
->kind
= FOCUS_IN_EVENT
;
3630 XSETFRAME (bufp
->frame_or_window
, frame
);
3636 if (dpyinfo
->x_focus_event_frame
== frame
)
3638 dpyinfo
->x_focus_event_frame
= 0;
3639 x_new_focus_frame (dpyinfo
, 0);
3644 /* The focus may have changed. Figure out if it is a real focus change,
3645 by checking both FocusIn/Out and Enter/LeaveNotify events.
3647 Returns FOCUS_IN_EVENT event in *BUFP. */
3650 x_detect_focus_change (dpyinfo
, event
, bufp
)
3651 struct mac_display_info
*dpyinfo
;
3653 struct input_event
*bufp
;
3655 struct frame
*frame
;
3657 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3661 /* On Mac, this is only called from focus events, so no switch needed. */
3662 mac_focus_changed ((event
->modifiers
& activeFlag
),
3663 dpyinfo
, frame
, bufp
);
3667 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3670 x_mouse_leave (dpyinfo
)
3671 struct x_display_info
*dpyinfo
;
3673 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3676 /* The focus has changed, or we have redirected a frame's focus to
3677 another frame (this happens when a frame uses a surrogate
3678 mini-buffer frame). Shift the highlight as appropriate.
3680 The FRAME argument doesn't necessarily have anything to do with which
3681 frame is being highlighted or un-highlighted; we only use it to find
3682 the appropriate X display info. */
3685 XTframe_rehighlight (frame
)
3686 struct frame
*frame
;
3688 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3692 x_frame_rehighlight (dpyinfo
)
3693 struct x_display_info
*dpyinfo
;
3695 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3697 if (dpyinfo
->x_focus_frame
)
3699 dpyinfo
->x_highlight_frame
3700 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3701 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3702 : dpyinfo
->x_focus_frame
);
3703 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3705 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3706 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3710 dpyinfo
->x_highlight_frame
= 0;
3712 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3715 frame_unhighlight (old_highlight
);
3716 if (dpyinfo
->x_highlight_frame
)
3717 frame_highlight (dpyinfo
->x_highlight_frame
);
3723 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3725 #if 0 /* MAC_TODO */
3726 /* Initialize mode_switch_bit and modifier_meaning. */
3728 x_find_modifier_meanings (dpyinfo
)
3729 struct x_display_info
*dpyinfo
;
3731 int min_code
, max_code
;
3734 XModifierKeymap
*mods
;
3736 dpyinfo
->meta_mod_mask
= 0;
3737 dpyinfo
->shift_lock_mask
= 0;
3738 dpyinfo
->alt_mod_mask
= 0;
3739 dpyinfo
->super_mod_mask
= 0;
3740 dpyinfo
->hyper_mod_mask
= 0;
3743 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3745 min_code
= dpyinfo
->display
->min_keycode
;
3746 max_code
= dpyinfo
->display
->max_keycode
;
3749 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3750 min_code
, max_code
- min_code
+ 1,
3752 mods
= XGetModifierMapping (dpyinfo
->display
);
3754 /* Scan the modifier table to see which modifier bits the Meta and
3755 Alt keysyms are on. */
3757 int row
, col
; /* The row and column in the modifier table. */
3759 for (row
= 3; row
< 8; row
++)
3760 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3763 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3765 /* Zeroes are used for filler. Skip them. */
3769 /* Are any of this keycode's keysyms a meta key? */
3773 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3775 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3781 dpyinfo
->meta_mod_mask
|= (1 << row
);
3786 dpyinfo
->alt_mod_mask
|= (1 << row
);
3791 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3796 dpyinfo
->super_mod_mask
|= (1 << row
);
3800 /* Ignore this if it's not on the lock modifier. */
3801 if ((1 << row
) == LockMask
)
3802 dpyinfo
->shift_lock_mask
= LockMask
;
3810 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3811 if (! dpyinfo
->meta_mod_mask
)
3813 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3814 dpyinfo
->alt_mod_mask
= 0;
3817 /* If some keys are both alt and meta,
3818 make them just meta, not alt. */
3819 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3821 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
3824 XFree ((char *) syms
);
3825 XFreeModifiermap (mods
);
3828 #endif /* MAC_TODO */
3830 /* Convert between the modifier bits X uses and the modifier bits
3834 x_mac_to_emacs_modifiers (dpyinfo
, state
)
3835 struct x_display_info
*dpyinfo
;
3836 unsigned short state
;
3838 return (((state
& shiftKey
) ? shift_modifier
: 0)
3839 | ((state
& controlKey
) ? ctrl_modifier
: 0)
3840 | ((state
& cmdKey
) ? meta_modifier
: 0)
3841 | ((state
& optionKey
) ? alt_modifier
: 0));
3844 #if 0 /* MAC_TODO */
3845 static unsigned short
3846 x_emacs_to_x_modifiers (dpyinfo
, state
)
3847 struct x_display_info
*dpyinfo
;
3850 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
3851 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
3852 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
3853 | ((state
& shift_modifier
) ? ShiftMask
: 0)
3854 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
3855 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
3857 #endif /* MAC_TODO */
3859 /* Convert a keysym to its name. */
3862 x_get_keysym_name (keysym
)
3869 value
= XKeysymToString (keysym
);
3880 /* Function to report a mouse movement to the mainstream Emacs code.
3881 The input handler calls this.
3883 We have received a mouse movement event, which is given in *event.
3884 If the mouse is over a different glyph than it was last time, tell
3885 the mainstream emacs code by setting mouse_moved. If not, ask for
3886 another motion event, so we can check again the next time it moves. */
3888 static Point last_mouse_motion_position
;
3889 static Lisp_Object last_mouse_motion_frame
;
3892 note_mouse_movement (frame
, pos
)
3896 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
3897 #if TARGET_API_MAC_CARBON
3901 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
3902 last_mouse_motion_position
= *pos
;
3903 XSETFRAME (last_mouse_motion_frame
, frame
);
3905 #if TARGET_API_MAC_CARBON
3906 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
3908 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
3911 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
3912 /* This case corresponds to LeaveNotify in X11. */
3914 /* If we move outside the frame, then we're certainly no
3915 longer on any text in the frame. */
3916 clear_mouse_face (dpyinfo
);
3917 dpyinfo
->mouse_face_mouse_frame
= 0;
3918 if (!dpyinfo
->grabbed
)
3919 rif
->define_frame_cursor (frame
,
3920 frame
->output_data
.mac
->nontext_cursor
);
3924 /* Has the mouse moved off the glyph it was on at the last sighting? */
3925 if (frame
!= last_mouse_glyph_frame
3926 || !PtInRect (*pos
, &last_mouse_glyph
))
3928 frame
->mouse_moved
= 1;
3929 last_mouse_scroll_bar
= Qnil
;
3930 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
3931 /* Remember which glyph we're now on. */
3932 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
3933 last_mouse_glyph_frame
= frame
;
3941 /************************************************************************
3943 ************************************************************************/
3945 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3948 redo_mouse_highlight ()
3950 if (!NILP (last_mouse_motion_frame
)
3951 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
3952 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
3953 last_mouse_motion_position
.h
,
3954 last_mouse_motion_position
.v
);
3958 static struct frame
*
3959 mac_focus_frame (dpyinfo
)
3960 struct mac_display_info
*dpyinfo
;
3962 if (dpyinfo
->x_focus_frame
)
3963 return dpyinfo
->x_focus_frame
;
3965 /* Mac version may get events, such as a menu bar click, even when
3966 all the frames are invisible. In this case, we regard the
3967 event came to the selected frame. */
3968 return SELECTED_FRAME ();
3972 /* Return the current position of the mouse.
3973 *FP should be a frame which indicates which display to ask about.
3975 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
3976 and *PART to the frame, window, and scroll bar part that the mouse
3977 is over. Set *X and *Y to the portion and whole of the mouse's
3978 position on the scroll bar.
3980 If the mouse movement started elsewhere, set *FP to the frame the
3981 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
3984 Set *TIME to the server time-stamp for the time at which the mouse
3985 was at this position.
3987 Don't store anything if we don't have a valid set of values to report.
3989 This clears the mouse_moved flag, so we can wait for the next mouse
3993 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
3996 Lisp_Object
*bar_window
;
3997 enum scroll_bar_part
*part
;
3999 unsigned long *time
;
4005 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4006 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4009 Lisp_Object frame
, tail
;
4011 /* Clear the mouse-moved flag for every frame on this display. */
4012 FOR_EACH_FRAME (tail
, frame
)
4013 XFRAME (frame
)->mouse_moved
= 0;
4015 last_mouse_scroll_bar
= Qnil
;
4017 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4018 && FRAME_LIVE_P (last_mouse_frame
))
4019 f1
= last_mouse_frame
;
4021 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4025 /* Ok, we found a frame. Store all the values.
4026 last_mouse_glyph is a rectangle used to reduce the
4027 generation of mouse events. To not miss any motion
4028 events, we must divide the frame into rectangles of the
4029 size of the smallest character that could be displayed
4030 on it, i.e. into the same rectangles that matrices on
4031 the frame are divided into. */
4034 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4035 GetMouse (&mouse_pos
);
4036 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4038 last_mouse_glyph_frame
= f1
;
4043 XSETINT (*x
, mouse_pos
.h
);
4044 XSETINT (*y
, mouse_pos
.v
);
4045 *time
= last_mouse_movement_time
;
4053 /************************************************************************
4055 ************************************************************************/
4057 #ifdef USE_TOOLKIT_SCROLL_BARS
4059 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4060 static OSStatus install_scroll_bar_timer
P_ ((void));
4061 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4062 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4063 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4064 struct input_event
*));
4065 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4067 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4069 struct input_event
*));
4070 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4071 struct input_event
*));
4072 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4073 Point
, struct input_event
*));
4074 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4077 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4079 static int last_scroll_bar_part
;
4081 static EventLoopTimerRef scroll_bar_timer
;
4083 static int scroll_bar_timer_event_posted_p
;
4085 #define SCROLL_BAR_FIRST_DELAY 0.5
4086 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4089 scroll_bar_timer_callback (timer
, data
)
4090 EventLoopTimerRef timer
;
4093 EventRef event
= NULL
;
4096 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4097 kEventAttributeNone
, &event
);
4102 GetMouse (&mouse_pos
);
4103 LocalToGlobal (&mouse_pos
);
4104 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4105 sizeof (Point
), &mouse_pos
);
4109 UInt32 modifiers
= GetCurrentKeyModifiers ();
4111 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4112 sizeof (UInt32
), &modifiers
);
4115 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4116 kEventPriorityStandard
);
4118 scroll_bar_timer_event_posted_p
= 1;
4121 ReleaseEvent (event
);
4125 install_scroll_bar_timer ()
4127 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4129 if (scroll_bar_timer_callbackUPP
== NULL
)
4130 scroll_bar_timer_callbackUPP
=
4131 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4133 if (scroll_bar_timer
== NULL
)
4134 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4135 kEventDurationForever as delays. */
4137 InstallEventLoopTimer (GetCurrentEventLoop (),
4138 kEventDurationForever
, kEventDurationForever
,
4139 scroll_bar_timer_callbackUPP
, NULL
,
4144 set_scroll_bar_timer (delay
)
4145 EventTimerInterval delay
;
4147 if (scroll_bar_timer
== NULL
)
4148 install_scroll_bar_timer ();
4150 scroll_bar_timer_event_posted_p
= 0;
4152 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4156 control_part_code_to_scroll_bar_part (part_code
)
4157 ControlPartCode part_code
;
4161 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4162 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4163 case kControlPageUpPart
: return scroll_bar_above_handle
;
4164 case kControlPageDownPart
: return scroll_bar_below_handle
;
4165 case kControlIndicatorPart
: return scroll_bar_handle
;
4172 construct_scroll_bar_click (bar
, part
, bufp
)
4173 struct scroll_bar
*bar
;
4175 struct input_event
*bufp
;
4177 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4178 bufp
->frame_or_window
= bar
->window
;
4182 XSETINT (bufp
->x
, 0);
4183 XSETINT (bufp
->y
, 0);
4184 bufp
->modifiers
= 0;
4188 get_control_part_bounds (ch
, part_code
, rect
)
4190 ControlPartCode part_code
;
4193 RgnHandle region
= NewRgn ();
4196 err
= GetControlRegion (ch
, part_code
, region
);
4198 GetRegionBounds (region
, rect
);
4199 DisposeRgn (region
);
4205 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4206 struct scroll_bar
*bar
;
4207 ControlPartCode part_code
;
4208 struct input_event
*bufp
;
4210 int part
= control_part_code_to_scroll_bar_part (part_code
);
4215 if (part
!= scroll_bar_handle
)
4217 construct_scroll_bar_click (bar
, part
, bufp
);
4218 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4219 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4222 last_scroll_bar_part
= part
;
4223 bar
->dragging
= Qnil
;
4224 tracked_scroll_bar
= bar
;
4228 x_scroll_bar_handle_release (bar
, bufp
)
4229 struct scroll_bar
*bar
;
4230 struct input_event
*bufp
;
4232 if (last_scroll_bar_part
!= scroll_bar_handle
4233 || !GC_NILP (bar
->dragging
))
4234 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4236 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4237 set_scroll_bar_timer (kEventDurationForever
);
4239 last_scroll_bar_part
= -1;
4240 bar
->dragging
= Qnil
;
4241 tracked_scroll_bar
= NULL
;
4245 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4247 struct scroll_bar
*bar
;
4249 struct input_event
*bufp
;
4251 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4253 if (last_scroll_bar_part
== scroll_bar_handle
)
4258 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4259 kControlIndicatorPart
, &r
);
4261 if (GC_NILP (bar
->dragging
))
4262 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4264 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4265 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4266 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4271 if (top
> top_range
)
4274 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4275 XSETINT (bufp
->x
, top
);
4276 XSETINT (bufp
->y
, top_range
);
4280 ControlPartCode part_code
;
4281 int unhilite_p
= 0, part
;
4283 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4287 part
= control_part_code_to_scroll_bar_part (part_code
);
4289 switch (last_scroll_bar_part
)
4291 case scroll_bar_above_handle
:
4292 case scroll_bar_below_handle
:
4293 if (part
!= scroll_bar_above_handle
4294 && part
!= scroll_bar_below_handle
)
4298 case scroll_bar_up_arrow
:
4299 case scroll_bar_down_arrow
:
4300 if (part
!= scroll_bar_up_arrow
4301 && part
!= scroll_bar_down_arrow
)
4308 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4309 else if (part
!= last_scroll_bar_part
4310 || scroll_bar_timer_event_posted_p
)
4312 construct_scroll_bar_click (bar
, part
, bufp
);
4313 last_scroll_bar_part
= part
;
4314 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4315 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4320 /* Set the thumb size and position of scroll bar BAR. We are currently
4321 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4324 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4325 struct scroll_bar
*bar
;
4326 int portion
, position
, whole
;
4328 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4330 int value
, viewsize
, maximum
;
4332 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4333 value
= 0, viewsize
= 1, maximum
= 0;
4338 maximum
= max (0, whole
- portion
);
4343 SetControl32BitMinimum (ch
, 0);
4344 SetControl32BitMaximum (ch
, maximum
);
4345 SetControl32BitValue (ch
, value
);
4346 SetControlViewSize (ch
, viewsize
);
4351 #endif /* USE_TOOLKIT_SCROLL_BARS */
4355 /************************************************************************
4356 Scroll bars, general
4357 ************************************************************************/
4359 /* Create a scroll bar and return the scroll bar vector for it. W is
4360 the Emacs window on which to create the scroll bar. TOP, LEFT,
4361 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4364 static struct scroll_bar
*
4365 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4367 int top
, left
, width
, height
, disp_top
, disp_height
;
4369 struct frame
*f
= XFRAME (w
->frame
);
4370 struct scroll_bar
*bar
4371 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4379 r
.right
= left
+ width
;
4380 r
.bottom
= disp_top
+ disp_height
;
4382 #if TARGET_API_MAC_CARBON
4383 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4384 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4386 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4387 0, 0, 0, scrollBarProc
, (long) bar
);
4389 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4391 XSETWINDOW (bar
->window
, w
);
4392 XSETINT (bar
->top
, top
);
4393 XSETINT (bar
->left
, left
);
4394 XSETINT (bar
->width
, width
);
4395 XSETINT (bar
->height
, height
);
4396 XSETINT (bar
->start
, 0);
4397 XSETINT (bar
->end
, 0);
4398 bar
->dragging
= Qnil
;
4399 #ifdef USE_TOOLKIT_SCROLL_BARS
4400 bar
->track_top
= Qnil
;
4401 bar
->track_height
= Qnil
;
4404 /* Add bar to its frame's list of scroll bars. */
4405 bar
->next
= FRAME_SCROLL_BARS (f
);
4407 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4408 if (!NILP (bar
->next
))
4409 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4416 /* Draw BAR's handle in the proper position.
4418 If the handle is already drawn from START to END, don't bother
4419 redrawing it, unless REBUILD is non-zero; in that case, always
4420 redraw it. (REBUILD is handy for drawing the handle after expose
4423 Normally, we want to constrain the start and end of the handle to
4424 fit inside its rectangle, but if the user is dragging the scroll
4425 bar handle, we want to let them drag it down all the way, so that
4426 the bar's top is as far down as it goes; otherwise, there's no way
4427 to move to the very end of the buffer. */
4429 #ifndef USE_TOOLKIT_SCROLL_BARS
4432 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4433 struct scroll_bar
*bar
;
4437 int dragging
= ! NILP (bar
->dragging
);
4438 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4439 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4440 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4441 int length
= end
- start
;
4443 /* If the display is already accurate, do nothing. */
4445 && start
== XINT (bar
->start
)
4446 && end
== XINT (bar
->end
))
4451 /* Make sure the values are reasonable, and try to preserve the
4452 distance between start and end. */
4455 else if (start
> top_range
)
4457 end
= start
+ length
;
4461 else if (end
> top_range
&& ! dragging
)
4464 /* Store the adjusted setting in the scroll bar. */
4465 XSETINT (bar
->start
, start
);
4466 XSETINT (bar
->end
, end
);
4468 /* Clip the end position, just for display. */
4469 if (end
> top_range
)
4472 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4473 top positions, to make sure the handle is always at least that
4474 many pixels tall. */
4475 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4477 SetControlMinimum (ch
, 0);
4478 /* Don't inadvertently activate deactivated scroll bars */
4479 if (GetControlMaximum (ch
) != -1)
4480 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4482 SetControlValue (ch
, start
);
4483 #if TARGET_API_MAC_CARBON
4484 SetControlViewSize (ch
, end
- start
);
4490 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4492 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4496 x_scroll_bar_remove (bar
)
4497 struct scroll_bar
*bar
;
4499 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4503 /* Destroy the Mac scroll bar control */
4504 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4506 /* Disassociate this scroll bar from its window. */
4507 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4513 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4514 that we are displaying PORTION characters out of a total of WHOLE
4515 characters, starting at POSITION. If WINDOW has no scroll bar,
4519 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4521 int portion
, whole
, position
;
4523 struct frame
*f
= XFRAME (w
->frame
);
4524 struct scroll_bar
*bar
;
4525 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4526 int window_y
, window_height
;
4528 /* Get window dimensions. */
4529 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4531 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4532 height
= window_height
;
4534 /* Compute the left edge of the scroll bar area. */
4535 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4537 /* Compute the width of the scroll bar which might be less than
4538 the width of the area reserved for the scroll bar. */
4539 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4540 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4544 /* Compute the left edge of the scroll bar. */
4545 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4548 sb_left
= left
+ width
- sb_width
;
4550 /* Adjustments according to Inside Macintosh to make it look nice */
4552 disp_height
= height
;
4558 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4564 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4567 /* Does the scroll bar exist yet? */
4568 if (NILP (w
->vertical_scroll_bar
))
4571 mac_clear_area (f
, left
, top
, width
, height
);
4573 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4575 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4579 /* It may just need to be moved and resized. */
4582 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4583 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4587 /* If already correctly positioned, do nothing. */
4588 if (!(XINT (bar
->left
) == sb_left
4589 && XINT (bar
->top
) == top
4590 && XINT (bar
->width
) == sb_width
4591 && XINT (bar
->height
) == height
))
4593 /* Since toolkit scroll bars are smaller than the space reserved
4594 for them on the frame, we have to clear "under" them. */
4595 mac_clear_area (f
, left
, top
, width
, height
);
4598 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4599 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4601 if (sb_width
< disp_height
)
4604 /* Remember new settings. */
4605 XSETINT (bar
->left
, sb_left
);
4606 XSETINT (bar
->top
, top
);
4607 XSETINT (bar
->width
, sb_width
);
4608 XSETINT (bar
->height
, height
);
4609 #ifdef USE_TOOLKIT_SCROLL_BARS
4610 bar
->track_top
= Qnil
;
4611 bar
->track_height
= Qnil
;
4618 #ifdef USE_TOOLKIT_SCROLL_BARS
4619 if (NILP (bar
->track_top
))
4621 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4626 SetControl32BitMinimum (ch
, 0);
4627 SetControl32BitMaximum (ch
, 1);
4628 SetControlViewSize (ch
, 1);
4630 /* Move the scroll bar thumb to the top. */
4631 SetControl32BitValue (ch
, 0);
4632 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4634 /* Move the scroll bar thumb to the bottom. */
4635 SetControl32BitValue (ch
, 1);
4636 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4638 UnionRect (&r0
, &r1
, &r0
);
4639 XSETINT (bar
->track_top
, r0
.top
);
4640 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4645 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4646 #else /* not USE_TOOLKIT_SCROLL_BARS */
4647 /* Set the scroll bar's current state, unless we're currently being
4649 if (NILP (bar
->dragging
))
4651 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4654 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4657 int start
= ((double) position
* top_range
) / whole
;
4658 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4659 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4662 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4666 /* The following three hooks are used when we're doing a thorough
4667 redisplay of the frame. We don't explicitly know which scroll bars
4668 are going to be deleted, because keeping track of when windows go
4669 away is a real pain - "Can you say set-window-configuration, boys
4670 and girls?" Instead, we just assert at the beginning of redisplay
4671 that *all* scroll bars are to be removed, and then save a scroll bar
4672 from the fiery pit when we actually redisplay its window. */
4674 /* Arrange for all scroll bars on FRAME to be removed at the next call
4675 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4676 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4679 XTcondemn_scroll_bars (frame
)
4682 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4683 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4686 bar
= FRAME_SCROLL_BARS (frame
);
4687 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4688 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4689 XSCROLL_BAR (bar
)->prev
= Qnil
;
4690 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4691 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4692 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4697 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4698 Note that WINDOW isn't necessarily condemned at all. */
4701 XTredeem_scroll_bar (window
)
4702 struct window
*window
;
4704 struct scroll_bar
*bar
;
4707 /* We can't redeem this window's scroll bar if it doesn't have one. */
4708 if (NILP (window
->vertical_scroll_bar
))
4711 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4713 /* Unlink it from the condemned list. */
4714 f
= XFRAME (WINDOW_FRAME (window
));
4715 if (NILP (bar
->prev
))
4717 /* If the prev pointer is nil, it must be the first in one of
4719 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4720 /* It's not condemned. Everything's fine. */
4722 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4723 window
->vertical_scroll_bar
))
4724 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4726 /* If its prev pointer is nil, it must be at the front of
4727 one or the other! */
4731 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4733 if (! NILP (bar
->next
))
4734 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4736 bar
->next
= FRAME_SCROLL_BARS (f
);
4738 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4739 if (! NILP (bar
->next
))
4740 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4743 /* Remove all scroll bars on FRAME that haven't been saved since the
4744 last call to `*condemn_scroll_bars_hook'. */
4747 XTjudge_scroll_bars (f
)
4750 Lisp_Object bar
, next
;
4752 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4754 /* Clear out the condemned list now so we won't try to process any
4755 more events on the hapless scroll bars. */
4756 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4758 for (; ! NILP (bar
); bar
= next
)
4760 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4762 x_scroll_bar_remove (b
);
4765 b
->next
= b
->prev
= Qnil
;
4768 /* Now there should be no references to the condemned scroll bars,
4769 and they should get garbage-collected. */
4773 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4774 is set to something other than NO_EVENT, it is enqueued.
4776 This may be called from a signal handler, so we have to ignore GC
4780 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4781 struct scroll_bar
*bar
;
4782 ControlPartCode part_code
;
4784 struct input_event
*bufp
;
4786 int win_y
, top_range
;
4788 if (! GC_WINDOWP (bar
->window
))
4791 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4792 bufp
->frame_or_window
= bar
->window
;
4795 bar
->dragging
= Qnil
;
4799 case kControlUpButtonPart
:
4800 bufp
->part
= scroll_bar_up_arrow
;
4802 case kControlDownButtonPart
:
4803 bufp
->part
= scroll_bar_down_arrow
;
4805 case kControlPageUpPart
:
4806 bufp
->part
= scroll_bar_above_handle
;
4808 case kControlPageDownPart
:
4809 bufp
->part
= scroll_bar_below_handle
;
4811 #if TARGET_API_MAC_CARBON
4814 case kControlIndicatorPart
:
4816 if (er
->what
== mouseDown
)
4817 bar
->dragging
= make_number (0);
4818 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4819 bufp
->part
= scroll_bar_handle
;
4823 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
4824 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
4826 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4830 if (! NILP (bar
->dragging
))
4831 win_y
-= XINT (bar
->dragging
);
4835 if (win_y
> top_range
)
4838 XSETINT (bufp
->x
, win_y
);
4839 XSETINT (bufp
->y
, top_range
);
4842 #ifndef USE_TOOLKIT_SCROLL_BARS
4844 /* Handle some mouse motion while someone is dragging the scroll bar.
4846 This may be called from a signal handler, so we have to ignore GC
4850 x_scroll_bar_note_movement (bar
, y_pos
, t
)
4851 struct scroll_bar
*bar
;
4855 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
4857 last_mouse_movement_time
= t
;
4860 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4862 /* If we're dragging the bar, display it. */
4863 if (! GC_NILP (bar
->dragging
))
4865 /* Where should the handle be now? */
4866 int new_start
= y_pos
- 24;
4868 if (new_start
!= XINT (bar
->start
))
4870 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
4872 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
4877 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4879 /* Return information to the user about the current position of the mouse
4880 on the scroll bar. */
4883 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
4885 Lisp_Object
*bar_window
;
4886 enum scroll_bar_part
*part
;
4888 unsigned long *time
;
4890 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
4891 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4892 #if TARGET_API_MAC_CARBON
4893 WindowPtr wp
= GetControlOwner (ch
);
4895 WindowPtr wp
= (*ch
)->contrlOwner
;
4898 struct frame
*f
= mac_window_to_frame (wp
);
4899 int win_y
, top_range
;
4901 SetPortWindowPort (wp
);
4903 GetMouse (&mouse_pos
);
4905 win_y
= mouse_pos
.v
- XINT (bar
->top
);
4906 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4908 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
4912 if (! NILP (bar
->dragging
))
4913 win_y
-= XINT (bar
->dragging
);
4917 if (win_y
> top_range
)
4921 *bar_window
= bar
->window
;
4923 if (! NILP (bar
->dragging
))
4924 *part
= scroll_bar_handle
;
4925 else if (win_y
< XINT (bar
->start
))
4926 *part
= scroll_bar_above_handle
;
4927 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
4928 *part
= scroll_bar_handle
;
4930 *part
= scroll_bar_below_handle
;
4932 XSETINT (*x
, win_y
);
4933 XSETINT (*y
, top_range
);
4936 last_mouse_scroll_bar
= Qnil
;
4938 *time
= last_mouse_movement_time
;
4942 /* The screen has been cleared so we may have changed foreground or
4943 background colors, and the scroll bars may need to be redrawn.
4944 Clear out the scroll bars, and ask for expose events, so we can
4948 x_scroll_bar_clear (f
)
4951 XTcondemn_scroll_bars (f
);
4952 XTjudge_scroll_bars (f
);
4956 /***********************************************************************
4958 ***********************************************************************/
4960 /* Set clipping for output in glyph row ROW. W is the window in which
4961 we operate. GC is the graphics context to set clipping in.
4963 ROW may be a text row or, e.g., a mode line. Text rows must be
4964 clipped to the interior of the window dedicated to text display,
4965 mode lines must be clipped to the whole window. */
4968 x_clip_to_row (w
, row
, area
, gc
)
4970 struct glyph_row
*row
;
4974 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4976 int window_x
, window_y
, window_width
;
4978 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
4980 clip_rect
.left
= window_x
;
4981 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
4982 clip_rect
.top
= max (clip_rect
.top
, window_y
);
4983 clip_rect
.right
= clip_rect
.left
+ window_width
;
4984 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
4986 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
4990 /* Draw a hollow box cursor on window W in glyph row ROW. */
4993 x_draw_hollow_cursor (w
, row
)
4995 struct glyph_row
*row
;
4997 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
4998 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
4999 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5002 struct glyph
*cursor_glyph
;
5005 /* Get the glyph the cursor is on. If we can't tell because
5006 the current matrix is invalid or such, give up. */
5007 cursor_glyph
= get_phys_cursor_glyph (w
);
5008 if (cursor_glyph
== NULL
)
5011 /* Compute frame-relative coordinates for phys cursor. */
5012 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5013 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5014 wd
= w
->phys_cursor_width
;
5016 /* The foreground of cursor_gc is typically the same as the normal
5017 background color, which can cause the cursor box to be invisible. */
5018 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5019 if (dpyinfo
->scratch_cursor_gc
)
5020 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5022 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5023 GCForeground
, &xgcv
);
5024 gc
= dpyinfo
->scratch_cursor_gc
;
5026 /* Set clipping, draw the rectangle, and reset clipping again. */
5027 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5028 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5029 mac_reset_clip_rectangles (dpy
, gc
);
5033 /* Draw a bar cursor on window W in glyph row ROW.
5035 Implementation note: One would like to draw a bar cursor with an
5036 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5037 Unfortunately, I didn't find a font yet that has this property set.
5041 x_draw_bar_cursor (w
, row
, width
, kind
)
5043 struct glyph_row
*row
;
5045 enum text_cursor_kinds kind
;
5047 struct frame
*f
= XFRAME (w
->frame
);
5048 struct glyph
*cursor_glyph
;
5050 /* If cursor is out of bounds, don't draw garbage. This can happen
5051 in mini-buffer windows when switching between echo area glyphs
5053 cursor_glyph
= get_phys_cursor_glyph (w
);
5054 if (cursor_glyph
== NULL
)
5057 /* If on an image, draw like a normal cursor. That's usually better
5058 visible than drawing a bar, esp. if the image is large so that
5059 the bar might not be in the window. */
5060 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5062 struct glyph_row
*row
;
5063 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5064 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5068 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5069 Window window
= FRAME_MAC_WINDOW (f
);
5070 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5071 unsigned long mask
= GCForeground
| GCBackground
;
5072 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5075 /* If the glyph's background equals the color we normally draw
5076 the bar cursor in, the bar cursor in its normal color is
5077 invisible. Use the glyph's foreground color instead in this
5078 case, on the assumption that the glyph's colors are chosen so
5079 that the glyph is legible. */
5080 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5081 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5083 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5086 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5089 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5090 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5094 width
= FRAME_CURSOR_WIDTH (f
);
5095 width
= min (cursor_glyph
->pixel_width
, width
);
5097 w
->phys_cursor_width
= width
;
5098 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5100 if (kind
== BAR_CURSOR
)
5101 mac_fill_rectangle (f
, gc
,
5102 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5103 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5104 width
, row
->height
);
5106 mac_fill_rectangle (f
, gc
,
5107 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5108 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5109 row
->height
- width
),
5110 cursor_glyph
->pixel_width
,
5113 mac_reset_clip_rectangles (dpy
, gc
);
5118 /* RIF: Define cursor CURSOR on frame F. */
5121 mac_define_frame_cursor (f
, cursor
)
5125 SetThemeCursor (cursor
);
5129 /* RIF: Clear area on frame F. */
5132 mac_clear_frame_area (f
, x
, y
, width
, height
)
5134 int x
, y
, width
, height
;
5136 mac_clear_area (f
, x
, y
, width
, height
);
5140 /* RIF: Draw cursor on window W. */
5143 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5145 struct glyph_row
*glyph_row
;
5147 int cursor_type
, cursor_width
;
5152 w
->phys_cursor_type
= cursor_type
;
5153 w
->phys_cursor_on_p
= 1;
5155 if (glyph_row
->exact_window_width_line_p
5156 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5158 glyph_row
->cursor_in_fringe_p
= 1;
5159 draw_fringe_bitmap (w
, glyph_row
, 0);
5162 switch (cursor_type
)
5164 case HOLLOW_BOX_CURSOR
:
5165 x_draw_hollow_cursor (w
, glyph_row
);
5168 case FILLED_BOX_CURSOR
:
5169 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5173 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5177 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5181 w
->phys_cursor_width
= 0;
5193 #if 0 /* MAC_TODO: no icon support yet. */
5195 x_bitmap_icon (f
, icon
)
5201 if (FRAME_W32_WINDOW (f
) == 0)
5205 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5206 else if (STRINGP (icon
))
5207 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5208 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5209 else if (SYMBOLP (icon
))
5213 if (EQ (icon
, intern ("application")))
5214 name
= (LPCTSTR
) IDI_APPLICATION
;
5215 else if (EQ (icon
, intern ("hand")))
5216 name
= (LPCTSTR
) IDI_HAND
;
5217 else if (EQ (icon
, intern ("question")))
5218 name
= (LPCTSTR
) IDI_QUESTION
;
5219 else if (EQ (icon
, intern ("exclamation")))
5220 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5221 else if (EQ (icon
, intern ("asterisk")))
5222 name
= (LPCTSTR
) IDI_ASTERISK
;
5223 else if (EQ (icon
, intern ("winlogo")))
5224 name
= (LPCTSTR
) IDI_WINLOGO
;
5228 hicon
= LoadIcon (NULL
, name
);
5236 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5241 #endif /* MAC_TODO */
5243 /************************************************************************
5245 ************************************************************************/
5247 /* Display Error Handling functions not used on W32. Listing them here
5248 helps diff stay in step when comparing w32term.c with xterm.c.
5250 x_error_catcher (display, error)
5251 x_catch_errors (dpy)
5252 x_catch_errors_unwind (old_val)
5253 x_check_errors (dpy, format)
5254 x_had_errors_p (dpy)
5255 x_clear_errors (dpy)
5256 x_uncatch_errors (dpy, count)
5258 x_connection_signal (signalnum)
5259 x_connection_closed (dpy, error_message)
5260 x_error_quitter (display, error)
5261 x_error_handler (display, error)
5262 x_io_error_quitter (display)
5267 /* Changing the font of the frame. */
5269 /* Give frame F the font named FONTNAME as its default font, and
5270 return the full name of that font. FONTNAME may be a wildcard
5271 pattern; in that case, we choose some font that fits the pattern.
5272 The return value shows which font we chose. */
5275 x_new_font (f
, fontname
)
5277 register char *fontname
;
5279 struct font_info
*fontp
5280 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5285 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5286 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5287 FRAME_FONTSET (f
) = -1;
5289 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5290 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5291 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5293 compute_fringe_widths (f
, 1);
5295 /* Compute the scroll bar width in character columns. */
5296 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5298 int wid
= FRAME_COLUMN_WIDTH (f
);
5299 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5300 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5304 int wid
= FRAME_COLUMN_WIDTH (f
);
5305 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5308 /* Now make the frame display the given font. */
5309 if (FRAME_MAC_WINDOW (f
) != 0)
5311 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5313 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5315 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5318 /* Don't change the size of a tip frame; there's no point in
5319 doing it because it's done in Fx_show_tip, and it leads to
5320 problems because the tip frame has no widget. */
5321 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5322 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5325 return build_string (fontp
->full_name
);
5328 /* Give frame F the fontset named FONTSETNAME as its default font, and
5329 return the full name of that fontset. FONTSETNAME may be a wildcard
5330 pattern; in that case, we choose some fontset that fits the pattern.
5331 The return value shows which fontset we chose. */
5334 x_new_fontset (f
, fontsetname
)
5338 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5344 if (FRAME_FONTSET (f
) == fontset
)
5345 /* This fontset is already set in frame F. There's nothing more
5347 return fontset_name (fontset
);
5349 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5351 if (!STRINGP (result
))
5352 /* Can't load ASCII font. */
5355 /* Since x_new_font doesn't update any fontset information, do it now. */
5356 FRAME_FONTSET (f
) = fontset
;
5358 return build_string (fontsetname
);
5362 /***********************************************************************
5363 TODO: W32 Input Methods
5364 ***********************************************************************/
5365 /* Listing missing functions from xterm.c helps diff stay in step.
5367 xim_destroy_callback (xim, client_data, call_data)
5368 xim_open_dpy (dpyinfo, resource_name)
5370 xim_instantiate_callback (display, client_data, call_data)
5371 xim_initialize (dpyinfo, resource_name)
5372 xim_close_dpy (dpyinfo)
5378 mac_get_window_bounds (f
, inner
, outer
)
5380 Rect
*inner
, *outer
;
5382 #if TARGET_API_MAC_CARBON
5383 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5384 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5385 #else /* not TARGET_API_MAC_CARBON */
5386 RgnHandle region
= NewRgn ();
5388 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5389 *inner
= (*region
)->rgnBBox
;
5390 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5391 *outer
= (*region
)->rgnBBox
;
5392 DisposeRgn (region
);
5393 #endif /* not TARGET_API_MAC_CARBON */
5398 /* Calculate the absolute position in frame F
5399 from its current recorded position values and gravity. */
5402 x_calc_absolute_position (f
)
5405 int width_diff
= 0, height_diff
= 0;
5406 int flags
= f
->size_hint_flags
;
5409 /* We have nothing to do if the current position
5410 is already for the top-left corner. */
5411 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5414 /* Find the offsets of the outside upper-left corner of
5415 the inner window, with respect to the outer window. */
5416 mac_get_window_bounds (f
, &inner
, &outer
);
5418 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5419 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5421 /* Treat negative positions as relative to the leftmost bottommost
5422 position that fits on the screen. */
5423 if (flags
& XNegative
)
5424 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5426 - FRAME_PIXEL_WIDTH (f
)
5429 if (flags
& YNegative
)
5430 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5432 - FRAME_PIXEL_HEIGHT (f
)
5435 /* The left_pos and top_pos
5436 are now relative to the top and left screen edges,
5437 so the flags should correspond. */
5438 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5441 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5442 to really change the position, and 0 when calling from
5443 x_make_frame_visible (in that case, XOFF and YOFF are the current
5444 position values). It is -1 when calling from x_set_frame_parameters,
5445 which means, do adjust for borders but don't change the gravity. */
5448 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5450 register int xoff
, yoff
;
5453 if (change_gravity
> 0)
5457 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5459 f
->size_hint_flags
|= XNegative
;
5461 f
->size_hint_flags
|= YNegative
;
5462 f
->win_gravity
= NorthWestGravity
;
5464 x_calc_absolute_position (f
);
5467 x_wm_set_size_hint (f
, (long) 0, 0);
5469 #if TARGET_API_MAC_CARBON
5470 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5471 /* If the title bar is completely outside the screen, adjust the
5473 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5474 kWindowConstrainMoveRegardlessOfFit
5475 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5476 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5479 Rect inner
, outer
, screen_rect
, dummy
;
5480 RgnHandle region
= NewRgn ();
5482 mac_get_window_bounds (f
, &inner
, &outer
);
5483 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5484 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5485 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5486 f
->top_pos
+ f
->y_pixels_diff
, false);
5488 /* If the title bar is completely outside the screen, adjust the
5489 position. The variable `outer' holds the title bar rectangle.
5490 The variable `inner' holds slightly smaller one than `outer',
5491 so that the calculation of overlapping may not become too
5493 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5494 outer
= (*region
)->rgnBBox
;
5495 DisposeRgn (region
);
5497 InsetRect (&inner
, 8, 8);
5498 screen_rect
= qd
.screenBits
.bounds
;
5499 screen_rect
.top
+= GetMBarHeight ();
5501 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5503 if (inner
.right
<= screen_rect
.left
)
5504 f
->left_pos
= screen_rect
.left
;
5505 else if (inner
.left
>= screen_rect
.right
)
5506 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5508 if (inner
.bottom
<= screen_rect
.top
)
5509 f
->top_pos
= screen_rect
.top
;
5510 else if (inner
.top
>= screen_rect
.bottom
)
5511 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5513 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5514 f
->top_pos
+ f
->y_pixels_diff
, false);
5522 /* Call this to change the size of frame F's x-window.
5523 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5524 for this size change and subsequent size changes.
5525 Otherwise we leave the window gravity unchanged. */
5528 x_set_window_size (f
, change_gravity
, cols
, rows
)
5533 int pixelwidth
, pixelheight
;
5537 check_frame_size (f
, &rows
, &cols
);
5538 f
->scroll_bar_actual_width
5539 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5541 compute_fringe_widths (f
, 0);
5543 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5544 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5546 f
->win_gravity
= NorthWestGravity
;
5547 x_wm_set_size_hint (f
, (long) 0, 0);
5549 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5550 #if TARGET_API_MAC_CARBON
5551 if (f
->output_data
.mac
->hourglass_control
)
5552 MoveControl (f
->output_data
.mac
->hourglass_control
,
5553 pixelwidth
- HOURGLASS_WIDTH
, 0);
5556 /* Now, strictly speaking, we can't be sure that this is accurate,
5557 but the window manager will get around to dealing with the size
5558 change request eventually, and we'll hear how it went when the
5559 ConfigureNotify event gets here.
5561 We could just not bother storing any of this information here,
5562 and let the ConfigureNotify event set everything up, but that
5563 might be kind of confusing to the Lisp code, since size changes
5564 wouldn't be reported in the frame parameters until some random
5565 point in the future when the ConfigureNotify event arrives.
5567 We pass 1 for DELAY since we can't run Lisp code inside of
5569 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5570 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5571 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5573 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5574 receive in the ConfigureNotify event; if we get what we asked
5575 for, then the event won't cause the screen to become garbaged, so
5576 we have to make sure to do it here. */
5577 SET_FRAME_GARBAGED (f
);
5579 XFlush (FRAME_X_DISPLAY (f
));
5581 /* If cursor was outside the new size, mark it as off. */
5582 mark_window_cursors_off (XWINDOW (f
->root_window
));
5584 /* Clear out any recollection of where the mouse highlighting was,
5585 since it might be in a place that's outside the new frame size.
5586 Actually checking whether it is outside is a pain in the neck,
5587 so don't try--just let the highlighting be done afresh with new size. */
5588 cancel_mouse_face (f
);
5593 /* Mouse warping. */
5595 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5598 x_set_mouse_position (f
, x
, y
)
5604 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5605 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5607 if (pix_x
< 0) pix_x
= 0;
5608 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5610 if (pix_y
< 0) pix_y
= 0;
5611 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5613 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5617 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5621 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5624 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5625 0, 0, 0, 0, pix_x
, pix_y
);
5630 /* focus shifting, raising and lowering. */
5633 x_focus_on_frame (f
)
5636 #if 0 /* This proves to be unpleasant. */
5640 /* I don't think that the ICCCM allows programs to do things like this
5641 without the interaction of the window manager. Whatever you end up
5642 doing with this code, do it to x_unfocus_frame too. */
5643 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5644 RevertToPointerRoot
, CurrentTime
);
5654 /* Raise frame F. */
5660 if (f
->async_visible
)
5663 SelectWindow (FRAME_MAC_WINDOW (f
));
5668 /* Lower frame F. */
5674 if (f
->async_visible
)
5677 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5683 XTframe_raise_lower (f
, raise_flag
)
5693 /* Change of visibility. */
5696 mac_handle_visibility_change (f
)
5699 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5700 int visible
= 0, iconified
= 0;
5701 struct input_event buf
;
5703 if (IsWindowVisible (wp
))
5704 if (IsWindowCollapsed (wp
))
5709 if (!f
->async_visible
&& visible
)
5713 /* wait_reading_process_output will notice this and update
5714 the frame's display structures. If we were made
5715 invisible, we should not set garbaged, because that stops
5716 redrawing on Update events. */
5717 SET_FRAME_GARBAGED (f
);
5720 buf
.kind
= DEICONIFY_EVENT
;
5721 XSETFRAME (buf
.frame_or_window
, f
);
5722 kbd_buffer_store_event (&buf
);
5724 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5725 /* Force a redisplay sooner or later to update the
5726 frame titles in case this is the second frame. */
5727 record_asynch_buffer_change ();
5729 else if (f
->async_visible
&& !visible
)
5733 buf
.kind
= ICONIFY_EVENT
;
5734 XSETFRAME (buf
.frame_or_window
, f
);
5735 kbd_buffer_store_event (&buf
);
5738 f
->async_visible
= visible
;
5739 f
->async_iconified
= iconified
;
5742 /* This tries to wait until the frame is really visible.
5743 However, if the window manager asks the user where to position
5744 the frame, this will return before the user finishes doing that.
5745 The frame will not actually be visible at that time,
5746 but it will become visible later when the window manager
5747 finishes with it. */
5750 x_make_frame_visible (f
)
5754 int original_top
, original_left
;
5758 if (! FRAME_VISIBLE_P (f
))
5760 /* We test FRAME_GARBAGED_P here to make sure we don't
5761 call x_set_offset a second time
5762 if we get to x_make_frame_visible a second time
5763 before the window gets really visible. */
5764 if (! FRAME_ICONIFIED_P (f
)
5765 && ! f
->output_data
.mac
->asked_for_visible
)
5766 #if TARGET_API_MAC_CARBON
5767 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5769 struct frame
*sf
= SELECTED_FRAME ();
5770 if (!FRAME_MAC_P (sf
))
5771 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5772 kWindowCenterOnMainScreen
);
5774 RepositionWindow (FRAME_MAC_WINDOW (f
),
5775 FRAME_MAC_WINDOW (sf
),
5776 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5777 kWindowCascadeStartAtParentWindowScreen
5779 kWindowCascadeOnParentWindowScreen
5782 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5786 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5788 f
->output_data
.mac
->asked_for_visible
= 1;
5790 SelectWindow (FRAME_MAC_WINDOW (f
));
5791 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
5792 ShowWindow (FRAME_MAC_WINDOW (f
));
5795 XFlush (FRAME_MAC_DISPLAY (f
));
5797 /* Synchronize to ensure Emacs knows the frame is visible
5798 before we do anything else. We do this loop with input not blocked
5799 so that incoming events are handled. */
5804 /* This must come after we set COUNT. */
5807 XSETFRAME (frame
, f
);
5809 /* Wait until the frame is visible. Process X events until a
5810 MapNotify event has been seen, or until we think we won't get a
5811 MapNotify at all.. */
5812 for (count
= input_signal_count
+ 10;
5813 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5815 /* Force processing of queued events. */
5818 /* Machines that do polling rather than SIGIO have been
5819 observed to go into a busy-wait here. So we'll fake an
5820 alarm signal to let the handler know that there's something
5821 to be read. We used to raise a real alarm, but it seems
5822 that the handler isn't always enabled here. This is
5824 if (input_polling_used ())
5826 /* It could be confusing if a real alarm arrives while
5827 processing the fake one. Turn it off and let the
5828 handler reset it. */
5829 extern void poll_for_input_1
P_ ((void));
5830 int old_poll_suppress_count
= poll_suppress_count
;
5831 poll_suppress_count
= 1;
5832 poll_for_input_1 ();
5833 poll_suppress_count
= old_poll_suppress_count
;
5836 /* See if a MapNotify event has been processed. */
5837 FRAME_SAMPLE_VISIBILITY (f
);
5842 /* Change from mapped state to withdrawn state. */
5844 /* Make the frame visible (mapped and not iconified). */
5847 x_make_frame_invisible (f
)
5850 /* A deactivate event does not occur when the last visible frame is
5851 made invisible. So if we clear the highlight here, it will not
5852 be rehighlighted when it is made visible. */
5854 /* Don't keep the highlight on an invisible frame. */
5855 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5856 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5861 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5862 that the current position of the window is user-specified, rather than
5863 program-specified, so that when the window is mapped again, it will be
5864 placed at the same location, without forcing the user to position it
5865 by hand again (they have already done that once for this window.) */
5866 x_wm_set_size_hint (f
, (long) 0, 1);
5868 HideWindow (FRAME_MAC_WINDOW (f
));
5872 #if !USE_CARBON_EVENTS
5873 mac_handle_visibility_change (f
);
5877 /* Change window state from mapped to iconified. */
5885 /* A deactivate event does not occur when the last visible frame is
5886 iconified. So if we clear the highlight here, it will not be
5887 rehighlighted when it is deiconified. */
5889 /* Don't keep the highlight on an invisible frame. */
5890 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5891 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5894 if (f
->async_iconified
)
5899 FRAME_SAMPLE_VISIBILITY (f
);
5901 if (! FRAME_VISIBLE_P (f
))
5902 ShowWindow (FRAME_MAC_WINDOW (f
));
5904 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
5909 error ("Can't notify window manager of iconification");
5911 #if !USE_CARBON_EVENTS
5912 mac_handle_visibility_change (f
);
5917 /* Free X resources of frame F. */
5920 x_free_frame_resources (f
)
5923 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5924 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5928 if (wp
!= tip_window
)
5929 remove_window_handler (wp
);
5932 if (wp
== tip_window
)
5933 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5934 closed' event. So we reset tip_window here. */
5937 free_frame_menubar (f
);
5939 if (FRAME_FACE_CACHE (f
))
5940 free_frame_faces (f
);
5944 if (FRAME_SIZE_HINTS (f
))
5945 xfree (FRAME_SIZE_HINTS (f
));
5947 xfree (f
->output_data
.mac
);
5948 f
->output_data
.mac
= NULL
;
5950 if (f
== dpyinfo
->x_focus_frame
)
5951 dpyinfo
->x_focus_frame
= 0;
5952 if (f
== dpyinfo
->x_focus_event_frame
)
5953 dpyinfo
->x_focus_event_frame
= 0;
5954 if (f
== dpyinfo
->x_highlight_frame
)
5955 dpyinfo
->x_highlight_frame
= 0;
5957 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5959 dpyinfo
->mouse_face_beg_row
5960 = dpyinfo
->mouse_face_beg_col
= -1;
5961 dpyinfo
->mouse_face_end_row
5962 = dpyinfo
->mouse_face_end_col
= -1;
5963 dpyinfo
->mouse_face_window
= Qnil
;
5964 dpyinfo
->mouse_face_deferred_gc
= 0;
5965 dpyinfo
->mouse_face_mouse_frame
= 0;
5972 /* Destroy the X window of frame F. */
5975 x_destroy_window (f
)
5978 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5980 x_free_frame_resources (f
);
5982 dpyinfo
->reference_count
--;
5986 /* Setting window manager hints. */
5988 /* Set the normal size hints for the window manager, for frame F.
5989 FLAGS is the flags word to use--or 0 meaning preserve the flags
5990 that the window now has.
5991 If USER_POSITION is nonzero, we set the USPosition
5992 flag (this is useful when FLAGS is 0). */
5994 x_wm_set_size_hint (f
, flags
, user_position
)
5999 int base_width
, base_height
, width_inc
, height_inc
;
6000 int min_rows
= 0, min_cols
= 0;
6001 XSizeHints
*size_hints
;
6003 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6004 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6005 width_inc
= FRAME_COLUMN_WIDTH (f
);
6006 height_inc
= FRAME_LINE_HEIGHT (f
);
6008 check_frame_size (f
, &min_rows
, &min_cols
);
6010 size_hints
= FRAME_SIZE_HINTS (f
);
6011 if (size_hints
== NULL
)
6013 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6014 bzero (size_hints
, sizeof (XSizeHints
));
6017 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6018 size_hints
->width_inc
= width_inc
;
6019 size_hints
->height_inc
= height_inc
;
6020 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6021 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6022 size_hints
->base_width
= base_width
;
6023 size_hints
->base_height
= base_height
;
6026 size_hints
->flags
= flags
;
6027 else if (user_position
)
6029 size_hints
->flags
&= ~ PPosition
;
6030 size_hints
->flags
|= USPosition
;
6034 #if 0 /* MAC_TODO: hide application instead of iconify? */
6035 /* Used for IconicState or NormalState */
6038 x_wm_set_window_state (f
, state
)
6042 #ifdef USE_X_TOOLKIT
6045 XtSetArg (al
[0], XtNinitialState
, state
);
6046 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6047 #else /* not USE_X_TOOLKIT */
6048 Window window
= FRAME_X_WINDOW (f
);
6050 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6051 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6053 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6054 #endif /* not USE_X_TOOLKIT */
6058 x_wm_set_icon_pixmap (f
, pixmap_id
)
6064 #ifndef USE_X_TOOLKIT
6065 Window window
= FRAME_X_WINDOW (f
);
6070 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6071 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6075 /* It seems there is no way to turn off use of an icon pixmap.
6076 The following line does it, only if no icon has yet been created,
6077 for some window managers. But with mwm it crashes.
6078 Some people say it should clear the IconPixmapHint bit in this case,
6079 but that doesn't work, and the X consortium said it isn't the
6080 right thing at all. Since there is no way to win,
6081 best to explicitly give up. */
6083 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6089 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6093 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6094 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6097 #else /* not USE_X_TOOLKIT */
6099 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6100 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6102 #endif /* not USE_X_TOOLKIT */
6105 #endif /* MAC_TODO */
6108 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6112 #if 0 /* MAC_TODO: no icons on Mac */
6113 #ifdef USE_X_TOOLKIT
6114 Window window
= XtWindow (f
->output_data
.x
->widget
);
6116 Window window
= FRAME_X_WINDOW (f
);
6119 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6120 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6121 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6123 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6124 #endif /* MAC_TODO */
6128 /***********************************************************************
6130 ***********************************************************************/
6132 /* An XLFD pattern is divided into blocks delimited by '*'. This
6133 structure holds information for each block. */
6134 struct xlfdpat_block
6136 /* Length of the pattern string in this block. Non-zero except for
6137 the first and the last blocks. */
6140 /* Pattern string except the last character in this block. The last
6141 character is replaced with NUL in order to use it as a
6143 unsigned char *pattern
;
6145 /* Last character of the pattern string. Must not be '?'. */
6146 unsigned char last_char
;
6148 /* One of the tables for the Boyer-Moore string search. It
6149 specifies the number of positions to proceed for each character
6150 with which the match fails. */
6153 /* The skip value for the last character in the above `skip' is
6154 assigned to `infinity' in order to simplify a loop condition.
6155 The original value is saved here. */
6161 /* Normalized pattern string. "Normalized" means that capital
6162 letters are lowered, blocks are not empty except the first and
6163 the last ones, and trailing '?'s in a block that is not the last
6164 one are moved to the next one. The last character in each block
6165 is replaced with NUL. */
6168 /* Number of characters except '*'s and trailing '?'s in the
6169 normalized pattern string. */
6172 /* Number of trailing '?'s in the normalized pattern string. */
6173 int trailing_anychars
;
6175 /* Number of blocks and information for each block. The latter is
6176 NULL if the pattern is exact (no '*' or '?' in it). */
6178 struct xlfdpat_block
*blocks
;
6182 xlfdpat_destroy (pat
)
6183 struct xlfdpat
*pat
;
6190 xfree (pat
->blocks
);
6197 static struct xlfdpat
*
6198 xlfdpat_create (pattern
)
6201 struct xlfdpat
*pat
;
6202 int nblocks
, i
, skip
;
6203 unsigned char last_char
, *p
, *q
, *anychar_head
;
6204 struct xlfdpat_block
*blk
;
6206 pat
= xmalloc (sizeof (struct xlfdpat
));
6210 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6211 if (pat
->buf
== NULL
)
6214 /* Normalize the pattern string and store it to `pat->buf'. */
6216 anychar_head
= NULL
;
6219 for (p
= pattern
; *p
; p
++)
6221 unsigned char c
= *p
;
6224 if (last_char
== '*')
6225 /* ...a** -> ...a* */
6229 if (last_char
== '?')
6230 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6231 /* ...*??* -> ...*?? */
6234 /* ...a??* -> ...a*?? */
6236 *anychar_head
++ = '*';
6243 if (last_char
!= '?')
6247 /* On Mac OS X 10.3, tolower also converts non-ASCII
6248 characters for some locales. */
6252 *q
++ = last_char
= c
;
6256 pat
->nblocks
= nblocks
;
6257 if (last_char
!= '?')
6258 pat
->trailing_anychars
= 0;
6261 pat
->trailing_anychars
= q
- anychar_head
;
6264 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6266 if (anychar_head
== NULL
&& nblocks
== 1)
6268 /* The pattern is exact. */
6273 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6274 if (pat
->blocks
== NULL
)
6277 /* Divide the normalized pattern into blocks. */
6279 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6284 blk
->len
= p
- blk
->pattern
;
6288 blk
->len
= q
- blk
->pattern
;
6290 /* Setup a table for the Boyer-Moore string search. */
6291 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6294 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6295 blk
->pattern
[blk
->len
- 1] = '\0';
6297 for (skip
= 1; skip
< blk
->len
; skip
++)
6298 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6301 for (i
= 0; i
< 256; i
++)
6302 blk
->skip
[i
] = skip
;
6304 p
= blk
->pattern
+ (blk
->len
- skip
);
6306 blk
->skip
[*p
++] = skip
;
6308 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6314 xlfdpat_destroy (pat
);
6319 xlfdpat_exact_p (pat
)
6320 struct xlfdpat
*pat
;
6322 return pat
->blocks
== NULL
;
6325 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6326 that the pattern in *BLK matches with its prefix. Return NULL
6327 there is no such strings. STRING must be lowered in advance. */
6330 xlfdpat_block_match_1 (blk
, string
, start_max
)
6331 struct xlfdpat_block
*blk
;
6332 unsigned char *string
;
6335 int start
, infinity
;
6336 unsigned char *p
, *s
;
6338 xassert (blk
->len
> 0);
6339 xassert (start_max
+ blk
->len
<= strlen (string
));
6340 xassert (blk
->last_char
!= '?');
6342 /* See the comments in the function `boyer_moore' (search.c) for the
6343 use of `infinity'. */
6344 infinity
= start_max
+ blk
->len
+ 1;
6345 blk
->skip
[blk
->last_char
] = infinity
;
6350 /* Check the last character of the pattern. */
6351 s
= string
+ blk
->len
- 1;
6354 start
+= blk
->skip
[*(s
+ start
)];
6356 while (start
<= start_max
);
6358 if (start
< infinity
)
6359 /* Couldn't find the last character. */
6362 /* No less than `infinity' means we could find the last
6363 character at `s[start - infinity]'. */
6366 /* Check the remaining characters. We prefer making no-'?'
6367 cases faster because the use of '?' is really rare. */
6372 while (*p
++ == *s
++)
6375 while (*(p
- 1) == '?');
6377 if (*(p
- 1) == '\0')
6379 return string
+ start
;
6382 start
+= blk
->last_char_skip
;
6384 while (start
<= start_max
);
6389 #define xlfdpat_block_match(b, s, m) \
6390 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6391 : xlfdpat_block_match_1 (b, s, m))
6393 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6394 matches with STRING. STRING must be lowered in advance. */
6397 xlfdpat_match (pat
, string
)
6398 struct xlfdpat
*pat
;
6399 unsigned char *string
;
6401 int str_len
, nblocks
, i
, start_max
;
6402 struct xlfdpat_block
*blk
;
6405 xassert (pat
->nblocks
> 0);
6407 if (xlfdpat_exact_p (pat
))
6408 return strcmp (pat
->buf
, string
) == 0;
6410 /* The number of the characters in the string must not be smaller
6411 than that in the pattern. */
6412 str_len
= strlen (string
);
6413 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6416 /* Chop off the trailing '?'s. */
6417 str_len
-= pat
->trailing_anychars
;
6419 /* The last block. When it is non-empty, it must match at the end
6421 nblocks
= pat
->nblocks
;
6422 blk
= pat
->blocks
+ (nblocks
- 1);
6424 /* The last block is also the first one. */
6425 return (str_len
== blk
->len
6426 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6427 else if (blk
->len
!= 0)
6428 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6431 /* The first block. When it is non-empty, it must match at the
6432 beginning of the string. */
6436 s
= xlfdpat_block_match (blk
, string
, 0);
6439 string
= s
+ blk
->len
;
6442 /* The rest of the blocks. */
6443 start_max
= str_len
- pat
->nchars
;
6444 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6446 s
= xlfdpat_block_match (blk
, string
, start_max
);
6449 start_max
-= s
- string
;
6450 string
= s
+ blk
->len
;
6457 /***********************************************************************
6459 ***********************************************************************/
6461 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6464 x_get_font_info (f
, font_idx
)
6468 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6471 /* the global font name table */
6472 static char **font_name_table
= NULL
;
6473 static int font_name_table_size
= 0;
6474 static int font_name_count
= 0;
6476 /* Alist linking font family names to Font Manager font family
6477 references (which can also be used as QuickDraw font IDs). We use
6478 an alist because hash tables are not ready when the terminal frame
6479 for Mac OS Classic is created. */
6480 static Lisp_Object fm_font_family_alist
;
6482 /* Hash table linking font family names to ATSU font IDs. */
6483 static Lisp_Object atsu_font_id_hash
;
6486 /* Alist linking character set strings to Mac text encoding and Emacs
6488 static Lisp_Object Vmac_charset_info_alist
;
6491 create_text_encoding_info_alist ()
6493 Lisp_Object result
= Qnil
, rest
;
6495 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6497 Lisp_Object charset_info
= XCAR (rest
);
6498 Lisp_Object charset
, coding_system
, text_encoding
;
6499 Lisp_Object existing_info
;
6501 if (!(CONSP (charset_info
)
6502 && STRINGP (charset
= XCAR (charset_info
))
6503 && CONSP (XCDR (charset_info
))
6504 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6505 && CONSP (XCDR (XCDR (charset_info
)))
6506 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6509 existing_info
= assq_no_quit (text_encoding
, result
);
6510 if (NILP (existing_info
))
6511 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6514 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6515 XSETCDR (XCDR (existing_info
),
6516 Fcons (charset
, XCDR (XCDR (existing_info
))));
6524 decode_mac_font_name (name
, size
, coding_system
)
6527 Lisp_Object coding_system
;
6529 struct coding_system coding
;
6532 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6534 for (p
= name
; *p
; p
++)
6535 if (!isascii (*p
) || iscntrl (*p
))
6540 setup_coding_system (coding_system
, &coding
);
6541 coding
.src_multibyte
= 0;
6542 coding
.dst_multibyte
= 1;
6543 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6544 coding
.composing
= COMPOSITION_DISABLED
;
6545 buf
= (char *) alloca (size
);
6547 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6548 bcopy (buf
, name
, coding
.produced
);
6549 name
[coding
.produced
] = '\0';
6553 /* If there's just one occurrence of '-' in the family name, it is
6554 replaced with '_'. (More than one occurrence of '-' means a
6555 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6556 p
= strchr (name
, '-');
6557 if (p
&& strchr (p
+ 1, '-') == NULL
)
6560 for (p
= name
; *p
; p
++)
6561 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6562 for some locales. */
6569 mac_to_x_fontname (name
, size
, style
, charset
)
6577 char xf
[256], *result
;
6580 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6584 strcpy(foundry
, "Apple");
6585 strcpy(family
, name
);
6588 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6589 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6590 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6592 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6593 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6594 for (p
= result
; *p
; p
++)
6595 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6596 for some locales. */
6603 /* Parse fully-specified and instantiated X11 font spec XF, and store
6604 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6605 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6606 caller must allocate at least 256 and 32 bytes respectively. For
6607 ordinary Mac fonts, the value stored to FAMILY should just be their
6608 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6609 intlfonts collection contain their charset designation in their
6610 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6611 types of font names are handled accordingly. */
6613 const int kDefaultFontSize
= 12;
6616 parse_x_font_name (xf
, family
, size
, style
, charset
)
6622 Str31 foundry
, weight
;
6623 int point_size
, avgwidth
;
6626 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6627 foundry
, family
, weight
, slant
, size
,
6628 &point_size
, &avgwidth
, charset
) != 8
6629 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6630 foundry
, family
, weight
, slant
, size
,
6631 &point_size
, &avgwidth
, charset
) != 8)
6637 *size
= point_size
/ 10;
6638 else if (avgwidth
> 0)
6639 *size
= avgwidth
/ 10;
6642 *size
= kDefaultFontSize
;
6645 if (strcmp (weight
, "bold") == 0)
6650 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6652 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6654 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6656 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6657 but take overlap into account. */
6658 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6659 memcpy (family
, foundry
, foundry_len
);
6660 family
[foundry_len
] = '-';
6661 family
[foundry_len
+ 1 + family_len
] = '-';
6662 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6668 for (p
= family
; *p
; p
++)
6669 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6670 for some locales. */
6679 add_font_name_table_entry (char *font_name
)
6681 if (font_name_table_size
== 0)
6683 font_name_table_size
= 256;
6684 font_name_table
= (char **)
6685 xmalloc (font_name_table_size
* sizeof (char *));
6687 else if (font_name_count
+ 1 >= font_name_table_size
)
6689 font_name_table_size
*= 2;
6690 font_name_table
= (char **)
6691 xrealloc (font_name_table
,
6692 font_name_table_size
* sizeof (char *));
6695 font_name_table
[font_name_count
++] = font_name
;
6698 /* Sets up the table font_name_table to contain the list of all fonts
6699 in the system the first time the table is used so that the Resource
6700 Manager need not be accessed every time this information is
6704 init_font_name_table ()
6706 #if TARGET_API_MAC_CARBON
6707 FMFontFamilyIterator ffi
;
6708 FMFontFamilyInstanceIterator ffii
;
6710 Lisp_Object text_encoding_info_alist
;
6711 struct gcpro gcpro1
;
6713 text_encoding_info_alist
= create_text_encoding_info_alist ();
6716 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6717 text_encoding_info_alist
)))
6720 ItemCount nfonts
, i
;
6721 ATSUFontID
*font_ids
= NULL
;
6722 Ptr name
, prev_name
= NULL
;
6726 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6727 make_float (DEFAULT_REHASH_SIZE
),
6728 make_float (DEFAULT_REHASH_THRESHOLD
),
6730 err
= ATSUFontCount (&nfonts
);
6732 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6734 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6736 for (i
= 0; i
< nfonts
; i
++)
6738 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6739 kFontMacintoshPlatform
, kFontNoScript
,
6740 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6743 name
= xmalloc (name_len
+ 1);
6746 name
[name_len
] = '\0';
6747 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6748 kFontMacintoshPlatform
, kFontNoScript
,
6749 kFontNoLanguage
, name_len
, name
,
6752 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6755 && (prev_name
== NULL
6756 || strcmp (name
, prev_name
) != 0))
6758 static char *cs
= "iso10646-1";
6760 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6762 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6764 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6766 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6767 italic
| bold
, cs
));
6768 Fputhash (make_unibyte_string (name
, name_len
),
6769 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
6783 /* Create a dummy instance iterator here to avoid creating and
6784 destroying it in the loop. */
6785 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6787 /* Create an iterator to enumerate the font families. */
6788 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6791 FMDisposeFontFamilyInstanceIterator (&ffii
);
6795 GCPRO1 (text_encoding_info_alist
);
6797 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6803 TextEncoding encoding
;
6804 TextEncodingBase sc
;
6805 Lisp_Object text_encoding_info
;
6807 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6813 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6815 sc
= GetTextEncodingBase (encoding
);
6816 text_encoding_info
= assq_no_quit (make_number (sc
),
6817 text_encoding_info_alist
);
6818 if (NILP (text_encoding_info
))
6819 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6820 text_encoding_info_alist
);
6821 decode_mac_font_name (name
, sizeof (name
),
6822 XCAR (XCDR (text_encoding_info
)));
6823 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
6825 fm_font_family_alist
);
6827 /* Point the instance iterator at the current font family. */
6828 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
6831 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
6834 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6836 if (size
> 0 || style
== normal
)
6837 for (; !NILP (rest
); rest
= XCDR (rest
))
6839 char *cs
= SDATA (XCAR (rest
));
6843 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6845 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6847 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6849 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6855 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
6864 /* Dispose of the iterators. */
6865 FMDisposeFontFamilyIterator (&ffi
);
6866 FMDisposeFontFamilyInstanceIterator (&ffii
);
6867 #else /* !TARGET_API_MAC_CARBON */
6869 SInt16 fontnum
, old_fontnum
;
6870 int num_mac_fonts
= CountResources('FOND');
6872 Handle font_handle
, font_handle_2
;
6873 short id
, scriptcode
;
6876 struct FontAssoc
*fat
;
6877 struct AsscEntry
*assc_entry
;
6878 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
6879 struct gcpro gcpro1
;
6881 GetPort (&port
); /* save the current font number used */
6882 old_fontnum
= port
->txFont
;
6884 text_encoding_info_alist
= create_text_encoding_info_alist ();
6886 GCPRO1 (text_encoding_info_alist
);
6888 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
6890 font_handle
= GetIndResource ('FOND', i
);
6894 GetResInfo (font_handle
, &id
, &type
, name
);
6895 GetFNum (name
, &fontnum
);
6901 scriptcode
= FontToScript (fontnum
);
6902 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
6903 text_encoding_info_alist
);
6904 if (NILP (text_encoding_info
))
6905 text_encoding_info
= assq_no_quit (make_number (smRoman
),
6906 text_encoding_info_alist
);
6907 decode_mac_font_name (name
, sizeof (name
),
6908 XCAR (XCDR (text_encoding_info
)));
6909 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
6910 make_number (fontnum
)),
6911 fm_font_family_alist
);
6914 HLock (font_handle
);
6916 if (GetResourceSizeOnDisk (font_handle
)
6917 >= sizeof (struct FamRec
))
6919 fat
= (struct FontAssoc
*) (*font_handle
6920 + sizeof (struct FamRec
));
6922 = (struct AsscEntry
*) (*font_handle
6923 + sizeof (struct FamRec
)
6924 + sizeof (struct FontAssoc
));
6926 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
6928 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
6930 for (; !NILP (rest
); rest
= XCDR (rest
))
6932 char *cs
= SDATA (XCAR (rest
));
6934 add_font_name_table_entry (mac_to_x_fontname (name
,
6935 assc_entry
->fontSize
,
6936 assc_entry
->fontStyle
,
6942 HUnlock (font_handle
);
6943 font_handle_2
= GetNextFOND (font_handle
);
6944 ReleaseResource (font_handle
);
6945 font_handle
= font_handle_2
;
6947 while (ResError () == noErr
&& font_handle
);
6952 TextFont (old_fontnum
);
6953 #endif /* !TARGET_API_MAC_CARBON */
6958 mac_clear_font_name_table ()
6962 for (i
= 0; i
< font_name_count
; i
++)
6963 xfree (font_name_table
[i
]);
6964 xfree (font_name_table
);
6965 font_name_table
= NULL
;
6966 font_name_table_size
= font_name_count
= 0;
6967 fm_font_family_alist
= Qnil
;
6971 enum xlfd_scalable_field_index
6973 XLFD_SCL_PIXEL_SIZE
,
6974 XLFD_SCL_POINT_SIZE
,
6979 static int xlfd_scalable_fields
[] =
6988 mac_do_list_fonts (pattern
, maxnames
)
6993 Lisp_Object font_list
= Qnil
;
6994 struct xlfdpat
*pat
;
6996 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
6999 if (font_name_table
== NULL
) /* Initialize when first used. */
7000 init_font_name_table ();
7002 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7005 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7006 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7007 fonts are scaled according to the specified size. */
7010 field
= xlfd_scalable_fields
;
7018 if ('0' <= *ptr
&& *ptr
<= '9')
7020 *val
= *ptr
++ - '0';
7021 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7022 *val
= *val
* 10 + *ptr
++ - '0';
7029 ptr
= strchr (ptr
, '-');
7032 while (ptr
&& i
< 14);
7034 if (i
== 14 && ptr
== NULL
)
7036 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7037 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7038 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7039 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7041 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7042 scl_val
[XLFD_SCL_POINT_SIZE
] =
7043 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7044 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7046 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7047 scl_val
[XLFD_SCL_AVGWIDTH
] =
7048 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7049 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7053 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7055 pat
= xlfdpat_create (pattern
);
7059 exact
= xlfdpat_exact_p (pat
);
7061 for (i
= 0; i
< font_name_count
; i
++)
7063 if (xlfdpat_match (pat
, font_name_table
[i
]))
7065 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7066 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7069 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7070 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7072 int former_len
= ptr
- font_name_table
[i
];
7074 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7077 memcpy (scaled
, font_name_table
[i
], former_len
);
7078 sprintf (scaled
+ former_len
,
7079 "-%d-%d-72-72-m-%d-%s",
7080 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7081 scl_val
[XLFD_SCL_POINT_SIZE
],
7082 scl_val
[XLFD_SCL_AVGWIDTH
],
7083 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7085 if (xlfdpat_match (pat
, scaled
))
7087 font_list
= Fcons (build_string (scaled
), font_list
);
7089 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7097 xlfdpat_destroy (pat
);
7102 /* Return a list of names of available fonts matching PATTERN on frame F.
7104 Frame F null means we have not yet created any frame on Mac, and
7105 consult the first display in x_display_list. MAXNAMES sets a limit
7106 on how many fonts to match. */
7109 x_list_fonts (f
, pattern
, size
, maxnames
)
7111 Lisp_Object pattern
;
7114 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7115 struct mac_display_info
*dpyinfo
7116 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7118 xassert (size
<= 0);
7120 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7121 if (NILP (patterns
))
7122 patterns
= Fcons (pattern
, Qnil
);
7124 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7126 pattern
= XCAR (patterns
);
7128 if (!STRINGP (pattern
))
7131 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7132 key
= Fcons (pattern
, make_number (maxnames
));
7134 list
= Fassoc (key
, tem
);
7137 list
= Fcdr_safe (list
);
7138 /* We have a cashed list. Don't have to get the list again. */
7143 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7146 /* MAC_TODO: add code for matching outline fonts here */
7148 /* Now store the result in the cache. */
7149 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7150 Fcons (Fcons (key
, list
),
7151 XCAR (XCDR (dpyinfo
->name_list_element
))));
7154 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7163 /* Check that FONT is valid on frame F. It is if it can be found in F's
7167 x_check_font (f
, font
)
7172 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7174 xassert (font
!= NULL
);
7176 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7177 if (dpyinfo
->font_table
[i
].name
7178 && font
== dpyinfo
->font_table
[i
].font
)
7181 xassert (i
< dpyinfo
->n_fonts
);
7184 #endif /* GLYPH_DEBUG != 0 */
7186 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7187 Note: There are (broken) X fonts out there with invalid XFontStruct
7188 min_bounds contents. For example, handa@etl.go.jp reports that
7189 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7190 have font->min_bounds.width == 0. */
7193 x_font_min_bounds (font
, w
, h
)
7194 MacFontStruct
*font
;
7197 *h
= FONT_HEIGHT (font
);
7198 *w
= font
->min_bounds
.width
;
7202 /* Compute the smallest character width and smallest font height over
7203 all fonts available on frame F. Set the members smallest_char_width
7204 and smallest_font_height in F's x_display_info structure to
7205 the values computed. Value is non-zero if smallest_font_height or
7206 smallest_char_width become smaller than they were before. */
7209 x_compute_min_glyph_bounds (f
)
7213 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7214 MacFontStruct
*font
;
7215 int old_width
= dpyinfo
->smallest_char_width
;
7216 int old_height
= dpyinfo
->smallest_font_height
;
7218 dpyinfo
->smallest_font_height
= 100000;
7219 dpyinfo
->smallest_char_width
= 100000;
7221 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7222 if (dpyinfo
->font_table
[i
].name
)
7224 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7227 font
= (MacFontStruct
*) fontp
->font
;
7228 xassert (font
!= (MacFontStruct
*) ~0);
7229 x_font_min_bounds (font
, &w
, &h
);
7231 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7232 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7235 xassert (dpyinfo
->smallest_char_width
> 0
7236 && dpyinfo
->smallest_font_height
> 0);
7238 return (dpyinfo
->n_fonts
== 1
7239 || dpyinfo
->smallest_char_width
< old_width
7240 || dpyinfo
->smallest_font_height
< old_height
);
7244 /* Determine whether given string is a fully-specified XLFD: all 14
7245 fields are present, none is '*'. */
7248 is_fully_specified_xlfd (char *p
)
7256 for (i
= 0; i
< 13; i
++)
7258 q
= strchr (p
+ 1, '-');
7261 if (q
- p
== 2 && *(p
+ 1) == '*')
7266 if (strchr (p
+ 1, '-') != NULL
)
7269 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7276 /* XLoadQueryFont creates and returns an internal representation for a
7277 font in a MacFontStruct struct. There is really no concept
7278 corresponding to "loading" a font on the Mac. But we check its
7279 existence and find the font number and all other information for it
7280 and store them in the returned MacFontStruct. */
7282 static MacFontStruct
*
7283 XLoadQueryFont (Display
*dpy
, char *fontname
)
7285 int i
, size
, char_width
;
7291 ATSUStyle mac_style
= NULL
;
7294 #if TARGET_API_MAC_CARBON
7295 TextEncoding encoding
;
7300 MacFontStruct
*font
;
7302 if (is_fully_specified_xlfd (fontname
))
7306 Lisp_Object matched_fonts
;
7308 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7309 if (NILP (matched_fonts
))
7311 name
= SDATA (XCAR (matched_fonts
));
7314 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7318 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7321 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7322 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7323 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7324 sizeof (Boolean
), sizeof (Boolean
)};
7325 static ATSUFontID font_id
;
7326 static Fixed size_fixed
;
7327 static Boolean bold_p
, italic_p
;
7328 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7329 &bold_p
, &italic_p
};
7330 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
};
7331 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
};
7332 Lisp_Object font_id_cons
;
7334 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7335 atsu_font_id_hash
, Qnil
);
7336 if (NILP (font_id_cons
))
7338 font_id
= cons_to_long (font_id_cons
);
7339 size_fixed
= Long2Fix (size
);
7340 bold_p
= (fontface
& bold
) != 0;
7341 italic_p
= (fontface
& italic
) != 0;
7342 err
= ATSUCreateStyle (&mac_style
);
7345 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7349 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7350 tags
, sizes
, values
);
7352 scriptcode
= kTextEncodingMacUnicode
;
7357 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7361 fontnum
= XINT (XCDR (tmp
));
7362 #if TARGET_API_MAC_CARBON
7363 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7365 scriptcode
= GetTextEncodingBase (encoding
);
7367 scriptcode
= FontToScript (fontnum
);
7371 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7373 font
->mac_fontnum
= fontnum
;
7374 font
->mac_fontsize
= size
;
7375 font
->mac_fontface
= fontface
;
7376 font
->mac_scriptcode
= scriptcode
;
7378 font
->mac_style
= mac_style
;
7381 /* Apple Japanese (SJIS) font is listed as both
7382 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7383 (Roman script) in init_font_name_table (). The latter should be
7384 treated as a one-byte font. */
7385 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7386 font
->mac_scriptcode
= smRoman
;
7388 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7391 if (font
->mac_style
)
7394 ATSUTextLayout text_layout
;
7396 Rect char_bounds
, min_bounds
, max_bounds
;
7397 int min_width
, max_width
;
7398 ATSTrapezoid glyph_bounds
;
7400 font
->per_char
= xmalloc (sizeof (XCharStruct
) * 0x10000);
7401 if (font
->per_char
== NULL
)
7403 mac_unload_font (&one_mac_display_info
, font
);
7406 bzero (font
->per_char
, sizeof (XCharStruct
) * 0x10000);
7408 err
= atsu_get_text_layout_with_text_ptr (&c
, 1,
7413 mac_unload_font (&one_mac_display_info
, font
);
7417 for (c
= 0x20; c
<= 0x7e; c
++)
7419 err
= ATSUClearLayoutCache (text_layout
, kATSUFromTextBeginning
);
7421 err
= ATSUMeasureTextImage (text_layout
,
7422 kATSUFromTextBeginning
, kATSUToTextEnd
,
7423 0, 0, &char_bounds
);
7425 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
7426 kATSUFromTextBeginning
, kATSUToTextEnd
,
7427 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
7428 kATSUseFractionalOrigins
,
7430 kATSUseDeviceOrigins
,
7432 1, &glyph_bounds
, NULL
);
7435 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
7436 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
7438 char_width
= Fix2Long (glyph_bounds
.upperRight
.x
7439 - glyph_bounds
.upperLeft
.x
);
7440 STORE_XCHARSTRUCT (font
->per_char
[c
],
7441 char_width
, char_bounds
);
7444 min_width
= max_width
= char_width
;
7445 min_bounds
= max_bounds
= char_bounds
;
7446 font
->ascent
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
7447 font
->descent
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
7453 min_width
= min (min_width
, char_width
);
7454 max_width
= max (max_width
, char_width
);
7456 if (!EmptyRect (&char_bounds
))
7458 SetRect (&min_bounds
,
7459 max (min_bounds
.left
, char_bounds
.left
),
7460 max (min_bounds
.top
, char_bounds
.top
),
7461 min (min_bounds
.right
, char_bounds
.right
),
7462 min (min_bounds
.bottom
, char_bounds
.bottom
));
7463 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7468 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7469 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7471 font
->min_byte1
= 0;
7472 font
->max_byte1
= 0xff;
7473 font
->min_char_or_byte2
= 0;
7474 font
->max_char_or_byte2
= 0xff;
7480 SInt16 old_fontnum
, old_fontsize
;
7482 FontInfo the_fontinfo
;
7483 int is_two_byte_font
;
7485 /* Save the current font number used. */
7487 #if TARGET_API_MAC_CARBON
7488 old_fontnum
= GetPortTextFont (port
);
7489 old_fontsize
= GetPortTextSize (port
);
7490 old_fontface
= GetPortTextFace (port
);
7492 old_fontnum
= port
->txFont
;
7493 old_fontsize
= port
->txSize
;
7494 old_fontface
= port
->txFace
;
7499 TextFace (fontface
);
7501 GetFontInfo (&the_fontinfo
);
7503 font
->ascent
= the_fontinfo
.ascent
;
7504 font
->descent
= the_fontinfo
.descent
;
7506 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7507 || font
->mac_scriptcode
== smTradChinese
7508 || font
->mac_scriptcode
== smSimpChinese
7509 || font
->mac_scriptcode
== smKorean
);
7511 if (is_two_byte_font
)
7513 font
->min_byte1
= 0xa1;
7514 font
->max_byte1
= 0xfe;
7515 font
->min_char_or_byte2
= 0xa1;
7516 font
->max_char_or_byte2
= 0xfe;
7518 /* Use the width of an "ideographic space" of that font
7519 because the_fontinfo.widMax returns the wrong width for
7521 switch (font
->mac_scriptcode
)
7524 font
->min_byte1
= 0x81;
7525 font
->max_byte1
= 0xfc;
7526 font
->min_char_or_byte2
= 0x40;
7527 font
->max_char_or_byte2
= 0xfc;
7528 char_width
= StringWidth("\p\x81\x40");
7531 font
->min_char_or_byte2
= 0x40;
7532 char_width
= StringWidth("\p\xa1\x40");
7535 char_width
= StringWidth("\p\xa1\xa1");
7538 char_width
= StringWidth("\p\xa1\xa1");
7544 font
->min_byte1
= font
->max_byte1
= 0;
7545 font
->min_char_or_byte2
= 0x20;
7546 font
->max_char_or_byte2
= 0xff;
7548 /* Do this instead of use the_fontinfo.widMax, which
7549 incorrectly returns 15 for 12-point Monaco! */
7550 char_width
= CharWidth ('m');
7553 if (is_two_byte_font
)
7555 font
->per_char
= NULL
;
7557 if (fontface
& italic
)
7558 font
->max_bounds
.rbearing
= char_width
+ 1;
7560 font
->max_bounds
.rbearing
= char_width
;
7561 font
->max_bounds
.lbearing
= 0;
7562 font
->max_bounds
.width
= char_width
;
7563 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7564 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7566 font
->min_bounds
= font
->max_bounds
;
7570 int c
, min_width
, max_width
;
7571 Rect char_bounds
, min_bounds
, max_bounds
;
7574 font
->per_char
= xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7575 bzero (font
->per_char
, sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7577 min_width
= max_width
= char_width
;
7578 SetRect (&min_bounds
, -32767, -32767, 32767, 32767);
7579 SetRect (&max_bounds
, 0, 0, 0, 0);
7580 for (c
= 0x20; c
<= 0xff; c
++)
7583 char_width
= CharWidth (ch
);
7584 QDTextBounds (1, &ch
, &char_bounds
);
7585 STORE_XCHARSTRUCT (font
->per_char
[c
- 0x20],
7586 char_width
, char_bounds
);
7587 /* Some Japanese fonts (in SJIS encoding) return 0 as
7588 the character width of 0x7f. */
7591 min_width
= min (min_width
, char_width
);
7592 max_width
= max (max_width
, char_width
);
7594 if (!EmptyRect (&char_bounds
))
7596 SetRect (&min_bounds
,
7597 max (min_bounds
.left
, char_bounds
.left
),
7598 max (min_bounds
.top
, char_bounds
.top
),
7599 min (min_bounds
.right
, char_bounds
.right
),
7600 min (min_bounds
.bottom
, char_bounds
.bottom
));
7601 UnionRect (&max_bounds
, &char_bounds
, &max_bounds
);
7604 STORE_XCHARSTRUCT (font
->min_bounds
, min_width
, min_bounds
);
7605 STORE_XCHARSTRUCT (font
->max_bounds
, max_width
, max_bounds
);
7606 if (min_width
== max_width
7607 && max_bounds
.left
>= 0 && max_bounds
.right
<= max_width
)
7609 /* Fixed width and no overhangs. */
7610 xfree (font
->per_char
);
7611 font
->per_char
= NULL
;
7615 /* Restore previous font number, size and face. */
7616 TextFont (old_fontnum
);
7617 TextSize (old_fontsize
);
7618 TextFace (old_fontface
);
7626 mac_unload_font (dpyinfo
, font
)
7627 struct mac_display_info
*dpyinfo
;
7630 xfree (font
->full_name
);
7632 xfree (font
->per_char
);
7634 if (font
->mac_style
)
7635 ATSUDisposeStyle (font
->mac_style
);
7641 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7642 pointer to the structure font_info while allocating it dynamically.
7643 If SIZE is 0, load any size of font.
7644 If loading is failed, return NULL. */
7647 x_load_font (f
, fontname
, size
)
7649 register char *fontname
;
7652 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7653 Lisp_Object font_names
;
7655 /* Get a list of all the fonts that match this name. Once we
7656 have a list of matching fonts, we compare them against the fonts
7657 we already have by comparing names. */
7658 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7660 if (!NILP (font_names
))
7665 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7666 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7667 if (dpyinfo
->font_table
[i
].name
7668 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7669 SDATA (XCAR (tail
)))
7670 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7671 SDATA (XCAR (tail
)))))
7672 return (dpyinfo
->font_table
+ i
);
7677 /* Load the font and add it to the table. */
7680 struct MacFontStruct
*font
;
7681 struct font_info
*fontp
;
7682 unsigned long value
;
7685 fontname
= (char *) SDATA (XCAR (font_names
));
7688 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7693 /* Find a free slot in the font table. */
7694 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7695 if (dpyinfo
->font_table
[i
].name
== NULL
)
7698 /* If no free slot found, maybe enlarge the font table. */
7699 if (i
== dpyinfo
->n_fonts
7700 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7703 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7704 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7706 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7709 fontp
= dpyinfo
->font_table
+ i
;
7710 if (i
== dpyinfo
->n_fonts
)
7713 /* Now fill in the slots of *FONTP. */
7715 bzero (fontp
, sizeof (*fontp
));
7717 fontp
->font_idx
= i
;
7718 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7719 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7721 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7723 /* Fixed width font. */
7724 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7731 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7732 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7734 fontp
->space_width
= pcm
->width
;
7736 fontp
->space_width
= FONT_WIDTH (font
);
7740 int width
= pcm
->width
;
7741 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7742 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7743 width
+= pcm
->width
;
7744 fontp
->average_width
= width
/ 95;
7747 fontp
->average_width
= FONT_WIDTH (font
);
7750 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7751 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7753 fontp
->size
= font
->max_bounds
.width
;
7754 fontp
->height
= FONT_HEIGHT (font
);
7756 /* For some font, ascent and descent in max_bounds field is
7757 larger than the above value. */
7758 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7759 if (max_height
> fontp
->height
)
7760 fontp
->height
= max_height
;
7763 /* The slot `encoding' specifies how to map a character
7764 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7765 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7766 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7767 2:0xA020..0xFF7F). For the moment, we don't know which charset
7768 uses this font. So, we set information in fontp->encoding[1]
7769 which is never used by any charset. If mapping can't be
7770 decided, set FONT_ENCODING_NOT_DECIDED. */
7771 if (font
->mac_scriptcode
== smJapanese
)
7772 fontp
->encoding
[1] = 4;
7776 = (font
->max_byte1
== 0
7778 ? (font
->min_char_or_byte2
< 0x80
7779 ? (font
->max_char_or_byte2
< 0x80
7780 ? 0 /* 0x20..0x7F */
7781 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
7782 : 1) /* 0xA0..0xFF */
7784 : (font
->min_byte1
< 0x80
7785 ? (font
->max_byte1
< 0x80
7786 ? (font
->min_char_or_byte2
< 0x80
7787 ? (font
->max_char_or_byte2
< 0x80
7788 ? 0 /* 0x2020..0x7F7F */
7789 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
7790 : 3) /* 0x20A0..0x7FFF */
7791 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
7792 : (font
->min_char_or_byte2
< 0x80
7793 ? (font
->max_char_or_byte2
< 0x80
7794 ? 2 /* 0xA020..0xFF7F */
7795 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
7796 : 1))); /* 0xA0A0..0xFFFF */
7799 #if 0 /* MAC_TODO: fill these out with more reasonably values */
7800 fontp
->baseline_offset
7801 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
7802 ? (long) value
: 0);
7803 fontp
->relative_compose
7804 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
7805 ? (long) value
: 0);
7806 fontp
->default_ascent
7807 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
7808 ? (long) value
: 0);
7810 fontp
->baseline_offset
= 0;
7811 fontp
->relative_compose
= 0;
7812 fontp
->default_ascent
= 0;
7815 /* Set global flag fonts_changed_p to non-zero if the font loaded
7816 has a character with a smaller width than any other character
7817 before, or if the font loaded has a smaller height than any
7818 other font loaded before. If this happens, it will make a
7819 glyph matrix reallocation necessary. */
7820 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
7827 /* Return a pointer to struct font_info of a font named FONTNAME for
7828 frame F. If no such font is loaded, return NULL. */
7831 x_query_font (f
, fontname
)
7833 register char *fontname
;
7835 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7838 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7839 if (dpyinfo
->font_table
[i
].name
7840 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
7841 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
7842 return (dpyinfo
->font_table
+ i
);
7847 /* Find a CCL program for a font specified by FONTP, and set the member
7848 `encoder' of the structure. */
7851 x_find_ccl_program (fontp
)
7852 struct font_info
*fontp
;
7854 Lisp_Object list
, elt
;
7856 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
7860 && STRINGP (XCAR (elt
))
7861 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
7867 struct ccl_program
*ccl
7868 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
7870 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
7873 fontp
->font_encoder
= ccl
;
7879 /* The Mac Event loop code */
7881 #if !TARGET_API_MAC_CARBON
7883 #include <Quickdraw.h>
7884 #include <Balloons.h>
7885 #include <Devices.h>
7887 #include <Gestalt.h>
7889 #include <Processes.h>
7891 #include <ToolUtils.h>
7892 #include <TextUtils.h>
7893 #include <Dialogs.h>
7896 #include <Resources.h>
7901 #endif /* ! TARGET_API_MAC_CARBON */
7906 #define WINDOW_RESOURCE 128
7907 #define TERM_WINDOW_RESOURCE 129
7909 #define DEFAULT_NUM_COLS 80
7911 #define MIN_DOC_SIZE 64
7912 #define MAX_DOC_SIZE 32767
7914 #define EXTRA_STACK_ALLOC (256 * 1024)
7916 #define ARGV_STRING_LIST_ID 129
7917 #define ABOUT_ALERT_ID 128
7918 #define RAM_TOO_LARGE_ALERT_ID 129
7920 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7921 Lisp_Object Qreverse
;
7923 /* True if using command key as meta key. */
7924 Lisp_Object Vmac_command_key_is_meta
;
7926 /* Modifier associated with the option key, or nil for normal behavior. */
7927 Lisp_Object Vmac_option_modifier
;
7929 /* True if the ctrl and meta keys should be reversed. */
7930 Lisp_Object Vmac_reverse_ctrl_meta
;
7932 /* True if the option and command modifiers should be used to emulate
7933 a three button mouse */
7934 Lisp_Object Vmac_emulate_three_button_mouse
;
7936 #if USE_CARBON_EVENTS
7937 /* True if the mouse wheel button (i.e. button 4) should map to
7938 mouse-2, instead of mouse-3. */
7939 Lisp_Object Vmac_wheel_button_is_mouse_2
;
7941 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7942 for processing before Emacs sees it. */
7943 Lisp_Object Vmac_pass_command_to_system
;
7945 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7946 for processing before Emacs sees it. */
7947 Lisp_Object Vmac_pass_control_to_system
;
7950 /* Points to the variable `inev' in the function XTread_socket. It is
7951 used for passing an input event to the function back from
7952 Carbon/Apple event handlers. */
7953 static struct input_event
*read_socket_inev
= NULL
;
7955 /* Set in term/mac-win.el to indicate that event loop can now generate
7956 drag and drop events. */
7957 Lisp_Object Qmac_ready_for_drag_n_drop
;
7959 Point saved_menu_event_location
;
7962 static void init_required_apple_events (void);
7964 do_ae_open_application (const AppleEvent
*, AppleEvent
*, long);
7966 do_ae_print_documents (const AppleEvent
*, AppleEvent
*, long);
7967 static pascal OSErr
do_ae_open_documents (AppleEvent
*, AppleEvent
*, long);
7968 static pascal OSErr
do_ae_quit_application (AppleEvent
*, AppleEvent
*, long);
7970 #if TARGET_API_MAC_CARBON
7972 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
7973 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
7974 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
7975 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
7978 static Lisp_Object Qapplication
, Qabout
;
7979 #if USE_CARBON_EVENTS
7981 extern void init_service_handler ();
7982 static Lisp_Object Qpreferences
, Qservices
, Qpaste
, Qperform
;
7984 /* Window Event Handler */
7985 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
7988 OSErr
install_window_handler (WindowPtr
);
7990 extern void init_emacs_passwd_dir ();
7991 extern int emacs_main (int, char **, char **);
7993 extern void initialize_applescript();
7994 extern void terminate_applescript();
7997 #if USE_CARBON_EVENTS
7998 mac_to_emacs_modifiers (UInt32 mods
)
8000 mac_to_emacs_modifiers (EventModifiers mods
)
8003 unsigned int result
= 0;
8004 if (mods
& macShiftKey
)
8005 result
|= shift_modifier
;
8006 if (mods
& macCtrlKey
)
8007 result
|= ctrl_modifier
;
8008 if (mods
& macMetaKey
)
8009 result
|= meta_modifier
;
8010 if (NILP (Vmac_command_key_is_meta
) && (mods
& macAltKey
))
8011 result
|= alt_modifier
;
8012 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8013 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8015 result
|= XUINT(val
);
8022 mac_get_emulated_btn ( UInt32 modifiers
)
8025 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8026 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8027 if (modifiers
& cmdKey
)
8028 result
= cmdIs3
? 2 : 1;
8029 else if (modifiers
& optionKey
)
8030 result
= cmdIs3
? 1 : 2;
8035 #if USE_CARBON_EVENTS
8036 /* Obtains the event modifiers from the event ref and then calls
8037 mac_to_emacs_modifiers. */
8039 mac_event_to_emacs_modifiers (EventRef eventRef
)
8042 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8043 sizeof (UInt32
), NULL
, &mods
);
8044 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8045 GetEventClass(eventRef
) == kEventClassMouse
)
8047 mods
&= ~(optionKey
| cmdKey
);
8049 return mac_to_emacs_modifiers (mods
);
8052 /* Given an event ref, return the code to use for the mouse button
8053 code in the emacs input_event. */
8055 mac_get_mouse_btn (EventRef ref
)
8057 EventMouseButton result
= kEventMouseButtonPrimary
;
8058 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8059 sizeof (EventMouseButton
), NULL
, &result
);
8062 case kEventMouseButtonPrimary
:
8063 if (NILP (Vmac_emulate_three_button_mouse
))
8067 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8068 sizeof (UInt32
), NULL
, &mods
);
8069 return mac_get_emulated_btn(mods
);
8071 case kEventMouseButtonSecondary
:
8072 return NILP (Vmac_wheel_button_is_mouse_2
) ? 1 : 2;
8073 case kEventMouseButtonTertiary
:
8074 case 4: /* 4 is the number for the mouse wheel button */
8075 return NILP (Vmac_wheel_button_is_mouse_2
) ? 2 : 1;
8081 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8082 events. However the click of the mouse wheel is not converted to a
8083 mouseDown or mouseUp event. Likewise for dead key down events.
8084 This calls ConvertEventRef, but then checks to see if it is a mouse
8085 up/down, or a dead key down carbon event that has not been
8086 converted, and if so, converts it by hand (to be picked up in the
8087 XTread_socket loop). */
8088 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8090 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8095 switch (GetEventClass (eventRef
))
8097 case kEventClassMouse
:
8098 switch (GetEventKind (eventRef
))
8100 case kEventMouseDown
:
8101 eventRec
->what
= mouseDown
;
8106 eventRec
->what
= mouseUp
;
8115 case kEventClassKeyboard
:
8116 switch (GetEventKind (eventRef
))
8118 case kEventRawKeyDown
:
8120 unsigned char char_codes
;
8123 eventRec
->what
= keyDown
;
8124 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8125 NULL
, sizeof (char), NULL
, &char_codes
);
8126 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8127 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8128 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8144 /* Need where and when. */
8147 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8148 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8149 /* Use two step process because new event modifiers are 32-bit
8150 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8151 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8152 NULL
, sizeof (UInt32
), NULL
, &mods
);
8153 eventRec
->modifiers
= mods
;
8155 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8166 Handle menubar_handle
;
8167 MenuHandle menu_handle
;
8169 menubar_handle
= GetNewMBar (128);
8170 if(menubar_handle
== NULL
)
8172 SetMenuBar (menubar_handle
);
8175 #if !TARGET_API_MAC_CARBON
8176 menu_handle
= GetMenuHandle (M_APPLE
);
8177 if(menu_handle
!= NULL
)
8178 AppendResMenu (menu_handle
,'DRVR');
8186 do_init_managers (void)
8188 #if !TARGET_API_MAC_CARBON
8189 InitGraf (&qd
.thePort
);
8191 FlushEvents (everyEvent
, 0);
8196 #endif /* !TARGET_API_MAC_CARBON */
8199 #if !TARGET_API_MAC_CARBON
8200 /* set up some extra stack space for use by emacs */
8201 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8203 /* MaxApplZone must be called for AppleScript to execute more
8204 complicated scripts */
8207 #endif /* !TARGET_API_MAC_CARBON */
8211 do_check_ram_size (void)
8213 SInt32 physical_ram_size
, logical_ram_size
;
8215 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8216 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8217 || physical_ram_size
> (1 << VALBITS
)
8218 || logical_ram_size
> (1 << VALBITS
))
8220 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8226 do_window_update (WindowPtr win
)
8228 struct frame
*f
= mac_window_to_frame (win
);
8232 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8234 if (win
!= tip_window
)
8236 if (f
->async_visible
== 0)
8238 /* Update events may occur when a frame gets iconified. */
8240 f
->async_visible
= 1;
8241 f
->async_iconified
= 0;
8242 SET_FRAME_GARBAGED (f
);
8248 #if TARGET_API_MAC_CARBON
8249 RgnHandle region
= NewRgn ();
8251 GetPortVisibleRegion (GetWindowPort (win
), region
);
8252 GetRegionBounds (region
, &r
);
8253 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8254 UpdateControls (win
, region
);
8255 DisposeRgn (region
);
8257 r
= (*win
->visRgn
)->rgnBBox
;
8258 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8259 UpdateControls (win
, win
->visRgn
);
8268 is_emacs_window (WindowPtr win
)
8270 Lisp_Object tail
, frame
;
8275 FOR_EACH_FRAME (tail
, frame
)
8276 if (FRAME_MAC_P (XFRAME (frame
)))
8277 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8286 /* Window-activate events will do the job. */
8292 /* Window-deactivate events will do the job. */
8297 do_apple_menu (SInt16 menu_item
)
8299 #if !TARGET_API_MAC_CARBON
8301 SInt16 da_driver_refnum
;
8303 if (menu_item
== I_ABOUT
)
8304 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8307 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8308 da_driver_refnum
= OpenDeskAcc (item_name
);
8310 #endif /* !TARGET_API_MAC_CARBON */
8314 do_menu_choice (SInt32 menu_choice
)
8316 SInt16 menu_id
, menu_item
;
8318 menu_id
= HiWord (menu_choice
);
8319 menu_item
= LoWord (menu_choice
);
8327 do_apple_menu (menu_item
);
8332 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8333 MenuHandle menu
= GetMenuHandle (menu_id
);
8338 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8339 menubar_selection_callback (f
, refcon
);
8348 /* Handle drags in size box. Based on code contributed by Ben
8349 Mesander and IM - Window Manager A. */
8352 do_grow_window (WindowPtr w
, EventRecord
*e
)
8355 int rows
, columns
, width
, height
;
8356 struct frame
*f
= mac_window_to_frame (w
);
8357 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8358 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8359 #if TARGET_API_MAC_CARBON
8365 if (size_hints
->flags
& PMinSize
)
8367 min_width
= size_hints
->min_width
;
8368 min_height
= size_hints
->min_height
;
8370 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8372 #if TARGET_API_MAC_CARBON
8373 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8375 height
= new_rect
.bottom
- new_rect
.top
;
8376 width
= new_rect
.right
- new_rect
.left
;
8378 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8379 /* see if it really changed size */
8382 height
= HiWord (grow_size
);
8383 width
= LoWord (grow_size
);
8386 if (width
!= FRAME_PIXEL_WIDTH (f
)
8387 || height
!= FRAME_PIXEL_HEIGHT (f
))
8389 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8390 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8392 x_set_window_size (f
, 0, columns
, rows
);
8397 /* Handle clicks in zoom box. Calculation of "standard state" based
8398 on code in IM - Window Manager A and code contributed by Ben
8399 Mesander. The standard state of an Emacs window is 80-characters
8400 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8403 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8406 Rect zoom_rect
, port_rect
;
8408 int w_title_height
, columns
, rows
, width
, height
;
8409 struct frame
*f
= mac_window_to_frame (w
);
8410 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8412 #if TARGET_API_MAC_CARBON
8414 Point standard_size
;
8416 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8417 standard_size
.v
= dpyinfo
->height
;
8419 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8420 zoom_in_or_out
= inZoomIn
;
8423 /* Adjust the standard size according to character boundaries. */
8425 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8426 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8427 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8428 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8429 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8430 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8431 && port_rect
.left
== zoom_rect
.left
8432 && port_rect
.top
== zoom_rect
.top
)
8433 zoom_in_or_out
= inZoomIn
;
8435 zoom_in_or_out
= inZoomOut
;
8438 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8440 #else /* not TARGET_API_MAC_CARBON */
8441 GetPort (&save_port
);
8443 SetPortWindowPort (w
);
8445 /* Clear window to avoid flicker. */
8446 EraseRect (&(w
->portRect
));
8447 if (zoom_in_or_out
== inZoomOut
)
8449 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8450 LocalToGlobal (&top_left
);
8452 /* calculate height of window's title bar */
8453 w_title_height
= top_left
.v
- 1
8454 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8456 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8457 zoom_rect
= qd
.screenBits
.bounds
;
8458 zoom_rect
.top
+= w_title_height
;
8459 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8461 zoom_rect
.right
= zoom_rect
.left
8462 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8464 /* Adjust the standard size according to character boundaries. */
8465 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8467 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8469 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8473 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8475 SetPort (save_port
);
8476 #endif /* not TARGET_API_MAC_CARBON */
8478 /* retrieve window size and update application values */
8479 #if TARGET_API_MAC_CARBON
8480 GetWindowPortBounds (w
, &port_rect
);
8482 port_rect
= w
->portRect
;
8484 height
= port_rect
.bottom
- port_rect
.top
;
8485 width
= port_rect
.right
- port_rect
.left
;
8487 if (width
!= FRAME_PIXEL_WIDTH (f
)
8488 || height
!= FRAME_PIXEL_HEIGHT (f
))
8490 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8491 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8493 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8494 SET_FRAME_GARBAGED (f
);
8495 cancel_mouse_face (f
);
8497 FRAME_PIXEL_WIDTH (f
) = width
;
8498 FRAME_PIXEL_HEIGHT (f
) = height
;
8500 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8503 /* Intialize AppleEvent dispatcher table for the required events. */
8505 init_required_apple_events ()
8510 /* Make sure we have apple events before starting. */
8511 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
8515 if (!(result
& (1 << gestaltAppleEventsPresent
)))
8518 #if TARGET_API_MAC_CARBON
8519 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8520 NewAEEventHandlerUPP
8521 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8524 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenApplication
,
8525 NewAEEventHandlerProc
8526 ((AEEventHandlerProcPtr
) do_ae_open_application
),
8532 #if TARGET_API_MAC_CARBON
8533 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8534 NewAEEventHandlerUPP
8535 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8538 err
= AEInstallEventHandler(kCoreEventClass
, kAEOpenDocuments
,
8539 NewAEEventHandlerProc
8540 ((AEEventHandlerProcPtr
) do_ae_open_documents
),
8546 #if TARGET_API_MAC_CARBON
8547 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8548 NewAEEventHandlerUPP
8549 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8552 err
= AEInstallEventHandler(kCoreEventClass
, kAEPrintDocuments
,
8553 NewAEEventHandlerProc
8554 ((AEEventHandlerProcPtr
) do_ae_print_documents
),
8560 #if TARGET_API_MAC_CARBON
8561 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8562 NewAEEventHandlerUPP
8563 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8566 err
= AEInstallEventHandler(kCoreEventClass
, kAEQuitApplication
,
8567 NewAEEventHandlerProc
8568 ((AEEventHandlerProcPtr
) do_ae_quit_application
),
8576 mac_store_application_menu_event (event
)
8577 #if USE_CARBON_EVENTS
8583 struct input_event buf
;
8584 Lisp_Object frame
, entry
;
8588 XSETFRAME (frame
, mac_focus_frame (&one_mac_display_info
));
8589 buf
.kind
= MENU_BAR_EVENT
;
8590 buf
.frame_or_window
= frame
;
8592 kbd_buffer_store_event (&buf
);
8594 buf
.arg
= Qapplication
;
8595 kbd_buffer_store_event (&buf
);
8597 #if USE_CARBON_EVENTS
8598 switch (GetEventClass (event
))
8601 case kEventClassService
:
8602 buf
.arg
= Qservices
;
8603 kbd_buffer_store_event (&buf
);
8604 switch (GetEventKind (event
))
8606 case kEventServicePaste
:
8610 case kEventServicePerform
:
8613 CFStringRef message
;
8615 err
= GetEventParameter (event
, kEventParamServiceMessageName
,
8616 typeCFStringRef
, NULL
,
8617 sizeof (CFStringRef
), NULL
, &message
);
8619 kbd_buffer_store_event (&buf
);
8620 if (err
== noErr
&& message
)
8621 entry
= intern (SDATA (cfstring_to_lisp (message
)));
8631 #endif /* MAC_OSX */
8632 case kEventClassCommand
:
8636 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
,
8637 NULL
, sizeof (HICommand
), NULL
, &command
);
8638 switch (command
.commandID
)
8640 case kHICommandAbout
:
8644 case kHICommandPreferences
:
8645 entry
= Qpreferences
;
8647 #endif /* MAC_OSX */
8648 case kHICommandQuit
:
8660 #else /* USE_CARBON_EVENTS */
8663 case kHICommandAbout
:
8666 case kHICommandQuit
:
8675 kbd_buffer_store_event (&buf
);
8678 #if USE_CARBON_EVENTS
8679 static pascal OSStatus
8680 mac_handle_command_event (next_handler
, event
, data
)
8681 EventHandlerCallRef next_handler
;
8688 GetEventParameter(event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8689 sizeof (HICommand
), NULL
, &command
);
8691 switch (command
.commandID
)
8693 case kHICommandAbout
:
8695 case kHICommandPreferences
:
8696 #endif /* MAC_OSX */
8697 result
= CallNextEventHandler (next_handler
, event
);
8698 if (result
!= eventNotHandledErr
)
8701 mac_store_application_menu_event (event
);
8708 return eventNotHandledErr
;
8712 init_command_handler ()
8715 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8716 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8718 if (handle_command_eventUPP
== NULL
)
8719 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8720 return InstallApplicationEventHandler (handle_command_eventUPP
,
8721 GetEventTypeCount (specs
), specs
,
8725 static pascal OSStatus
8726 mac_handle_window_event (next_handler
, event
, data
)
8727 EventHandlerCallRef next_handler
;
8734 XSizeHints
*size_hints
;
8736 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8737 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8739 switch (GetEventKind (event
))
8741 case kEventWindowUpdate
:
8742 result
= CallNextEventHandler (next_handler
, event
);
8743 if (result
!= eventNotHandledErr
)
8746 do_window_update (wp
);
8749 case kEventWindowBoundsChanging
:
8750 result
= CallNextEventHandler (next_handler
, event
);
8751 if (result
!= eventNotHandledErr
)
8754 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8755 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8756 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8757 if ((attributes
& kWindowBoundsChangeUserResize
)
8758 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8759 == (PResizeInc
| PBaseSize
| PMinSize
)))
8764 GetEventParameter (event
, kEventParamCurrentBounds
,
8766 NULL
, sizeof (Rect
), NULL
, &bounds
);
8767 width
= bounds
.right
- bounds
.left
;
8768 height
= bounds
.bottom
- bounds
.top
;
8770 if (width
< size_hints
->min_width
)
8771 width
= size_hints
->min_width
;
8773 width
= size_hints
->base_width
8774 + (int) ((width
- size_hints
->base_width
)
8775 / (float) size_hints
->width_inc
+ .5)
8776 * size_hints
->width_inc
;
8778 if (height
< size_hints
->min_height
)
8779 height
= size_hints
->min_height
;
8781 height
= size_hints
->base_height
8782 + (int) ((height
- size_hints
->base_height
)
8783 / (float) size_hints
->height_inc
+ .5)
8784 * size_hints
->height_inc
;
8786 bounds
.right
= bounds
.left
+ width
;
8787 bounds
.bottom
= bounds
.top
+ height
;
8788 SetEventParameter (event
, kEventParamCurrentBounds
,
8789 typeQDRectangle
, sizeof (Rect
), &bounds
);
8794 case kEventWindowShown
:
8795 case kEventWindowHidden
:
8796 case kEventWindowExpanded
:
8797 case kEventWindowCollapsed
:
8798 result
= CallNextEventHandler (next_handler
, event
);
8800 mac_handle_visibility_change (mac_window_to_frame (wp
));
8806 return eventNotHandledErr
;
8809 static pascal OSStatus
8810 mac_handle_mouse_event (next_handler
, event
, data
)
8811 EventHandlerCallRef next_handler
;
8817 switch (GetEventKind (event
))
8819 case kEventMouseWheelMoved
:
8823 EventMouseWheelAxis axis
;
8827 result
= CallNextEventHandler (next_handler
, event
);
8828 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
8831 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
8832 NULL
, sizeof (WindowRef
), NULL
, &wp
);
8833 f
= mac_window_to_frame (wp
);
8834 if (f
!= mac_focus_frame (&one_mac_display_info
))
8837 GetEventParameter (event
, kEventParamMouseWheelAxis
,
8838 typeMouseWheelAxis
, NULL
,
8839 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
8840 if (axis
!= kEventMouseWheelAxisY
)
8843 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
8844 NULL
, sizeof (SInt32
), NULL
, &delta
);
8845 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
8846 NULL
, sizeof (Point
), NULL
, &point
);
8847 read_socket_inev
->kind
= WHEEL_EVENT
;
8848 read_socket_inev
->code
= 0;
8849 read_socket_inev
->modifiers
=
8850 (mac_event_to_emacs_modifiers (event
)
8851 | ((delta
< 0) ? down_modifier
: up_modifier
));
8852 SetPortWindowPort (wp
);
8853 GlobalToLocal (&point
);
8854 XSETINT (read_socket_inev
->x
, point
.h
);
8855 XSETINT (read_socket_inev
->y
, point
.v
);
8856 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
8866 return eventNotHandledErr
;
8868 #endif /* USE_CARBON_EVENTS */
8872 install_window_handler (window
)
8876 #if USE_CARBON_EVENTS
8877 EventTypeSpec specs_window
[] =
8878 {{kEventClassWindow
, kEventWindowUpdate
},
8879 {kEventClassWindow
, kEventWindowBoundsChanging
},
8880 {kEventClassWindow
, kEventWindowShown
},
8881 {kEventClassWindow
, kEventWindowHidden
},
8882 {kEventClassWindow
, kEventWindowExpanded
},
8883 {kEventClassWindow
, kEventWindowCollapsed
}};
8884 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
8885 static EventHandlerUPP handle_window_eventUPP
= NULL
;
8886 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
8888 if (handle_window_eventUPP
== NULL
)
8889 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
8890 if (handle_mouse_eventUPP
== NULL
)
8891 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
8892 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
8893 GetEventTypeCount (specs_window
),
8894 specs_window
, NULL
, NULL
);
8896 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
8897 GetEventTypeCount (specs_mouse
),
8898 specs_mouse
, NULL
, NULL
);
8900 #if TARGET_API_MAC_CARBON
8901 if (mac_do_track_dragUPP
== NULL
)
8902 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
8903 if (mac_do_receive_dragUPP
== NULL
)
8904 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
8907 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
8909 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
8915 remove_window_handler (window
)
8918 #if TARGET_API_MAC_CARBON
8919 if (mac_do_track_dragUPP
)
8920 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
8921 if (mac_do_receive_dragUPP
)
8922 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
8926 /* Open Application Apple Event */
8928 do_ae_open_application(const AppleEvent
*pae
, AppleEvent
*preply
, long prefcon
)
8934 /* Called when we receive an AppleEvent with an ID of
8935 "kAEOpenDocuments". This routine gets the direct parameter,
8936 extracts the FSSpecs in it, and puts their names on a list. */
8937 #pragma options align=mac68k
8938 typedef struct SelectionRange
{
8939 short unused1
; // 0 (not used)
8940 short lineNum
; // line to select (<0 to specify range)
8941 long startRange
; // start of selection range (if line < 0)
8942 long endRange
; // end of selection range (if line < 0)
8943 long unused2
; // 0 (not used)
8944 long theDate
; // modification date/time
8946 #pragma options align=reset
8949 do_ae_open_documents(AppleEvent
*message
, AppleEvent
*reply
, long refcon
)
8954 DescType actual_type
;
8956 SelectionRange position
;
8957 Lisp_Object file_list
= Qnil
;
8959 xassert (read_socket_inev
);
8961 err
= AEGetParamDesc (message
, keyDirectObject
, typeAEList
, &the_desc
);
8963 goto descriptor_error_exit
;
8965 err
= AEGetParamPtr (message
, keyAEPosition
, typeChar
, &actual_type
, &position
, sizeof(SelectionRange
), &actual_size
);
8967 file_list
= Fcons (list3 (make_number (position
.lineNum
+ 1),
8968 make_number (position
.startRange
+ 1),
8969 make_number (position
.endRange
+ 1)),
8972 /* Check to see that we got all of the required parameters from the
8973 event descriptor. For an 'odoc' event this should just be the
8975 err
= AEGetAttributePtr(message
, keyMissedKeywordAttr
, typeWildCard
,
8976 &actual_type
, (Ptr
) &keyword
,
8977 sizeof (keyword
), &actual_size
);
8978 /* No error means that we found some unused parameters.
8979 errAEDescNotFound means that there are no more parameters. If we
8980 get an error code other than that, flag it. */
8981 if ((err
== noErr
) || (err
!= errAEDescNotFound
))
8983 err
= errAEEventNotHandled
;
8988 /* Got all the parameters we need. Now, go through the direct
8989 object list and parse it up. */
8991 long num_files_to_open
;
8993 err
= AECountItems (&the_desc
, &num_files_to_open
);
8998 /* AE file list is one based so just use that for indexing here. */
8999 for (i
= 1; i
<= num_files_to_open
; i
++)
9001 char unix_path_name
[MAXPATHLEN
];
9005 err
= AEGetNthPtr (&the_desc
, i
, typeFSRef
, &keyword
,
9006 &actual_type
, &fref
, sizeof (FSRef
),
9008 if (err
!= noErr
|| actual_type
!= typeFSRef
)
9011 if (FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
))
9016 err
= AEGetNthPtr(&the_desc
, i
, typeFSS
, &keyword
, &actual_type
,
9017 (Ptr
) &fs
, sizeof (fs
), &actual_size
);
9018 if (err
!= noErr
) continue;
9020 if (fsspec_to_posix_pathname (&fs
, unix_path_name
,
9021 sizeof (unix_path_name
) - 1) == noErr
)
9023 /* x-dnd functions expect undecoded filenames. */
9024 file_list
= Fcons (make_unibyte_string (unix_path_name
,
9025 strlen (unix_path_name
)),
9030 /* Build a DRAG_N_DROP_EVENT type event as is done in
9031 constuct_drag_n_drop in w32term.c. */
9032 if (!NILP (file_list
))
9034 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
9038 read_socket_inev
->kind
= DRAG_N_DROP_EVENT
;
9039 read_socket_inev
->code
= 0;
9040 read_socket_inev
->modifiers
= 0;
9042 XSETINT (read_socket_inev
->x
, 0);
9043 XSETINT (read_socket_inev
->y
, 0);
9045 XSETFRAME (frame
, f
);
9046 read_socket_inev
->frame_or_window
= Fcons (frame
, file_list
);
9049 /* Regardless of whether Emacs was suspended or in the
9050 foreground, ask it to redraw its entire screen. Otherwise
9051 parts of the screen can be left in an inconsistent
9053 wp
= FRAME_MAC_WINDOW (f
);
9055 #if TARGET_API_MAC_CARBON
9059 GetWindowPortBounds (wp
, &r
);
9060 InvalWindowRect (wp
, &r
);
9062 #else /* not TARGET_API_MAC_CARBON */
9063 InvalRect (&(wp
->portRect
));
9064 #endif /* not TARGET_API_MAC_CARBON */
9070 /* Nuke the coerced file list in any case */
9071 err2
= AEDisposeDesc(&the_desc
);
9073 descriptor_error_exit
:
9074 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
9079 #if TARGET_API_MAC_CARBON
9081 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9082 void *handlerRefCon
, DragReference theDrag
)
9084 static int can_accept
;
9087 ItemReference theItem
;
9088 FlavorFlags theFlags
;
9091 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9092 return dragNotAcceptedErr
;
9096 case kDragTrackingEnterHandler
:
9097 CountDragItems (theDrag
, &items
);
9099 for (index
= 1; index
<= items
; index
++)
9101 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9102 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9103 if (result
== noErr
)
9111 case kDragTrackingEnterWindow
:
9114 RgnHandle hilite_rgn
= NewRgn ();
9116 struct frame
*f
= mac_window_to_frame (window
);
9118 GetWindowPortBounds (window
, &r
);
9119 OffsetRect (&r
, -r
.left
, -r
.top
);
9120 RectRgn (hilite_rgn
, &r
);
9121 ShowDragHilite (theDrag
, hilite_rgn
, true);
9122 DisposeRgn (hilite_rgn
);
9123 SetThemeCursor (kThemeCopyArrowCursor
);
9127 case kDragTrackingInWindow
:
9130 case kDragTrackingLeaveWindow
:
9133 struct frame
*f
= mac_window_to_frame (window
);
9135 HideDragHilite (theDrag
);
9136 SetThemeCursor (kThemeArrowCursor
);
9140 case kDragTrackingLeaveHandler
:
9148 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9149 DragReference theDrag
)
9153 FlavorFlags theFlags
;
9156 ItemReference theItem
;
9158 Size size
= sizeof (HFSFlavor
);
9159 Lisp_Object file_list
;
9161 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9162 return dragNotAcceptedErr
;
9165 GetDragMouse (theDrag
, &mouse
, 0L);
9166 CountDragItems (theDrag
, &items
);
9167 for (index
= 1; index
<= items
; index
++)
9169 /* Only handle file references. */
9170 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9171 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9172 if (result
== noErr
)
9177 char unix_path_name
[MAXPATHLEN
];
9179 GetFlavorData (theDrag
, theItem
, flavorTypeHFS
, &data
, &size
, 0L);
9181 /* Use Carbon routines, otherwise it converts the file name
9182 to /Macintosh HD/..., which is not correct. */
9183 FSpMakeFSRef (&data
.fileSpec
, &fref
);
9184 if (! FSRefMakePath (&fref
, unix_path_name
, sizeof (unix_path_name
)));
9186 if (fsspec_to_posix_pathname (&data
.fileSpec
, unix_path_name
,
9187 sizeof (unix_path_name
) - 1) == noErr
)
9189 /* x-dnd functions expect undecoded filenames. */
9190 file_list
= Fcons (make_unibyte_string (unix_path_name
,
9191 strlen (unix_path_name
)),
9195 /* If there are items in the list, construct an event and post it to
9196 the queue like an interrupt using kbd_buffer_store_event. */
9197 if (!NILP (file_list
))
9199 struct input_event event
;
9201 struct frame
*f
= mac_window_to_frame (window
);
9204 GlobalToLocal (&mouse
);
9205 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9207 event
.kind
= DRAG_N_DROP_EVENT
;
9209 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9210 event
.timestamp
= TickCount () * (1000 / 60);
9211 XSETINT (event
.x
, mouse
.h
);
9212 XSETINT (event
.y
, mouse
.v
);
9213 XSETFRAME (frame
, f
);
9214 event
.frame_or_window
= Fcons (frame
, file_list
);
9216 /* Post to the interrupt queue */
9217 kbd_buffer_store_event (&event
);
9218 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9220 ProcessSerialNumber psn
;
9221 GetCurrentProcess (&psn
);
9222 SetFrontProcess (&psn
);
9228 return dragNotAcceptedErr
;
9233 /* Print Document Apple Event */
9235 do_ae_print_documents (const AppleEvent
*pAE
, AppleEvent
*reply
, long refcon
)
9237 return errAEEventNotHandled
;
9242 do_ae_quit_application (AppleEvent
* message
, AppleEvent
*reply
, long refcon
)
9244 #if USE_CARBON_EVENTS
9246 EventRef event
= NULL
;
9247 static const HICommand quit_command
= {kEventAttributeNone
, kHICommandQuit
};
9249 err
= CreateEvent (NULL
, kEventClassCommand
, kEventCommandProcess
, 0,
9250 kEventAttributeUserEvent
, &event
);
9252 err
= SetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
9253 sizeof (HICommand
), &quit_command
);
9255 mac_store_application_menu_event (event
);
9257 ReleaseEvent (event
);
9262 return errAEEventNotHandled
;
9264 mac_store_application_menu_event (kHICommandQuit
);
9273 profiler_exit_proc ()
9275 ProfilerDump ("\pEmacs.prof");
9280 /* These few functions implement Emacs as a normal Mac application
9281 (almost): set up the heap and the Toolbox, handle necessary system
9282 events plus a few simple menu events. They also set up Emacs's
9283 access to functions defined in the rest of this file. Emacs uses
9284 function hooks to perform all its terminal I/O. A complete list of
9285 these functions appear in termhooks.h. For what they do, read the
9286 comments there and see also w32term.c and xterm.c. What's
9287 noticeably missing here is the event loop, which is normally
9288 present in most Mac application. After performing the necessary
9289 Mac initializations, main passes off control to emacs_main
9290 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9291 (defined further below) to read input. This is where
9292 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9299 #if __profile__ /* is the profiler on? */
9300 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9305 /* set creator and type for files created by MSL */
9310 do_init_managers ();
9315 do_check_ram_size ();
9318 init_emacs_passwd_dir ();
9322 initialize_applescript ();
9324 init_required_apple_events ();
9330 /* set up argv array from STR# resource */
9331 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9335 /* free up AppleScript resources on exit */
9336 atexit (terminate_applescript
);
9338 #if __profile__ /* is the profiler on? */
9339 atexit (profiler_exit_proc
);
9342 /* 3rd param "envp" never used in emacs_main */
9343 (void) emacs_main (argc
, argv
, 0);
9346 /* Never reached - real exit in Fkill_emacs */
9351 /* Table for translating Mac keycode to X keysym values. Contributed
9353 Mapping for special keys is now identical to that in Apple X11
9354 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9355 on the right of the Cmd key on laptops, and fn + `enter' (->
9357 static unsigned char keycode_to_xkeysym_table
[] = {
9358 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9359 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9360 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9362 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9363 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9364 /*0x38*/ 0, 0, 0, 0,
9365 /*0x3C*/ 0, 0, 0, 0,
9367 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9368 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9369 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9370 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9372 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9373 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9374 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9375 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9377 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9378 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9379 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9380 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9382 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9383 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9384 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9385 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9389 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9391 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9392 return *xKeySym
!= 0;
9395 #if !USE_CARBON_EVENTS
9396 static RgnHandle mouse_region
= NULL
;
9399 mac_wait_next_event (er
, sleep_time
, dequeue
)
9404 static EventRecord er_buf
= {nullEvent
};
9405 UInt32 target_tick
, current_tick
;
9406 EventMask event_mask
;
9408 if (mouse_region
== NULL
)
9409 mouse_region
= NewRgn ();
9411 event_mask
= everyEvent
;
9412 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop
)))
9413 event_mask
-= highLevelEventMask
;
9415 current_tick
= TickCount ();
9416 target_tick
= current_tick
+ sleep_time
;
9418 if (er_buf
.what
== nullEvent
)
9419 while (!WaitNextEvent (event_mask
, &er_buf
,
9420 target_tick
- current_tick
, mouse_region
))
9422 current_tick
= TickCount ();
9423 if (target_tick
<= current_tick
)
9429 er_buf
.what
= nullEvent
;
9432 #endif /* not USE_CARBON_EVENTS */
9434 /* Emacs calls this whenever it wants to read an input event from the
9437 XTread_socket (sd
, expected
, hold_quit
)
9439 struct input_event
*hold_quit
;
9441 struct input_event inev
;
9443 #if USE_CARBON_EVENTS
9445 EventTargetRef toolbox_dispatcher
;
9448 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9450 if (interrupt_input_blocked
)
9452 interrupt_input_pending
= 1;
9456 interrupt_input_pending
= 0;
9459 /* So people can tell when we have read the available input. */
9460 input_signal_count
++;
9462 #if USE_CARBON_EVENTS
9463 toolbox_dispatcher
= GetEventDispatcherTarget ();
9465 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9466 kEventRemoveFromQueue
, &eventRef
))
9467 #else /* !USE_CARBON_EVENTS */
9468 while (mac_wait_next_event (&er
, 0, true))
9469 #endif /* !USE_CARBON_EVENTS */
9473 unsigned long timestamp
;
9475 /* It is necessary to set this (additional) argument slot of an
9476 event to nil because keyboard.c protects incompletely
9477 processed event from being garbage collected by placing them
9478 in the kbd_buffer_gcpro vector. */
9480 inev
.kind
= NO_EVENT
;
9483 #if USE_CARBON_EVENTS
9484 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9486 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9489 #if USE_CARBON_EVENTS
9490 /* Handle new events */
9491 if (!mac_convert_event_ref (eventRef
, &er
))
9493 /* There used to be a handler for the kEventMouseWheelMoved
9494 event here. But as of Mac OS X 10.4, this kind of event
9495 is not directly posted to the main event queue by
9496 two-finger scrolling on the trackpad. Instead, some
9497 private event is posted and it is converted to a wheel
9498 event by the default handler for the application target.
9499 The converted one can be received by a Carbon event
9500 handler installed on a window target. */
9501 read_socket_inev
= &inev
;
9502 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9503 read_socket_inev
= NULL
;
9506 #endif /* USE_CARBON_EVENTS */
9512 WindowPtr window_ptr
;
9513 ControlPartCode part_code
;
9516 #if USE_CARBON_EVENTS
9517 /* This is needed to send mouse events like aqua window
9518 buttons to the correct handler. */
9519 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9520 != eventNotHandledErr
)
9523 last_mouse_glyph_frame
= 0;
9525 if (dpyinfo
->grabbed
&& last_mouse_frame
9526 && FRAME_LIVE_P (last_mouse_frame
))
9528 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9529 part_code
= inContent
;
9533 part_code
= FindWindow (er
.where
, &window_ptr
);
9534 if (tip_window
&& window_ptr
== tip_window
)
9536 HideWindow (tip_window
);
9537 part_code
= FindWindow (er
.where
, &window_ptr
);
9541 if (er
.what
!= mouseDown
&&
9542 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9548 f
= mac_focus_frame (dpyinfo
);
9549 saved_menu_event_location
= er
.where
;
9550 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9551 XSETFRAME (inev
.frame_or_window
, f
);
9555 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9556 SelectWindow (window_ptr
);
9559 ControlPartCode control_part_code
;
9561 Point mouse_loc
= er
.where
;
9563 ControlKind control_kind
;
9566 f
= mac_window_to_frame (window_ptr
);
9567 /* convert to local coordinates of new window */
9568 SetPortWindowPort (window_ptr
);
9570 GlobalToLocal (&mouse_loc
);
9571 #if TARGET_API_MAC_CARBON
9572 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9573 &control_part_code
);
9576 GetControlKind (ch
, &control_kind
);
9579 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9583 #if USE_CARBON_EVENTS
9584 inev
.code
= mac_get_mouse_btn (eventRef
);
9585 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9587 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9588 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9590 XSETINT (inev
.x
, mouse_loc
.h
);
9591 XSETINT (inev
.y
, mouse_loc
.v
);
9593 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9595 #ifndef USE_TOOLKIT_SCROLL_BARS
9596 /* control_part_code becomes kControlNoPart if
9597 a progress indicator is clicked. */
9598 && control_part_code
!= kControlNoPart
9599 #else /* USE_TOOLKIT_SCROLL_BARS */
9601 && control_kind
.kind
== kControlKindScrollBar
9602 #endif /* MAC_OSX */
9603 #endif /* USE_TOOLKIT_SCROLL_BARS */
9606 struct scroll_bar
*bar
;
9608 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9610 bar
= tracked_scroll_bar
;
9611 #ifndef USE_TOOLKIT_SCROLL_BARS
9612 control_part_code
= kControlIndicatorPart
;
9616 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9617 #ifdef USE_TOOLKIT_SCROLL_BARS
9618 /* Make the "Ctrl-Mouse-2 splits window" work
9619 for toolkit scroll bars. */
9620 if (er
.modifiers
& controlKey
)
9621 x_scroll_bar_handle_click (bar
, control_part_code
,
9623 else if (er
.what
== mouseDown
)
9624 x_scroll_bar_handle_press (bar
, control_part_code
,
9627 x_scroll_bar_handle_release (bar
, &inev
);
9628 #else /* not USE_TOOLKIT_SCROLL_BARS */
9629 x_scroll_bar_handle_click (bar
, control_part_code
,
9631 if (er
.what
== mouseDown
9632 && control_part_code
== kControlIndicatorPart
)
9633 tracked_scroll_bar
= bar
;
9635 tracked_scroll_bar
= NULL
;
9636 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9641 int x
= mouse_loc
.h
;
9642 int y
= mouse_loc
.v
;
9644 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9645 if (EQ (window
, f
->tool_bar_window
))
9647 if (er
.what
== mouseDown
)
9648 handle_tool_bar_click (f
, x
, y
, 1, 0);
9650 handle_tool_bar_click (f
, x
, y
, 0,
9656 XSETFRAME (inev
.frame_or_window
, f
);
9657 inev
.kind
= MOUSE_CLICK_EVENT
;
9661 if (er
.what
== mouseDown
)
9663 dpyinfo
->grabbed
|= (1 << inev
.code
);
9664 last_mouse_frame
= f
;
9667 last_tool_bar_item
= -1;
9671 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9672 /* If a button is released though it was not
9673 previously pressed, that would be because
9674 of multi-button emulation. */
9675 dpyinfo
->grabbed
= 0;
9677 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9680 /* Ignore any mouse motion that happened before
9681 this event; any subsequent mouse-movement Emacs
9682 events should reflect only motion after the
9687 #ifdef USE_TOOLKIT_SCROLL_BARS
9688 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9693 inev
.modifiers
|= down_modifier
;
9696 inev
.modifiers
|= up_modifier
;
9703 #if TARGET_API_MAC_CARBON
9704 DragWindow (window_ptr
, er
.where
, NULL
);
9705 #else /* not TARGET_API_MAC_CARBON */
9706 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9707 #endif /* not TARGET_API_MAC_CARBON */
9708 /* Update the frame parameters. */
9710 struct frame
*f
= mac_window_to_frame (window_ptr
);
9712 if (f
&& !f
->async_iconified
)
9713 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9718 if (TrackGoAway (window_ptr
, er
.where
))
9720 inev
.kind
= DELETE_WINDOW_EVENT
;
9721 XSETFRAME (inev
.frame_or_window
,
9722 mac_window_to_frame (window_ptr
));
9726 /* window resize handling added --ben */
9728 do_grow_window (window_ptr
, &er
);
9731 /* window zoom handling added --ben */
9734 if (TrackBox (window_ptr
, er
.where
, part_code
))
9735 do_zoom_window (window_ptr
, part_code
);
9745 #if USE_CARBON_EVENTS
9746 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9747 != eventNotHandledErr
)
9750 do_window_update ((WindowPtr
) er
.message
);
9755 #if USE_CARBON_EVENTS
9756 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9757 != eventNotHandledErr
)
9760 switch ((er
.message
>> 24) & 0x000000FF)
9762 case suspendResumeMessage
:
9763 if ((er
.message
& resumeFlag
) == 1)
9769 case mouseMovedMessage
:
9770 #if !USE_CARBON_EVENTS
9771 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9772 er
.where
.h
+ 1, er
.where
.v
+ 1);
9774 previous_help_echo_string
= help_echo_string
;
9775 help_echo_string
= Qnil
;
9777 if (dpyinfo
->grabbed
&& last_mouse_frame
9778 && FRAME_LIVE_P (last_mouse_frame
))
9779 f
= last_mouse_frame
;
9781 f
= dpyinfo
->x_focus_frame
;
9783 if (dpyinfo
->mouse_face_hidden
)
9785 dpyinfo
->mouse_face_hidden
= 0;
9786 clear_mouse_face (dpyinfo
);
9791 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9792 Point mouse_pos
= er
.where
;
9794 SetPortWindowPort (wp
);
9796 GlobalToLocal (&mouse_pos
);
9798 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9799 #ifdef USE_TOOLKIT_SCROLL_BARS
9800 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9802 #else /* not USE_TOOLKIT_SCROLL_BARS */
9803 x_scroll_bar_note_movement (tracked_scroll_bar
,
9805 - XINT (tracked_scroll_bar
->top
),
9806 er
.when
* (1000 / 60));
9807 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9810 /* Generate SELECT_WINDOW_EVENTs when needed. */
9811 if (mouse_autoselect_window
)
9815 window
= window_from_coordinates (f
,
9820 /* Window will be selected only when it is
9821 not selected now and last mouse movement
9822 event was not in it. Minibuffer window
9823 will be selected iff it is active. */
9824 if (WINDOWP (window
)
9825 && !EQ (window
, last_window
)
9826 && !EQ (window
, selected_window
))
9828 inev
.kind
= SELECT_WINDOW_EVENT
;
9829 inev
.frame_or_window
= window
;
9834 if (!note_mouse_movement (f
, &mouse_pos
))
9835 help_echo_string
= previous_help_echo_string
;
9839 /* If the contents of the global variable
9840 help_echo_string has changed, generate a
9842 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9850 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9852 #if USE_CARBON_EVENTS
9853 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9854 != eventNotHandledErr
)
9857 if (window_ptr
== tip_window
)
9859 HideWindow (tip_window
);
9863 if (!is_emacs_window (window_ptr
))
9866 if ((er
.modifiers
& activeFlag
) != 0)
9868 /* A window has been activated */
9869 Point mouse_loc
= er
.where
;
9871 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9873 SetPortWindowPort (window_ptr
);
9874 GlobalToLocal (&mouse_loc
);
9875 /* Window-activated event counts as mouse movement,
9876 so update things that depend on mouse position. */
9877 note_mouse_movement (mac_window_to_frame (window_ptr
),
9882 /* A window has been deactivated */
9883 #if USE_TOOLKIT_SCROLL_BARS
9884 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9886 struct input_event event
;
9889 event
.kind
= NO_EVENT
;
9890 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
9891 if (event
.kind
!= NO_EVENT
)
9893 event
.timestamp
= timestamp
;
9894 kbd_buffer_store_event_hold (&event
, hold_quit
);
9899 dpyinfo
->grabbed
= 0;
9901 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9903 f
= mac_window_to_frame (window_ptr
);
9904 if (f
== dpyinfo
->mouse_face_mouse_frame
)
9906 /* If we move outside the frame, then we're
9907 certainly no longer on any text in the
9909 clear_mouse_face (dpyinfo
);
9910 dpyinfo
->mouse_face_mouse_frame
= 0;
9913 /* Generate a nil HELP_EVENT to cancel a help-echo.
9914 Do it only if there's something to cancel.
9915 Otherwise, the startup message is cleared when the
9916 mouse leaves the frame. */
9917 if (any_help_event_p
)
9926 int keycode
= (er
.message
& keyCodeMask
) >> 8;
9929 #if USE_CARBON_EVENTS && defined (MAC_OSX)
9930 /* When using Carbon Events, we need to pass raw keyboard
9931 events to the TSM ourselves. If TSM handles it, it
9932 will pass back noErr, otherwise it will pass back
9933 "eventNotHandledErr" and we can process it
9935 if ((!NILP (Vmac_pass_command_to_system
)
9936 || !(er
.modifiers
& cmdKey
))
9937 && (!NILP (Vmac_pass_control_to_system
)
9938 || !(er
.modifiers
& controlKey
))
9939 && (!NILP (Vmac_command_key_is_meta
)
9940 && NILP (Vmac_option_modifier
)
9941 || !(er
.modifiers
& optionKey
)))
9942 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9943 != eventNotHandledErr
)
9948 if (dpyinfo
->x_focus_frame
== NULL
)
9950 /* Beep if keyboard input occurs when all the frames
9958 static SInt16 last_key_script
= -1;
9959 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
9961 if (last_key_script
!= current_key_script
)
9963 struct input_event event
;
9966 event
.kind
= LANGUAGE_CHANGE_EVENT
;
9968 event
.code
= current_key_script
;
9969 event
.timestamp
= timestamp
;
9970 kbd_buffer_store_event (&event
);
9973 last_key_script
= current_key_script
;
9978 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
9980 clear_mouse_face (dpyinfo
);
9981 dpyinfo
->mouse_face_hidden
= 1;
9984 if (keycode_to_xkeysym (keycode
, &xkeysym
))
9986 inev
.code
= 0xff00 | xkeysym
;
9987 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
9991 if (er
.modifiers
& (controlKey
|
9992 (NILP (Vmac_command_key_is_meta
) ? optionKey
9995 /* This code comes from Keyboard Resource,
9996 Appendix C of IM - Text. This is necessary
9997 since shift is ignored in KCHR table
9998 translation when option or command is pressed.
9999 It also does not translate correctly
10000 control-shift chars like C-% so mask off shift
10002 int new_modifiers
= er
.modifiers
& 0xe600;
10003 /* mask off option and command */
10004 int new_keycode
= keycode
| new_modifiers
;
10005 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10006 unsigned long some_state
= 0;
10007 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
10008 &some_state
) & 0xff;
10010 else if (!NILP (Vmac_option_modifier
)
10011 && (er
.modifiers
& optionKey
))
10013 /* When using the option key as an emacs modifier,
10014 convert the pressed key code back to one
10015 without the Mac option modifier applied. */
10016 int new_modifiers
= er
.modifiers
& ~optionKey
;
10017 int new_keycode
= keycode
| new_modifiers
;
10018 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
10019 unsigned long some_state
= 0;
10020 inev
.code
= KeyTranslate (kchr_ptr
, new_keycode
,
10021 &some_state
) & 0xff;
10024 inev
.code
= er
.message
& charCodeMask
;
10025 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10029 #if USE_CARBON_EVENTS
10030 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10032 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10034 inev
.modifiers
|= (extra_keyboard_modifiers
10035 & (meta_modifier
| alt_modifier
10036 | hyper_modifier
| super_modifier
));
10037 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10040 case kHighLevelEvent
:
10041 read_socket_inev
= &inev
;
10042 AEProcessAppleEvent (&er
);
10043 read_socket_inev
= NULL
;
10049 #if USE_CARBON_EVENTS
10050 ReleaseEvent (eventRef
);
10053 if (inev
.kind
!= NO_EVENT
)
10055 inev
.timestamp
= timestamp
;
10056 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10061 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10066 XSETFRAME (frame
, f
);
10072 any_help_event_p
= 1;
10073 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10074 help_echo_object
, help_echo_pos
);
10078 help_echo_string
= Qnil
;
10079 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10086 /* If the focus was just given to an autoraising frame,
10088 /* ??? This ought to be able to handle more than one such frame. */
10089 if (pending_autoraise_frame
)
10091 x_raise_frame (pending_autoraise_frame
);
10092 pending_autoraise_frame
= 0;
10095 #if !USE_CARBON_EVENTS
10096 /* Check which frames are still visible. We do this here because
10097 there doesn't seem to be any direct notification from the Window
10098 Manager that the visibility of a window has changed (at least,
10099 not in all cases). */
10101 Lisp_Object tail
, frame
;
10103 FOR_EACH_FRAME (tail
, frame
)
10105 struct frame
*f
= XFRAME (frame
);
10107 /* The tooltip has been drawn already. Avoid the
10108 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10109 if (EQ (frame
, tip_frame
))
10112 if (FRAME_MAC_P (f
))
10113 mac_handle_visibility_change (f
);
10123 /* Need to override CodeWarrior's input function so no conversion is
10124 done on newlines Otherwise compiled functions in .elc files will be
10125 read incorrectly. Defined in ...:MSL C:MSL
10126 Common:Source:buffer_io.c. */
10129 __convert_to_newlines (unsigned char * p
, size_t * n
)
10131 #pragma unused(p,n)
10135 __convert_from_newlines (unsigned char * p
, size_t * n
)
10137 #pragma unused(p,n)
10143 make_mac_terminal_frame (struct frame
*f
)
10148 XSETFRAME (frame
, f
);
10150 f
->output_method
= output_mac
;
10151 f
->output_data
.mac
= (struct mac_output
*)
10152 xmalloc (sizeof (struct mac_output
));
10153 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10155 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10157 FRAME_COLS (f
) = 96;
10158 FRAME_LINES (f
) = 4;
10160 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10161 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10163 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10165 f
->output_data
.mac
->cursor_pixel
= 0;
10166 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10167 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10168 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10170 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10171 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10172 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10173 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10174 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10175 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10177 FRAME_FONTSET (f
) = -1;
10178 f
->output_data
.mac
->explicit_parent
= 0;
10181 f
->border_width
= 0;
10183 f
->internal_border_width
= 0;
10188 f
->new_text_cols
= 0;
10189 f
->new_text_lines
= 0;
10191 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10192 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10193 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10197 if (!(FRAME_MAC_WINDOW (f
) =
10198 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10199 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10201 /* so that update events can find this mac_output struct */
10202 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10208 /* Need to be initialized for unshow_buffer in window.c. */
10209 selected_window
= f
->selected_window
;
10211 Fmodify_frame_parameters (frame
,
10212 Fcons (Fcons (Qfont
,
10213 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10214 Fmodify_frame_parameters (frame
,
10215 Fcons (Fcons (Qforeground_color
,
10216 build_string ("black")), Qnil
));
10217 Fmodify_frame_parameters (frame
,
10218 Fcons (Fcons (Qbackground_color
,
10219 build_string ("white")), Qnil
));
10224 /***********************************************************************
10226 ***********************************************************************/
10228 int mac_initialized
= 0;
10231 mac_initialize_display_info ()
10233 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10234 GDHandle main_device_handle
;
10236 bzero (dpyinfo
, sizeof (*dpyinfo
));
10239 dpyinfo
->mac_id_name
10240 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10241 + SCHARS (Vsystem_name
)
10243 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10244 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10246 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10247 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10250 main_device_handle
= LMGetMainDevice();
10252 dpyinfo
->reference_count
= 0;
10253 dpyinfo
->resx
= 72.0;
10254 dpyinfo
->resy
= 72.0;
10255 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10257 /* HasDepth returns true if it is possible to have a 32 bit display,
10258 but this may not be what is actually used. Mac OSX can do better.
10259 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10260 header for CGGetActiveDisplayList says that the first display returned
10261 is the active one, so we use that. */
10263 CGDirectDisplayID disp_id
[1];
10264 CGDisplayCount disp_count
;
10265 CGDisplayErr error_code
;
10267 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10268 if (error_code
!= 0)
10269 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10271 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10274 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10275 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10276 gdDevType
, dpyinfo
->color_p
))
10279 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10280 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10281 dpyinfo
->grabbed
= 0;
10282 dpyinfo
->root_window
= NULL
;
10283 dpyinfo
->image_cache
= make_image_cache ();
10285 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10286 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10287 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10288 dpyinfo
->mouse_face_window
= Qnil
;
10289 dpyinfo
->mouse_face_overlay
= Qnil
;
10290 dpyinfo
->mouse_face_hidden
= 0;
10295 mac_make_rdb (xrm_option
)
10298 XrmDatabase database
;
10300 database
= xrm_get_preference_database (NULL
);
10302 xrm_merge_string_database (database
, xrm_option
);
10307 struct mac_display_info
*
10308 mac_term_init (display_name
, xrm_option
, resource_name
)
10309 Lisp_Object display_name
;
10311 char *resource_name
;
10313 struct mac_display_info
*dpyinfo
;
10317 if (!mac_initialized
)
10320 mac_initialized
= 1;
10323 if (x_display_list
)
10324 error ("Sorry, this version can only handle one display");
10326 mac_initialize_display_info ();
10328 dpyinfo
= &one_mac_display_info
;
10330 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10332 /* Put this display on the chain. */
10333 dpyinfo
->next
= x_display_list
;
10334 x_display_list
= dpyinfo
;
10336 /* Put it on x_display_name_list. */
10337 x_display_name_list
= Fcons (Fcons (display_name
,
10338 Fcons (Qnil
, dpyinfo
->xrdb
)),
10339 x_display_name_list
);
10340 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10346 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10349 x_delete_display (dpyinfo
)
10350 struct mac_display_info
*dpyinfo
;
10354 /* Discard this display from x_display_name_list and x_display_list.
10355 We can't use Fdelq because that can quit. */
10356 if (! NILP (x_display_name_list
)
10357 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10358 x_display_name_list
= XCDR (x_display_name_list
);
10363 tail
= x_display_name_list
;
10364 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10366 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10368 XSETCDR (tail
, XCDR (XCDR (tail
)));
10371 tail
= XCDR (tail
);
10375 if (x_display_list
== dpyinfo
)
10376 x_display_list
= dpyinfo
->next
;
10379 struct x_display_info
*tail
;
10381 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10382 if (tail
->next
== dpyinfo
)
10383 tail
->next
= tail
->next
->next
;
10386 /* Free the font names in the font table. */
10387 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10388 if (dpyinfo
->font_table
[i
].name
)
10390 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10391 xfree (dpyinfo
->font_table
[i
].full_name
);
10392 xfree (dpyinfo
->font_table
[i
].name
);
10395 if (dpyinfo
->font_table
->font_encoder
)
10396 xfree (dpyinfo
->font_table
->font_encoder
);
10398 xfree (dpyinfo
->font_table
);
10399 xfree (dpyinfo
->mac_id_name
);
10401 if (x_display_list
== 0)
10403 mac_clear_font_name_table ();
10404 bzero (dpyinfo
, sizeof (*dpyinfo
));
10413 extern int inhibit_window_system
;
10414 extern int noninteractive
;
10415 CFBundleRef appsBundle
;
10418 /* No need to test if already -nw*/
10419 if (inhibit_window_system
|| noninteractive
)
10422 appsBundle
= CFBundleGetMainBundle();
10423 if (appsBundle
!= NULL
)
10425 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10426 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10427 /* We found the bundle identifier, now we know we are valid. */
10434 /* MAC_TODO: Have this start the bundled executable */
10436 /* For now, prevent the fatal error by bringing it up in the terminal */
10437 inhibit_window_system
= 1;
10441 MakeMeTheFrontProcess ()
10443 ProcessSerialNumber psn
;
10446 err
= GetCurrentProcess (&psn
);
10448 (void) SetFrontProcess (&psn
);
10451 /***** Code to handle C-g testing *****/
10453 /* Contains the Mac modifier formed from quit_char */
10454 int mac_quit_char_modifiers
= 0;
10455 int mac_quit_char_keycode
;
10456 extern int quit_char
;
10459 mac_determine_quit_char_modifiers()
10461 /* Todo: Determine modifiers from quit_char. */
10462 UInt32 qc_modifiers
= ctrl_modifier
;
10464 /* Map modifiers */
10465 mac_quit_char_modifiers
= 0;
10466 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= macCtrlKey
;
10467 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= macShiftKey
;
10468 if (qc_modifiers
& meta_modifier
) mac_quit_char_modifiers
|= macMetaKey
;
10469 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= macAltKey
;
10473 init_quit_char_handler ()
10475 /* TODO: Let this support keys other the 'g' */
10476 mac_quit_char_keycode
= 5;
10477 /* Look at <architecture/adb_kb_map.h> for details */
10478 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10480 mac_determine_quit_char_modifiers();
10482 #endif /* MAC_OSX */
10490 MenuItemIndex menu_index
;
10492 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10493 &menu
, &menu_index
);
10495 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10496 #if USE_CARBON_EVENTS
10497 EnableMenuCommand (NULL
, kHICommandPreferences
);
10498 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10499 &menu
, &menu_index
);
10502 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10503 InsertMenuItemTextWithCFString (menu
, NULL
,
10504 0, kMenuItemAttrSeparator
, 0);
10505 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10506 0, 0, kHICommandAbout
);
10508 #endif /* USE_CARBON_EVENTS */
10509 #else /* !MAC_OSX */
10510 #if USE_CARBON_EVENTS
10511 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10517 /* Set up use of X before we make the first connection. */
10519 extern frame_parm_handler mac_frame_parm_handlers
[];
10521 static struct redisplay_interface x_redisplay_interface
=
10523 mac_frame_parm_handlers
,
10527 x_clear_end_of_line
,
10529 x_after_update_window_line
,
10530 x_update_window_begin
,
10531 x_update_window_end
,
10534 0, /* flush_display_optional */
10535 x_clear_window_mouse_face
,
10536 x_get_glyph_overhangs
,
10537 x_fix_overlapping_area
,
10538 x_draw_fringe_bitmap
,
10539 0, /* define_fringe_bitmap */
10540 0, /* destroy_fringe_bitmap */
10541 mac_per_char_metric
,
10543 mac_compute_glyph_string_overhangs
,
10544 x_draw_glyph_string
,
10545 mac_define_frame_cursor
,
10546 mac_clear_frame_area
,
10547 mac_draw_window_cursor
,
10548 mac_draw_vertical_window_border
,
10549 mac_shift_glyphs_for_insert
10555 rif
= &x_redisplay_interface
;
10557 clear_frame_hook
= x_clear_frame
;
10558 ins_del_lines_hook
= x_ins_del_lines
;
10559 delete_glyphs_hook
= x_delete_glyphs
;
10560 ring_bell_hook
= XTring_bell
;
10561 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10562 set_terminal_modes_hook
= XTset_terminal_modes
;
10563 update_begin_hook
= x_update_begin
;
10564 update_end_hook
= x_update_end
;
10565 set_terminal_window_hook
= XTset_terminal_window
;
10566 read_socket_hook
= XTread_socket
;
10567 frame_up_to_date_hook
= XTframe_up_to_date
;
10568 mouse_position_hook
= XTmouse_position
;
10569 frame_rehighlight_hook
= XTframe_rehighlight
;
10570 frame_raise_lower_hook
= XTframe_raise_lower
;
10572 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10573 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10574 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10575 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10577 scroll_region_ok
= 1; /* we'll scroll partial frames */
10578 char_ins_del_ok
= 1;
10579 line_ins_del_ok
= 1; /* we'll just blt 'em */
10580 fast_clear_end_of_line
= 1; /* X does this well */
10581 memory_below_frame
= 0; /* we don't remember what scrolls
10585 last_tool_bar_item
= -1;
10586 any_help_event_p
= 0;
10588 /* Try to use interrupt input; if we can't, then start polling. */
10589 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10593 #if TARGET_API_MAC_CARBON
10594 init_required_apple_events ();
10596 #if USE_CARBON_EVENTS
10598 init_service_handler ();
10600 init_quit_char_handler ();
10601 #endif /* MAC_OSX */
10603 init_command_handler ();
10606 #endif /* USE_CARBON_EVENTS */
10609 if (!inhibit_window_system
)
10610 MakeMeTheFrontProcess ();
10621 staticpro (&x_error_message_string
);
10622 x_error_message_string
= Qnil
;
10625 Qmodifier_value
= intern ("modifier-value");
10626 Qalt
= intern ("alt");
10627 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10628 Qhyper
= intern ("hyper");
10629 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10630 Qsuper
= intern ("super");
10631 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10633 Qapplication
= intern ("application"); staticpro (&Qapplication
);
10634 Qabout
= intern ("about"); staticpro (&Qabout
);
10636 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10637 Qpreferences
= intern ("preferences"); staticpro (&Qpreferences
);
10638 Qservices
= intern ("services"); staticpro (&Qservices
);
10639 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10640 Qperform
= intern ("perform"); staticpro (&Qperform
);
10644 Fprovide (intern ("mac-carbon"), Qnil
);
10647 staticpro (&Qreverse
);
10648 Qreverse
= intern ("reverse");
10650 staticpro (&Qmac_ready_for_drag_n_drop
);
10651 Qmac_ready_for_drag_n_drop
= intern ("mac-ready-for-drag-n-drop");
10653 staticpro (&x_display_name_list
);
10654 x_display_name_list
= Qnil
;
10656 staticpro (&last_mouse_scroll_bar
);
10657 last_mouse_scroll_bar
= Qnil
;
10659 staticpro (&fm_font_family_alist
);
10660 fm_font_family_alist
= Qnil
;
10663 staticpro (&atsu_font_id_hash
);
10664 atsu_font_id_hash
= Qnil
;
10667 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10668 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10669 #ifdef USE_TOOLKIT_SCROLL_BARS
10670 Vx_toolkit_scroll_bars
= Qt
;
10672 Vx_toolkit_scroll_bars
= Qnil
;
10675 staticpro (&last_mouse_motion_frame
);
10676 last_mouse_motion_frame
= Qnil
;
10678 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta
,
10679 doc
: /* Non-nil means that the command key is used as the Emacs meta key.
10680 Otherwise the option key is used. */);
10681 Vmac_command_key_is_meta
= Qt
;
10683 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10684 doc
: /* Modifier to use for the Mac alt/option key. The value can
10685 be alt, hyper, or super for the respective modifier. If the value is
10686 nil then the key will act as the normal Mac option modifier. */);
10687 Vmac_option_modifier
= Qnil
;
10689 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta
,
10690 doc
: /* Non-nil means that the control and meta keys are reversed. This is
10691 useful for non-standard keyboard layouts. */);
10692 Vmac_reverse_ctrl_meta
= Qnil
;
10694 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10695 &Vmac_emulate_three_button_mouse
,
10696 doc
: /* t means that when the option-key is held down while pressing the
10697 mouse button, the click will register as mouse-2 and while the
10698 command-key is held down, the click will register as mouse-3.
10699 'reverse means that the option-key will register for mouse-3
10700 and the command-key will register for mouse-2. nil means that
10701 no emulation should be done and the modifiers should be placed
10702 on the mouse-1 event. */);
10703 Vmac_emulate_three_button_mouse
= Qnil
;
10705 #if USE_CARBON_EVENTS
10706 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2
,
10707 doc
: /* Non-nil means that the wheel button will be treated as mouse-2 and
10708 the right click will be mouse-3.
10709 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
10710 Vmac_wheel_button_is_mouse_2
= Qt
;
10712 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system
,
10713 doc
: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
10714 Toolbox for processing before Emacs sees it. */);
10715 Vmac_pass_command_to_system
= Qt
;
10717 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system
,
10718 doc
: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
10719 Toolbox for processing before Emacs sees it. */);
10720 Vmac_pass_control_to_system
= Qt
;
10724 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics
,
10725 doc
: /* If non-nil, allow anti-aliasing.
10726 The text will be rendered using Core Graphics text rendering which
10727 may anti-alias the text. */);
10728 Vmac_use_core_graphics
= Qnil
;
10730 /* Register an entry for `mac-roman' so that it can be used when
10731 creating the terminal frame on Mac OS 9 before loading
10732 term/mac-win.elc. */
10733 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10734 doc
: /* Alist linking Emacs character sets to Mac text encoding and Emacs coding system.
10735 Each entry should be of the form:
10737 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10739 where CHARSET-NAME is a string used in font names to identify the
10740 charset, TEXT-ENCODING is a TextEncodingBase value, and CODING_SYSTEM
10741 is a coding system corresponding to TEXT-ENCODING. */);
10742 Vmac_charset_info_alist
=
10743 Fcons (list3 (build_string ("mac-roman"),
10744 make_number (smRoman
), Qnil
), Qnil
);
10747 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10748 (do not change this comment) */