1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006 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 */
75 #include "dispextern.h"
77 #include "termhooks.h"
85 #include "intervals.h"
91 /* Non-nil means Emacs uses toolkit scroll bars. */
93 Lisp_Object Vx_toolkit_scroll_bars
;
95 /* If non-zero, the text will be rendered using Core Graphics text
96 rendering which may anti-alias the text. */
97 int mac_use_core_graphics
;
100 /* Non-zero means that a HELP_EVENT has been generated since Emacs
103 static int any_help_event_p
;
105 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
106 static Lisp_Object last_window
;
108 /* Non-zero means make use of UNDERLINE_POSITION font properties.
109 (Not yet supported.) */
110 int x_use_underline_position_properties
;
112 /* This is a chain of structures for all the X displays currently in
115 struct x_display_info
*x_display_list
;
117 /* This is a list of cons cells, each of the form (NAME
118 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of
119 x_display_list and in the same order. NAME is the name of the
120 frame. FONT-LIST-CACHE records previous values returned by
121 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database
122 equivalent, which is implemented with a Lisp object, for the
125 Lisp_Object x_display_name_list
;
127 /* This is display since Mac does not support multiple ones. */
128 struct mac_display_info one_mac_display_info
;
130 /* Frame being updated by update_frame. This is declared in term.c.
131 This is set by update_begin and looked at by all the XT functions.
132 It is zero while not inside an update. In that case, the XT
133 functions assume that `selected_frame' is the frame to apply to. */
135 extern struct frame
*updating_frame
;
137 /* This is a frame waiting to be auto-raised, within XTread_socket. */
139 struct frame
*pending_autoraise_frame
;
143 Formerly, we used PointerMotionHintMask (in standard_event_mask)
144 so that we would have to call XQueryPointer after each MotionNotify
145 event to ask for another such event. However, this made mouse tracking
146 slow, and there was a bug that made it eventually stop.
148 Simply asking for MotionNotify all the time seems to work better.
150 In order to avoid asking for motion events and then throwing most
151 of them away or busy-polling the server for mouse positions, we ask
152 the server for pointer motion hints. This means that we get only
153 one event per group of mouse movements. "Groups" are delimited by
154 other kinds of events (focus changes and button clicks, for
155 example), or by XQueryPointer calls; when one of these happens, we
156 get another MotionNotify event the next time the mouse moves. This
157 is at least as efficient as getting motion events when mouse
158 tracking is on, and I suspect only negligibly worse when tracking
161 /* Where the mouse was last time we reported a mouse event. */
163 static Rect last_mouse_glyph
;
164 static FRAME_PTR last_mouse_glyph_frame
;
166 /* The scroll bar in which the last X motion event occurred.
168 If the last X motion event occurred in a scroll bar, we set this so
169 XTmouse_position can know whether to report a scroll bar motion or
172 If the last X motion event didn't occur in a scroll bar, we set
173 this to Qnil, to tell XTmouse_position to return an ordinary motion
176 static Lisp_Object last_mouse_scroll_bar
;
178 /* This is a hack. We would really prefer that XTmouse_position would
179 return the time associated with the position it returns, but there
180 doesn't seem to be any way to wrest the time-stamp from the server
181 along with the position query. So, we just keep track of the time
182 of the last movement we received, and return that in hopes that
183 it's somewhat accurate. */
185 static Time last_mouse_movement_time
;
187 struct scroll_bar
*tracked_scroll_bar
= NULL
;
189 /* Incremented by XTread_socket whenever it really tries to read
193 static int volatile input_signal_count
;
195 static int input_signal_count
;
198 extern Lisp_Object Vsystem_name
;
200 /* A mask of extra modifier bits to put into every keyboard char. */
202 extern EMACS_INT extra_keyboard_modifiers
;
204 /* The keysyms to use for the various modifiers. */
206 static Lisp_Object Qalt
, Qhyper
, Qsuper
, Qcontrol
, Qmeta
, Qmodifier_value
;
208 extern int inhibit_window_system
;
210 #if __MRC__ && !TARGET_API_MAC_CARBON
211 QDGlobals qd
; /* QuickDraw global information structure. */
214 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
216 struct mac_display_info
*mac_display_info_for_display (Display
*);
217 static void x_update_window_end
P_ ((struct window
*, int, int));
218 static int x_io_error_quitter
P_ ((Display
*));
219 int x_catch_errors
P_ ((Display
*));
220 void x_uncatch_errors
P_ ((Display
*, int));
221 void x_lower_frame
P_ ((struct frame
*));
222 void x_scroll_bar_clear
P_ ((struct frame
*));
223 int x_had_errors_p
P_ ((Display
*));
224 void x_wm_set_size_hint
P_ ((struct frame
*, long, int));
225 void x_raise_frame
P_ ((struct frame
*));
226 void x_set_window_size
P_ ((struct frame
*, int, int, int));
227 void x_wm_set_window_state
P_ ((struct frame
*, int));
228 void x_wm_set_icon_pixmap
P_ ((struct frame
*, int));
229 void mac_initialize
P_ ((void));
230 static void x_font_min_bounds
P_ ((XFontStruct
*, int *, int *));
231 static int x_compute_min_glyph_bounds
P_ ((struct frame
*));
232 static void x_update_end
P_ ((struct frame
*));
233 static void XTframe_up_to_date
P_ ((struct frame
*));
234 static void XTset_terminal_modes
P_ ((void));
235 static void XTreset_terminal_modes
P_ ((void));
236 static void x_clear_frame
P_ ((void));
237 static void frame_highlight
P_ ((struct frame
*));
238 static void frame_unhighlight
P_ ((struct frame
*));
239 static void x_new_focus_frame
P_ ((struct x_display_info
*, struct frame
*));
240 static void mac_focus_changed
P_ ((int, struct mac_display_info
*,
241 struct frame
*, struct input_event
*));
242 static void x_detect_focus_change
P_ ((struct mac_display_info
*,
243 EventRecord
*, struct input_event
*));
244 static void XTframe_rehighlight
P_ ((struct frame
*));
245 static void x_frame_rehighlight
P_ ((struct x_display_info
*));
246 static void x_draw_hollow_cursor
P_ ((struct window
*, struct glyph_row
*));
247 static void x_draw_bar_cursor
P_ ((struct window
*, struct glyph_row
*, int,
248 enum text_cursor_kinds
));
250 static void x_clip_to_row
P_ ((struct window
*, struct glyph_row
*, int, GC
));
251 static void x_flush
P_ ((struct frame
*f
));
252 static void x_update_begin
P_ ((struct frame
*));
253 static void x_update_window_begin
P_ ((struct window
*));
254 static void x_after_update_window_line
P_ ((struct glyph_row
*));
255 static void x_scroll_bar_report_motion
P_ ((struct frame
**, Lisp_Object
*,
256 enum scroll_bar_part
*,
257 Lisp_Object
*, Lisp_Object
*,
260 static int is_emacs_window
P_ ((WindowPtr
));
261 static XCharStruct
*mac_per_char_metric
P_ ((XFontStruct
*, XChar2b
*, int));
262 static void XSetFont
P_ ((Display
*, GC
, XFontStruct
*));
264 /* Defined in macmenu.h. */
265 extern void menubar_selection_callback (FRAME_PTR
, int);
267 #define GC_FORE_COLOR(gc) (&(gc)->fore_color)
268 #define GC_BACK_COLOR(gc) (&(gc)->back_color)
269 #define GC_FONT(gc) ((gc)->xgcv.font)
270 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
272 static RgnHandle saved_port_clip_region
= NULL
;
278 static RgnHandle new_region
= NULL
;
280 if (saved_port_clip_region
== NULL
)
281 saved_port_clip_region
= NewRgn ();
282 if (new_region
== NULL
)
283 new_region
= NewRgn ();
285 if (gc
->n_clip_rects
)
287 GetClip (saved_port_clip_region
);
288 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
289 SetClip (new_region
);
297 if (gc
->n_clip_rects
)
298 SetClip (saved_port_clip_region
);
302 /* X display function emulation */
305 XFreePixmap (display
, pixmap
)
306 Display
*display
; /* not used */
309 DisposeGWorld (pixmap
);
313 /* Mac version of XDrawLine. */
316 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
321 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
323 RGBForeColor (GC_FORE_COLOR (gc
));
332 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
341 GetGWorld (&old_port
, &old_gdh
);
344 RGBForeColor (GC_FORE_COLOR (gc
));
346 LockPixels (GetGWorldPixMap (p
));
349 UnlockPixels (GetGWorldPixMap (p
));
351 SetGWorld (old_port
, old_gdh
);
356 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
360 unsigned int width
, height
;
364 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
366 RGBBackColor (GC_BACK_COLOR (gc
));
367 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
373 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
377 /* Mac version of XClearArea. */
380 mac_clear_area (f
, x
, y
, width
, height
)
383 unsigned int width
, height
;
385 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
388 /* Mac version of XClearWindow. */
394 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
396 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
398 #if TARGET_API_MAC_CARBON
402 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
405 #else /* not TARGET_API_MAC_CARBON */
406 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
407 #endif /* not TARGET_API_MAC_CARBON */
411 /* Mac replacement for XCopyArea. */
414 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
417 int x
, y
, width
, height
;
418 unsigned short *bits
;
424 bitmap
.rowBytes
= sizeof(unsigned short);
425 bitmap
.baseAddr
= (char *)bits
;
426 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
428 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
430 RGBForeColor (GC_FORE_COLOR (gc
));
431 RGBBackColor (GC_BACK_COLOR (gc
));
432 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
435 #if TARGET_API_MAC_CARBON
441 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
442 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
443 UnlockPortBits (port
);
445 #else /* not TARGET_API_MAC_CARBON */
446 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
447 overlay_p
? srcOr
: srcCopy
, 0);
448 #endif /* not TARGET_API_MAC_CARBON */
451 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
455 /* Mac replacement for XCreateBitmapFromBitmapData. */
458 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
463 static unsigned char swap_nibble
[16]
464 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
465 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
466 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
467 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
471 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
472 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
473 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
474 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
475 for (i
= 0; i
< h
; i
++)
477 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
478 for (j
= 0; j
< w1
; j
++)
480 /* Bitswap XBM bytes to match how Mac does things. */
481 unsigned char c
= *bits
++;
482 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
483 | (swap_nibble
[(c
>>4) & 0xf]));;
487 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
492 mac_free_bitmap (bitmap
)
495 xfree (bitmap
->baseAddr
);
500 XCreatePixmap (display
, w
, width
, height
, depth
)
501 Display
*display
; /* not used */
503 unsigned int width
, height
;
510 SetPortWindowPort (w
);
512 SetRect (&r
, 0, 0, width
, height
);
513 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
521 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
522 Display
*display
; /* not used */
525 unsigned int width
, height
;
526 unsigned long fg
, bg
;
533 static GC gc
= NULL
; /* not reentrant */
536 gc
= XCreateGC (display
, w
, 0, NULL
);
538 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
542 GetGWorld (&old_port
, &old_gdh
);
543 SetGWorld (pixmap
, NULL
);
544 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
545 XSetForeground (display
, gc
, fg
);
546 XSetBackground (display
, gc
, bg
);
547 RGBForeColor (GC_FORE_COLOR (gc
));
548 RGBBackColor (GC_BACK_COLOR (gc
));
549 LockPixels (GetGWorldPixMap (pixmap
));
550 #if TARGET_API_MAC_CARBON
551 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
552 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
553 #else /* not TARGET_API_MAC_CARBON */
554 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
555 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
556 #endif /* not TARGET_API_MAC_CARBON */
557 UnlockPixels (GetGWorldPixMap (pixmap
));
558 SetGWorld (old_port
, old_gdh
);
559 mac_free_bitmap (&bitmap
);
565 /* Mac replacement for XFillRectangle. */
568 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
572 unsigned int width
, height
;
576 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
578 RGBForeColor (GC_FORE_COLOR (gc
));
579 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
582 PaintRect (&r
); /* using foreground color of gc */
587 /* Mac replacement for XDrawRectangle: dest is a window. */
590 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
594 unsigned int width
, height
;
598 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
600 RGBForeColor (GC_FORE_COLOR (gc
));
601 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
604 FrameRect (&r
); /* using foreground color of gc */
611 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
612 ConstUniCharArrayPtr text
;
613 UniCharCount text_length
;
615 ATSUTextLayout
*text_layout
;
618 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
620 if (saved_text_layout
== NULL
)
622 UniCharCount lengths
[] = {kATSUToTextEnd
};
623 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
624 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
625 static ATSLineLayoutOptions line_layout
=
626 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
627 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
628 | kATSLineUseQDRendering
630 kATSLineIsDisplayOnly
| kATSLineFractDisable
633 ATSUAttributeValuePtr values
[] = {&line_layout
};
635 err
= ATSUCreateTextLayoutWithTextPtr (text
,
636 kATSUFromTextBeginning
,
642 err
= ATSUSetLayoutControls (saved_text_layout
,
643 sizeof (tags
) / sizeof (tags
[0]),
644 tags
, sizes
, values
);
645 /* XXX: Should we do this? */
647 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
651 err
= ATSUSetRunStyle (saved_text_layout
, style
,
652 kATSUFromTextBeginning
, kATSUToTextEnd
);
654 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
655 kATSUFromTextBeginning
,
661 *text_layout
= saved_text_layout
;
668 mac_invert_rectangle (f
, x
, y
, width
, height
)
671 unsigned int width
, height
;
675 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
677 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
684 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, bytes_per_char
)
689 int nchars
, bg_width
, bytes_per_char
;
691 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
694 if (GC_FONT (gc
)->mac_style
)
697 ATSUTextLayout text_layout
;
699 xassert (bytes_per_char
== 2);
701 #ifndef WORDS_BIG_ENDIAN
704 UniChar
*text
= (UniChar
*)buf
;
706 for (i
= 0; i
< nchars
; i
++)
707 text
[i
] = EndianU16_BtoN (text
[i
]);
710 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
712 GC_FONT (gc
)->mac_style
,
717 if (!mac_use_core_graphics
)
721 RGBForeColor (GC_FORE_COLOR (gc
));
726 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
727 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
728 RGBBackColor (GC_BACK_COLOR (gc
));
730 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
733 ATSUDrawText (text_layout
,
734 kATSUFromTextBeginning
, kATSUToTextEnd
,
735 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
742 CGContextRef context
;
743 float port_height
= FRAME_PIXEL_HEIGHT (f
);
744 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
745 ByteCount sizes
[] = {sizeof (CGContextRef
)};
746 ATSUAttributeValuePtr values
[] = {&context
};
749 QDBeginCGContext (port
, &context
);
750 if (gc
->n_clip_rects
|| bg_width
)
752 CGContextTranslateCTM (context
, 0, port_height
);
753 CGContextScaleCTM (context
, 1, -1);
754 if (gc
->n_clip_rects
)
755 CGContextClipToRects (context
, gc
->clip_rects
,
759 CGContextSetRGBFillColor
761 RED_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
762 GREEN_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
763 BLUE_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
767 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
768 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
770 CGContextScaleCTM (context
, 1, -1);
771 CGContextTranslateCTM (context
, 0, -port_height
);
773 CGContextSetRGBFillColor
775 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
776 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
777 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
779 err
= ATSUSetLayoutControls (text_layout
,
780 sizeof (tags
) / sizeof (tags
[0]),
781 tags
, sizes
, values
);
783 ATSUDrawText (text_layout
,
784 kATSUFromTextBeginning
, kATSUToTextEnd
,
785 Long2Fix (x
), Long2Fix (port_height
- y
));
786 CGContextSynchronize (context
);
787 QDEndCGContext (port
, &context
);
789 /* This doesn't work on Mac OS X 10.1. */
790 ATSUClearLayoutControls (text_layout
,
791 sizeof (tags
) / sizeof (tags
[0]), tags
);
793 ATSUSetLayoutControls (text_layout
,
794 sizeof (tags
) / sizeof (tags
[0]),
795 tags
, sizes
, values
);
801 #endif /* USE_ATSUI */
803 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
806 if (mac_use_core_graphics
)
807 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
810 RGBForeColor (GC_FORE_COLOR (gc
));
814 RGBBackColor (GC_BACK_COLOR (gc
));
820 /* We prefer not to use srcCopy text transfer mode on Mac OS X
822 - Screen is double-buffered. (In srcCopy mode, a text is
823 drawn into an offscreen graphics world first. So
824 performance gain cannot be expected.)
825 - It lowers rendering quality.
826 - Some fonts leave garbage on cursor movement. */
831 RGBBackColor (GC_BACK_COLOR (gc
));
832 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
833 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
838 TextFont (GC_FONT (gc
)->mac_fontnum
);
839 TextSize (GC_FONT (gc
)->mac_fontsize
);
840 TextFace (GC_FONT (gc
)->mac_fontface
);
842 DrawText (buf
, 0, nchars
* bytes_per_char
);
844 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
847 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
848 if (mac_use_core_graphics
)
849 SwapQDTextFlags(savedFlags
);
855 /* Mac replacement for XDrawString. */
858 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
865 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, 0, 1);
869 /* Mac replacement for XDrawString16. */
872 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
879 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, 0, 2);
883 /* Mac replacement for XDrawImageString. */
886 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
891 int nchars
, bg_width
;
893 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, 1);
897 /* Mac replacement for XDrawString16. */
900 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
905 int nchars
, bg_width
;
907 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
, 2);
911 /* Mac replacement for XQueryTextExtents, but takes a character. If
912 STYLE is NULL, measurement is done by QuickDraw Text routines for
913 the font of the current graphics port. If CG_GLYPH is not NULL,
914 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
917 mac_query_char_extents (style
, c
,
918 font_ascent_return
, font_descent_return
,
919 overall_return
, cg_glyph
)
926 int *font_ascent_return
, *font_descent_return
;
927 XCharStruct
*overall_return
;
928 #if USE_CG_TEXT_DRAWING
941 ATSUTextLayout text_layout
;
944 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
947 ATSTrapezoid glyph_bounds
;
949 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
950 kATSUFromTextBeginning
, kATSUToTextEnd
,
951 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
952 kATSUseFractionalOrigins
,
954 kATSUseDeviceOrigins
,
956 1, &glyph_bounds
, NULL
);
959 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
960 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
962 width
= Fix2Long (glyph_bounds
.upperRight
.x
963 - glyph_bounds
.upperLeft
.x
);
964 if (font_ascent_return
)
965 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
966 if (font_descent_return
)
967 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
970 if (err
== noErr
&& overall_return
)
972 err
= ATSUMeasureTextImage (text_layout
,
973 kATSUFromTextBeginning
, kATSUToTextEnd
,
976 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
977 #if USE_CG_TEXT_DRAWING
978 if (err
== noErr
&& cg_glyph
)
981 ATSUGlyphInfoArray glyph_info_array
;
982 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
984 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
985 kATSUToTextEnd
, NULL
, NULL
, NULL
);
987 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
988 kATSUToTextEnd
, &count
,
992 xassert (glyph_info_array
.glyphs
[0].glyphID
);
993 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1004 if (font_ascent_return
|| font_descent_return
)
1008 GetFontInfo (&font_info
);
1009 if (font_ascent_return
)
1010 *font_ascent_return
= font_info
.ascent
;
1011 if (font_descent_return
)
1012 *font_descent_return
= font_info
.descent
;
1018 width
= CharWidth (ch
);
1019 QDTextBounds (1, &ch
, &char_bounds
);
1020 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1028 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1031 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1032 XFontStruct
*font_struct
;
1035 XCharStruct
*overall_return
;
1038 short width
= 0, lbearing
= 0, rbearing
= 0;
1041 for (i
= 0; i
< nchars
; i
++)
1043 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1045 width
+= FONT_WIDTH (font_struct
);
1048 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1049 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1050 width
+= pcm
->width
;
1055 overall_return
->lbearing
= lbearing
;
1056 overall_return
->rbearing
= rbearing
;
1057 overall_return
->width
= width
;
1059 /* What's the meaning of the return value of XTextExtents16? */
1063 #if USE_CG_TEXT_DRAWING
1064 static int cg_text_anti_aliasing_threshold
= 8;
1067 init_cg_text_anti_aliasing_threshold ()
1073 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1074 kCFPreferencesCurrentApplication
,
1077 cg_text_anti_aliasing_threshold
= threshold
;
1081 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1086 int nchars
, bg_width
;
1089 float port_height
, gx
, gy
;
1091 CGContextRef context
;
1095 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1098 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1099 port_height
= FRAME_PIXEL_HEIGHT (f
);
1101 gy
= port_height
- y
;
1102 glyphs
= (CGGlyph
*)buf
;
1103 advances
= alloca (sizeof (CGSize
) * nchars
);
1104 if (advances
== NULL
)
1106 for (i
= 0; i
< nchars
; i
++)
1108 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1110 advances
[i
].width
= pcm
->width
;
1111 advances
[i
].height
= 0;
1112 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1116 QDBeginCGContext (port
, &context
);
1117 if (gc
->n_clip_rects
|| bg_width
)
1119 CGContextTranslateCTM (context
, 0, port_height
);
1120 CGContextScaleCTM (context
, 1, -1);
1121 if (gc
->n_clip_rects
)
1122 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1125 CGContextSetRGBFillColor
1127 RED_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
1128 GREEN_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
1129 BLUE_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
1133 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1134 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1136 CGContextScaleCTM (context
, 1, -1);
1137 CGContextTranslateCTM (context
, 0, -port_height
);
1139 CGContextSetRGBFillColor (context
,
1140 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
1141 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
1142 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
1144 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1145 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1146 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1147 CGContextSetShouldAntialias (context
, false);
1148 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1149 CGContextSetTextPosition (context
, gx
, gy
);
1150 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1152 for (i
= 0; i
< nchars
; i
++)
1154 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1155 gx
+= advances
[i
].width
;
1158 CGContextSynchronize (context
);
1159 QDEndCGContext (port
, &context
);
1166 /* Mac replacement for XCopyArea: dest must be window. */
1169 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1174 unsigned int width
, height
;
1179 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1181 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1182 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1184 ForeColor (blackColor
);
1185 BackColor (whiteColor
);
1187 mac_begin_clip (gc
);
1188 LockPixels (GetGWorldPixMap (src
));
1189 #if TARGET_API_MAC_CARBON
1194 LockPortBits (port
);
1195 CopyBits (GetPortBitMapForCopyBits (src
),
1196 GetPortBitMapForCopyBits (port
),
1197 &src_r
, &dest_r
, srcCopy
, 0);
1198 UnlockPortBits (port
);
1200 #else /* not TARGET_API_MAC_CARBON */
1201 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1202 &src_r
, &dest_r
, srcCopy
, 0);
1203 #endif /* not TARGET_API_MAC_CARBON */
1204 UnlockPixels (GetGWorldPixMap (src
));
1207 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1212 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1213 width
, height
, dest_x
, dest_y
)
1218 unsigned int width
, height
;
1223 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1225 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1226 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1228 ForeColor (blackColor
);
1229 BackColor (whiteColor
);
1231 mac_begin_clip (gc
);
1232 LockPixels (GetGWorldPixMap (src
));
1233 LockPixels (GetGWorldPixMap (mask
));
1234 #if TARGET_API_MAC_CARBON
1239 LockPortBits (port
);
1240 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1241 GetPortBitMapForCopyBits (port
),
1242 &src_r
, &src_r
, &dest_r
);
1243 UnlockPortBits (port
);
1245 #else /* not TARGET_API_MAC_CARBON */
1246 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1247 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1248 #endif /* not TARGET_API_MAC_CARBON */
1249 UnlockPixels (GetGWorldPixMap (mask
));
1250 UnlockPixels (GetGWorldPixMap (src
));
1253 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1257 /* Mac replacement for XCopyArea: used only for scrolling. */
1260 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1264 unsigned int width
, height
;
1267 #if TARGET_API_MAC_CARBON
1269 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1271 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1272 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1273 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1274 kScrollWindowNoOptions
, dummy
);
1276 #else /* not TARGET_API_MAC_CARBON */
1278 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1282 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1283 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1285 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1286 color mapping in CopyBits. Otherwise, it will be slow. */
1287 ForeColor (blackColor
);
1288 BackColor (whiteColor
);
1289 mac_begin_clip (gc
);
1290 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1293 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1294 #endif /* not TARGET_API_MAC_CARBON */
1298 /* Mac replacement for XChangeGC. */
1301 XChangeGC (display
, gc
, mask
, xgcv
)
1307 if (mask
& GCForeground
)
1308 XSetForeground (display
, gc
, xgcv
->foreground
);
1309 if (mask
& GCBackground
)
1310 XSetBackground (display
, gc
, xgcv
->background
);
1312 XSetFont (display
, gc
, xgcv
->font
);
1316 /* Mac replacement for XCreateGC. */
1319 XCreateGC (display
, window
, mask
, xgcv
)
1325 GC gc
= xmalloc (sizeof (*gc
));
1329 bzero (gc
, sizeof (*gc
));
1330 XChangeGC (display
, gc
, mask
, xgcv
);
1337 /* Used in xfaces.c. */
1340 XFreeGC (display
, gc
)
1344 if (gc
->clip_region
)
1345 DisposeRgn (gc
->clip_region
);
1350 /* Mac replacement for XGetGCValues. */
1353 XGetGCValues (display
, gc
, mask
, xgcv
)
1359 if (mask
& GCForeground
)
1360 xgcv
->foreground
= gc
->xgcv
.foreground
;
1361 if (mask
& GCBackground
)
1362 xgcv
->background
= gc
->xgcv
.background
;
1364 xgcv
->font
= gc
->xgcv
.font
;
1368 /* Mac replacement for XSetForeground. */
1371 XSetForeground (display
, gc
, color
)
1374 unsigned long color
;
1376 if (gc
->xgcv
.foreground
!= color
)
1378 gc
->xgcv
.foreground
= color
;
1379 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1380 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1381 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1386 /* Mac replacement for XSetBackground. */
1389 XSetBackground (display
, gc
, color
)
1392 unsigned long color
;
1394 if (gc
->xgcv
.background
!= color
)
1396 gc
->xgcv
.background
= color
;
1397 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1398 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1399 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1404 /* Mac replacement for XSetFont. */
1407 XSetFont (display
, gc
, font
)
1412 gc
->xgcv
.font
= font
;
1416 /* Mac replacement for XSetClipRectangles. */
1419 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1427 xassert (n
>= 0 && n
<= MAX_CLIP_RECTS
);
1429 gc
->n_clip_rects
= n
;
1432 if (gc
->clip_region
== NULL
)
1433 gc
->clip_region
= NewRgn ();
1434 RectRgn (gc
->clip_region
, rectangles
);
1437 RgnHandle region
= NewRgn ();
1439 for (i
= 1; i
< n
; i
++)
1441 RectRgn (region
, rectangles
+ i
);
1442 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1444 DisposeRgn (region
);
1447 #if defined (MAC_OSX) && USE_ATSUI
1448 for (i
= 0; i
< n
; i
++)
1450 Rect
*rect
= rectangles
+ i
;
1452 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1453 rect
->right
- rect
->left
,
1454 rect
->bottom
- rect
->top
);
1460 /* Mac replacement for XSetClipMask. */
1463 mac_reset_clip_rectangles (display
, gc
)
1467 gc
->n_clip_rects
= 0;
1471 /* Mac replacement for XSetWindowBackground. */
1474 XSetWindowBackground (display
, w
, color
)
1477 unsigned long color
;
1479 #if !TARGET_API_MAC_CARBON
1480 AuxWinHandle aw_handle
;
1481 CTabHandle ctab_handle
;
1482 ColorSpecPtr ct_table
;
1487 bg_color
.red
= RED16_FROM_ULONG (color
);
1488 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1489 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1491 #if TARGET_API_MAC_CARBON
1492 SetWindowContentColor (w
, &bg_color
);
1494 if (GetAuxWin (w
, &aw_handle
))
1496 ctab_handle
= (*aw_handle
)->awCTable
;
1497 HandToHand ((Handle
*) &ctab_handle
);
1498 ct_table
= (*ctab_handle
)->ctTable
;
1499 ct_size
= (*ctab_handle
)->ctSize
;
1500 while (ct_size
> -1)
1502 if (ct_table
->value
== 0)
1504 ct_table
->rgb
= bg_color
;
1505 CTabChanged (ctab_handle
);
1506 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1514 /* x_sync is a no-op on Mac. */
1522 /* Flush display of frame F, or of all frames if F is null. */
1528 #if TARGET_API_MAC_CARBON
1531 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1533 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1539 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1540 Calls to XFlush should be unnecessary because the X output buffer
1541 is flushed automatically as needed by calls to XPending,
1542 XNextEvent, or XWindowEvent according to the XFlush man page.
1543 XTread_socket calls XPending. Removing XFlush improves
1546 #define XFlush(DISPLAY) (void) 0
1549 /* Return the struct mac_display_info corresponding to DPY. There's
1552 struct mac_display_info
*
1553 mac_display_info_for_display (dpy
)
1556 return &one_mac_display_info
;
1561 /***********************************************************************
1562 Starting and ending an update
1563 ***********************************************************************/
1565 /* Start an update of frame F. This function is installed as a hook
1566 for update_begin, i.e. it is called when update_begin is called.
1567 This function is called prior to calls to x_update_window_begin for
1568 each window being updated. */
1574 #if TARGET_API_MAC_CARBON
1575 /* During update of a frame, availability of input events is
1576 periodically checked with ReceiveNextEvent if
1577 redisplay-dont-pause is nil. That normally flushes window buffer
1578 changes for every check, and thus screen update looks waving even
1579 if no input is available. So we disable screen updates during
1580 update of a frame. */
1582 DisableScreenUpdates ();
1588 /* Start update of window W. Set the global variable updated_window
1589 to the window being updated and set output_cursor to the cursor
1593 x_update_window_begin (w
)
1596 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1597 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1600 set_output_cursor (&w
->cursor
);
1604 if (f
== display_info
->mouse_face_mouse_frame
)
1606 /* Don't do highlighting for mouse motion during the update. */
1607 display_info
->mouse_face_defer
= 1;
1609 /* If F needs to be redrawn, simply forget about any prior mouse
1611 if (FRAME_GARBAGED_P (f
))
1612 display_info
->mouse_face_window
= Qnil
;
1614 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1615 their mouse_face_p flag set, which means that they are always
1616 unequal to rows in a desired matrix which never have that
1617 flag set. So, rows containing mouse-face glyphs are never
1618 scrolled, and we don't have to switch the mouse highlight off
1619 here to prevent it from being scrolled. */
1621 /* Can we tell that this update does not affect the window
1622 where the mouse highlight is? If so, no need to turn off.
1623 Likewise, don't do anything if the frame is garbaged;
1624 in that case, the frame's current matrix that we would use
1625 is all wrong, and we will redisplay that line anyway. */
1626 if (!NILP (display_info
->mouse_face_window
)
1627 && w
== XWINDOW (display_info
->mouse_face_window
))
1631 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1632 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1635 if (i
< w
->desired_matrix
->nrows
)
1636 clear_mouse_face (display_info
);
1645 /* Draw a vertical window border from (x,y0) to (x,y1) */
1648 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1652 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1655 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1657 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1660 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1663 /* End update of window W (which is equal to updated_window).
1665 Draw vertical borders between horizontally adjacent windows, and
1666 display W's cursor if CURSOR_ON_P is non-zero.
1668 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1669 glyphs in mouse-face were overwritten. In that case we have to
1670 make sure that the mouse-highlight is properly redrawn.
1672 W may be a menu bar pseudo-window in case we don't have X toolkit
1673 support. Such windows don't have a cursor, so don't display it
1677 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1679 int cursor_on_p
, mouse_face_overwritten_p
;
1681 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1683 if (!w
->pseudo_window_p
)
1688 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1690 output_cursor
.x
, output_cursor
.y
);
1692 if (draw_window_fringes (w
, 1))
1693 x_draw_vertical_border (w
);
1698 /* If a row with mouse-face was overwritten, arrange for
1699 XTframe_up_to_date to redisplay the mouse highlight. */
1700 if (mouse_face_overwritten_p
)
1702 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1703 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1704 dpyinfo
->mouse_face_window
= Qnil
;
1707 updated_window
= NULL
;
1711 /* End update of frame F. This function is installed as a hook in
1718 /* Mouse highlight may be displayed again. */
1719 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1722 #if TARGET_API_MAC_CARBON
1723 EnableScreenUpdates ();
1725 XFlush (FRAME_MAC_DISPLAY (f
));
1730 /* This function is called from various places in xdisp.c whenever a
1731 complete update has been performed. The global variable
1732 updated_window is not available here. */
1735 XTframe_up_to_date (f
)
1738 if (FRAME_MAC_P (f
))
1740 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1742 if (dpyinfo
->mouse_face_deferred_gc
1743 || f
== dpyinfo
->mouse_face_mouse_frame
)
1746 if (dpyinfo
->mouse_face_mouse_frame
)
1747 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1748 dpyinfo
->mouse_face_mouse_x
,
1749 dpyinfo
->mouse_face_mouse_y
);
1750 dpyinfo
->mouse_face_deferred_gc
= 0;
1757 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1758 arrow bitmaps, or clear the fringes if no bitmaps are required
1759 before DESIRED_ROW is made current. The window being updated is
1760 found in updated_window. This function is called from
1761 update_window_line only if it is known that there are differences
1762 between bitmaps to be drawn between current row and DESIRED_ROW. */
1765 x_after_update_window_line (desired_row
)
1766 struct glyph_row
*desired_row
;
1768 struct window
*w
= updated_window
;
1774 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1775 desired_row
->redraw_fringe_bitmaps_p
= 1;
1777 /* When a window has disappeared, make sure that no rest of
1778 full-width rows stays visible in the internal border. Could
1779 check here if updated_window is the leftmost/rightmost window,
1780 but I guess it's not worth doing since vertically split windows
1781 are almost never used, internal border is rarely set, and the
1782 overhead is very small. */
1783 if (windows_or_buffers_changed
1784 && desired_row
->full_width_p
1785 && (f
= XFRAME (w
->frame
),
1786 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1788 && (height
= desired_row
->visible_height
,
1791 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1793 /* Internal border is drawn below the tool bar. */
1794 if (WINDOWP (f
->tool_bar_window
)
1795 && w
== XWINDOW (f
->tool_bar_window
))
1799 mac_clear_area (f
, 0, y
, width
, height
);
1800 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1806 /* Draw the bitmap WHICH in one of the left or right fringes of
1807 window W. ROW is the glyph row for which to display the bitmap; it
1808 determines the vertical position at which the bitmap has to be
1812 x_draw_fringe_bitmap (w
, row
, p
)
1814 struct glyph_row
*row
;
1815 struct draw_fringe_bitmap_params
*p
;
1817 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1818 Display
*display
= FRAME_MAC_DISPLAY (f
);
1819 struct face
*face
= p
->face
;
1822 /* Must clip because of partially visible lines. */
1823 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1826 /* Adjust position of "bottom aligned" bitmap on partially
1827 visible last row. */
1829 int oldVH
= row
->visible_height
;
1830 row
->visible_height
= p
->h
;
1831 row
->y
-= rowY
- p
->y
;
1832 x_clip_to_row (w
, row
, -1, face
->gc
);
1834 row
->visible_height
= oldVH
;
1837 x_clip_to_row (w
, row
, -1, face
->gc
);
1839 if (p
->bx
>= 0 && !p
->overlay_p
)
1841 #if 0 /* MAC_TODO: stipple */
1842 /* In case the same realized face is used for fringes and
1843 for something displayed in the text (e.g. face `region' on
1844 mono-displays, the fill style may have been changed to
1845 FillSolid in x_draw_glyph_string_background. */
1847 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1849 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1852 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1854 #if 0 /* MAC_TODO: stipple */
1856 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1862 unsigned short *bits
= p
->bits
+ p
->dh
;
1865 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1866 XSetForeground (display
, face
->gc
,
1868 ? (p
->overlay_p
? face
->background
1869 : f
->output_data
.mac
->cursor_pixel
)
1870 : face
->foreground
));
1871 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1872 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1873 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1876 mac_reset_clip_rectangles (display
, face
->gc
);
1881 /* This is called when starting Emacs and when restarting after
1882 suspend. When starting Emacs, no window is mapped. And nothing
1883 must be done to Emacs's own window if it is suspended (though that
1887 XTset_terminal_modes ()
1891 /* This is called when exiting or suspending Emacs. Exiting will make
1892 the windows go away, and suspending requires no action. */
1895 XTreset_terminal_modes ()
1901 /***********************************************************************
1903 ***********************************************************************/
1905 /* Function prototypes of this page. */
1907 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1908 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1911 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1912 is not contained in the font. */
1914 static INLINE XCharStruct
*
1915 x_per_char_metric (font
, char2b
)
1919 /* The result metric information. */
1920 XCharStruct
*pcm
= NULL
;
1922 xassert (font
&& char2b
);
1925 if (font
->mac_style
)
1927 XCharStructRow
**row
= font
->bounds
.rows
+ char2b
->byte1
;
1931 *row
= xmalloc (sizeof (XCharStructRow
));
1933 bzero (*row
, sizeof (XCharStructRow
));
1937 pcm
= (*row
)->per_char
+ char2b
->byte2
;
1938 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row
, char2b
->byte2
))
1941 mac_query_char_extents (font
->mac_style
,
1942 (char2b
->byte1
<< 8) + char2b
->byte2
,
1943 NULL
, NULL
, pcm
, NULL
);
1945 XCHARSTRUCTROW_SET_CHAR_VALID (*row
, char2b
->byte2
);
1952 if (font
->bounds
.per_char
!= NULL
)
1954 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1956 /* min_char_or_byte2 specifies the linear character index
1957 corresponding to the first element of the per_char array,
1958 max_char_or_byte2 is the index of the last character. A
1959 character with non-zero CHAR2B->byte1 is not in the font.
1960 A character with byte2 less than min_char_or_byte2 or
1961 greater max_char_or_byte2 is not in the font. */
1962 if (char2b
->byte1
== 0
1963 && char2b
->byte2
>= font
->min_char_or_byte2
1964 && char2b
->byte2
<= font
->max_char_or_byte2
)
1965 pcm
= font
->bounds
.per_char
1966 + (char2b
->byte2
- font
->min_char_or_byte2
);
1970 /* If either min_byte1 or max_byte1 are nonzero, both
1971 min_char_or_byte2 and max_char_or_byte2 are less than
1972 256, and the 2-byte character index values corresponding
1973 to the per_char array element N (counting from 0) are:
1975 byte1 = N/D + min_byte1
1976 byte2 = N\D + min_char_or_byte2
1980 D = max_char_or_byte2 - min_char_or_byte2 + 1
1981 / = integer division
1982 \ = integer modulus */
1983 if (char2b
->byte1
>= font
->min_byte1
1984 && char2b
->byte1
<= font
->max_byte1
1985 && char2b
->byte2
>= font
->min_char_or_byte2
1986 && char2b
->byte2
<= font
->max_char_or_byte2
)
1988 pcm
= (font
->bounds
.per_char
1989 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1990 * (char2b
->byte1
- font
->min_byte1
))
1991 + (char2b
->byte2
- font
->min_char_or_byte2
));
1997 /* If the per_char pointer is null, all glyphs between the first
1998 and last character indexes inclusive have the same
1999 information, as given by both min_bounds and max_bounds. */
2000 if (char2b
->byte2
>= font
->min_char_or_byte2
2001 && char2b
->byte2
<= font
->max_char_or_byte2
)
2002 pcm
= &font
->max_bounds
;
2008 return ((pcm
== NULL
2009 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
2016 static XCharStruct
*
2017 mac_per_char_metric (font
, char2b
, font_type
)
2022 return x_per_char_metric (font
, char2b
);
2026 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2027 the two-byte form of C. Encoding is returned in *CHAR2B. */
2030 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2033 struct font_info
*font_info
;
2036 int charset
= CHAR_CHARSET (c
);
2037 XFontStruct
*font
= font_info
->font
;
2039 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2040 This may be either a program in a special encoder language or a
2042 if (font_info
->font_encoder
)
2044 /* It's a program. */
2045 struct ccl_program
*ccl
= font_info
->font_encoder
;
2047 check_ccl_update (ccl
);
2048 if (CHARSET_DIMENSION (charset
) == 1)
2050 ccl
->reg
[0] = charset
;
2051 ccl
->reg
[1] = char2b
->byte2
;
2056 ccl
->reg
[0] = charset
;
2057 ccl
->reg
[1] = char2b
->byte1
;
2058 ccl
->reg
[2] = char2b
->byte2
;
2061 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2063 /* We assume that MSBs are appropriately set/reset by CCL
2065 if (font
->max_byte1
== 0) /* 1-byte font */
2066 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2068 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2070 else if (font_info
->encoding
[charset
])
2072 /* Fixed encoding scheme. See fontset.h for the meaning of the
2073 encoding numbers. */
2074 int enc
= font_info
->encoding
[charset
];
2076 if ((enc
== 1 || enc
== 2)
2077 && CHARSET_DIMENSION (charset
) == 2)
2078 char2b
->byte1
|= 0x80;
2080 if (enc
== 1 || enc
== 3)
2081 char2b
->byte2
|= 0x80;
2087 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2088 char2b
->byte1
= sjis1
;
2089 char2b
->byte2
= sjis2
;
2094 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2096 return FONT_TYPE_UNKNOWN
;
2101 /***********************************************************************
2103 ***********************************************************************/
2107 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2108 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2109 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2111 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2112 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2113 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2114 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2115 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2116 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2117 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2118 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2119 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2120 unsigned long *, double, int));*/
2121 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2122 double, int, unsigned long));
2123 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2124 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2125 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2126 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2127 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2128 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2130 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2131 int, int, int, int, int, int,
2133 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2134 int, int, int, Rect
*));
2137 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2141 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2146 struct glyph_string
*s
;
2148 if (s
->font
== FRAME_FONT (s
->f
)
2149 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2150 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2152 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2155 /* Cursor on non-default face: must merge. */
2159 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2160 xgcv
.foreground
= s
->face
->background
;
2162 /* If the glyph would be invisible, try a different foreground. */
2163 if (xgcv
.foreground
== xgcv
.background
)
2164 xgcv
.foreground
= s
->face
->foreground
;
2165 if (xgcv
.foreground
== xgcv
.background
)
2166 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2167 if (xgcv
.foreground
== xgcv
.background
)
2168 xgcv
.foreground
= s
->face
->foreground
;
2170 /* Make sure the cursor is distinct from text in this face. */
2171 if (xgcv
.background
== s
->face
->background
2172 && xgcv
.foreground
== s
->face
->foreground
)
2174 xgcv
.background
= s
->face
->foreground
;
2175 xgcv
.foreground
= s
->face
->background
;
2178 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2179 xgcv
.font
= s
->font
;
2180 mask
= GCForeground
| GCBackground
| GCFont
;
2182 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2183 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2186 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2187 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2189 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2194 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2197 x_set_mouse_face_gc (s
)
2198 struct glyph_string
*s
;
2203 /* What face has to be used last for the mouse face? */
2204 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2205 face
= FACE_FROM_ID (s
->f
, face_id
);
2207 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2209 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2210 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2212 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2213 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2214 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2216 /* If font in this face is same as S->font, use it. */
2217 if (s
->font
== s
->face
->font
)
2218 s
->gc
= s
->face
->gc
;
2221 /* Otherwise construct scratch_cursor_gc with values from FACE
2226 xgcv
.background
= s
->face
->background
;
2227 xgcv
.foreground
= s
->face
->foreground
;
2228 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2229 xgcv
.font
= s
->font
;
2230 mask
= GCForeground
| GCBackground
| GCFont
;
2232 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2233 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2236 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2237 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2239 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2242 xassert (s
->gc
!= 0);
2246 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2247 Faces to use in the mode line have already been computed when the
2248 matrix was built, so there isn't much to do, here. */
2251 x_set_mode_line_face_gc (s
)
2252 struct glyph_string
*s
;
2254 s
->gc
= s
->face
->gc
;
2258 /* Set S->gc of glyph string S for drawing that glyph string. Set
2259 S->stippled_p to a non-zero value if the face of S has a stipple
2263 x_set_glyph_string_gc (s
)
2264 struct glyph_string
*s
;
2266 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2268 if (s
->hl
== DRAW_NORMAL_TEXT
)
2270 s
->gc
= s
->face
->gc
;
2271 s
->stippled_p
= s
->face
->stipple
!= 0;
2273 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2275 x_set_mode_line_face_gc (s
);
2276 s
->stippled_p
= s
->face
->stipple
!= 0;
2278 else if (s
->hl
== DRAW_CURSOR
)
2280 x_set_cursor_gc (s
);
2283 else if (s
->hl
== DRAW_MOUSE_FACE
)
2285 x_set_mouse_face_gc (s
);
2286 s
->stippled_p
= s
->face
->stipple
!= 0;
2288 else if (s
->hl
== DRAW_IMAGE_RAISED
2289 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2291 s
->gc
= s
->face
->gc
;
2292 s
->stippled_p
= s
->face
->stipple
!= 0;
2296 s
->gc
= s
->face
->gc
;
2297 s
->stippled_p
= s
->face
->stipple
!= 0;
2300 /* GC must have been set. */
2301 xassert (s
->gc
!= 0);
2305 /* Set clipping for output of glyph string S. S may be part of a mode
2306 line or menu if we don't have X toolkit support. */
2309 x_set_glyph_string_clipping (s
)
2310 struct glyph_string
*s
;
2312 Rect rects
[MAX_CLIP_RECTS
];
2315 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2316 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2321 Compute left and right overhang of glyph string S. If S is a glyph
2322 string for a composition, assume overhangs don't exist. */
2325 mac_compute_glyph_string_overhangs (s
)
2326 struct glyph_string
*s
;
2329 && s
->first_glyph
->type
== CHAR_GLYPH
)
2332 || s
->font
->mac_style
2338 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2339 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2340 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2345 MacFontStruct
*font
= s
->font
;
2347 TextFont (font
->mac_fontnum
);
2348 TextSize (font
->mac_fontsize
);
2349 TextFace (font
->mac_fontface
);
2351 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2353 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2354 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2359 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2362 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2363 struct glyph_string
*s
;
2366 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2370 /* Draw the background of glyph_string S. If S->background_filled_p
2371 is non-zero don't draw it. FORCE_P non-zero means draw the
2372 background even if it wouldn't be drawn normally. This is used
2373 when a string preceding S draws into the background of S, or S
2374 contains the first component of a composition. */
2377 x_draw_glyph_string_background (s
, force_p
)
2378 struct glyph_string
*s
;
2381 /* Nothing to do if background has already been drawn or if it
2382 shouldn't be drawn in the first place. */
2383 if (!s
->background_filled_p
)
2385 int box_line_width
= max (s
->face
->box_line_width
, 0);
2387 #if 0 /* MAC_TODO: stipple */
2390 /* Fill background with a stipple pattern. */
2391 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2392 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2393 s
->y
+ box_line_width
,
2394 s
->background_width
,
2395 s
->height
- 2 * box_line_width
);
2396 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2397 s
->background_filled_p
= 1;
2401 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2402 || s
->font_not_found_p
2403 || s
->extends_to_end_of_line_p
2406 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2407 s
->background_width
,
2408 s
->height
- 2 * box_line_width
);
2409 s
->background_filled_p
= 1;
2415 /* Draw the foreground of glyph string S. */
2418 x_draw_glyph_string_foreground (s
)
2419 struct glyph_string
*s
;
2423 /* If first glyph of S has a left box line, start drawing the text
2424 of S to the right of that box line. */
2425 if (s
->face
->box
!= FACE_NO_BOX
2426 && s
->first_glyph
->left_box_line_p
)
2427 x
= s
->x
+ abs (s
->face
->box_line_width
);
2431 /* Draw characters of S as rectangles if S's font could not be
2433 if (s
->font_not_found_p
)
2435 for (i
= 0; i
< s
->nchars
; ++i
)
2437 struct glyph
*g
= s
->first_glyph
+ i
;
2438 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2439 g
->pixel_width
- 1, s
->height
- 1);
2440 x
+= g
->pixel_width
;
2445 char *char1b
= (char *) s
->char2b
;
2446 int boff
= s
->font_info
->baseline_offset
;
2448 if (s
->font_info
->vertical_centering
)
2449 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2451 /* If we can use 8-bit functions, condense S->char2b. */
2454 && GC_FONT (s
->gc
)->mac_style
== NULL
2457 for (i
= 0; i
< s
->nchars
; ++i
)
2458 char1b
[i
] = s
->char2b
[i
].byte2
;
2460 /* Draw text with XDrawString if background has already been
2461 filled. Otherwise, use XDrawImageString. (Note that
2462 XDrawImageString is usually faster than XDrawString.) Always
2463 use XDrawImageString when drawing the cursor so that there is
2464 no chance that characters under a box cursor are invisible. */
2466 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2467 bg_width
= 0; /* Corresponds to XDrawString. */
2469 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2473 || GC_FONT (s
->gc
)->mac_style
2476 #if USE_CG_TEXT_DRAWING
2478 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2479 s
->char2b
, s
->nchars
, bg_width
))
2483 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2484 s
->char2b
, s
->nchars
, bg_width
);
2486 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2487 char1b
, s
->nchars
, bg_width
);
2491 /* Draw the foreground of composite glyph string S. */
2494 x_draw_composite_glyph_string_foreground (s
)
2495 struct glyph_string
*s
;
2499 /* If first glyph of S has a left box line, start drawing the text
2500 of S to the right of that box line. */
2501 if (s
->face
->box
!= FACE_NO_BOX
2502 && s
->first_glyph
->left_box_line_p
)
2503 x
= s
->x
+ abs (s
->face
->box_line_width
);
2507 /* S is a glyph string for a composition. S->gidx is the index of
2508 the first character drawn for glyphs of this composition.
2509 S->gidx == 0 means we are drawing the very first character of
2510 this composition. */
2512 /* Draw a rectangle for the composition if the font for the very
2513 first character of the composition could not be loaded. */
2514 if (s
->font_not_found_p
)
2517 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2518 s
->width
- 1, s
->height
- 1);
2522 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2523 mac_draw_string_16 (s
->f
, s
->gc
,
2524 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2525 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2531 #ifdef USE_X_TOOLKIT
2533 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2536 /* Return the frame on which widget WIDGET is used.. Abort if frame
2537 cannot be determined. */
2539 static struct frame
*
2540 x_frame_of_widget (widget
)
2543 struct x_display_info
*dpyinfo
;
2547 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2549 /* Find the top-level shell of the widget. Note that this function
2550 can be called when the widget is not yet realized, so XtWindow
2551 (widget) == 0. That's the reason we can't simply use
2552 x_any_window_to_frame. */
2553 while (!XtIsTopLevelShell (widget
))
2554 widget
= XtParent (widget
);
2556 /* Look for a frame with that top-level widget. Allocate the color
2557 on that frame to get the right gamma correction value. */
2558 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2559 if (GC_FRAMEP (XCAR (tail
))
2560 && (f
= XFRAME (XCAR (tail
)),
2561 (f
->output_data
.nothing
!= 1
2562 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2563 && f
->output_data
.x
->widget
== widget
)
2570 /* Allocate the color COLOR->pixel on the screen and display of
2571 widget WIDGET in colormap CMAP. If an exact match cannot be
2572 allocated, try the nearest color available. Value is non-zero
2573 if successful. This is called from lwlib. */
2576 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2581 struct frame
*f
= x_frame_of_widget (widget
);
2582 return x_alloc_nearest_color (f
, cmap
, color
);
2586 #endif /* USE_X_TOOLKIT */
2588 #if 0 /* MAC_TODO */
2590 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2591 CMAP. If an exact match can't be allocated, try the nearest color
2592 available. Value is non-zero if successful. Set *COLOR to the
2596 x_alloc_nearest_color (f
, cmap
, color
)
2601 Display
*display
= FRAME_X_DISPLAY (f
);
2602 Screen
*screen
= FRAME_X_SCREEN (f
);
2605 gamma_correct (f
, color
);
2606 rc
= XAllocColor (display
, cmap
, color
);
2609 /* If we got to this point, the colormap is full, so we're going
2610 to try to get the next closest color. The algorithm used is
2611 a least-squares matching, which is what X uses for closest
2612 color matching with StaticColor visuals. */
2614 unsigned long nearest_delta
= ~0;
2615 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2616 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2618 for (i
= 0; i
< ncells
; ++i
)
2620 XQueryColors (display
, cmap
, cells
, ncells
);
2622 for (nearest
= i
= 0; i
< ncells
; ++i
)
2624 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2625 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2626 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2627 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2629 if (delta
< nearest_delta
)
2632 nearest_delta
= delta
;
2636 color
->red
= cells
[nearest
].red
;
2637 color
->green
= cells
[nearest
].green
;
2638 color
->blue
= cells
[nearest
].blue
;
2639 rc
= XAllocColor (display
, cmap
, color
);
2642 #ifdef DEBUG_X_COLORS
2644 register_color (color
->pixel
);
2645 #endif /* DEBUG_X_COLORS */
2651 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2652 It's necessary to do this instead of just using PIXEL directly to
2653 get color reference counts right. */
2656 x_copy_color (f
, pixel
)
2658 unsigned long pixel
;
2662 color
.pixel
= pixel
;
2664 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2665 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2667 #ifdef DEBUG_X_COLORS
2668 register_color (pixel
);
2674 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2675 It's necessary to do this instead of just using PIXEL directly to
2676 get color reference counts right. */
2679 x_copy_dpy_color (dpy
, cmap
, pixel
)
2682 unsigned long pixel
;
2686 color
.pixel
= pixel
;
2688 XQueryColor (dpy
, cmap
, &color
);
2689 XAllocColor (dpy
, cmap
, &color
);
2691 #ifdef DEBUG_X_COLORS
2692 register_color (pixel
);
2697 #endif /* MAC_TODO */
2700 /* Brightness beyond which a color won't have its highlight brightness
2703 Nominally, highlight colors for `3d' faces are calculated by
2704 brightening an object's color by a constant scale factor, but this
2705 doesn't yield good results for dark colors, so for colors who's
2706 brightness is less than this value (on a scale of 0-255) have to
2707 use an additional additive factor.
2709 The value here is set so that the default menu-bar/mode-line color
2710 (grey75) will not have its highlights changed at all. */
2711 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2714 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2715 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2716 If this produces the same color as COLOR, try a color where all RGB
2717 values have DELTA added. Return the allocated color in *COLOR.
2718 DISPLAY is the X display, CMAP is the colormap to operate on.
2719 Value is non-zero if successful. */
2722 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2724 unsigned long *color
;
2731 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2734 /* Change RGB values by specified FACTOR. Avoid overflow! */
2735 xassert (factor
>= 0);
2736 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2737 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2738 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2740 /* Calculate brightness of COLOR. */
2741 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2742 + BLUE_FROM_ULONG (*color
)) / 6;
2744 /* We only boost colors that are darker than
2745 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2746 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2747 /* Make an additive adjustment to NEW, because it's dark enough so
2748 that scaling by FACTOR alone isn't enough. */
2750 /* How far below the limit this color is (0 - 1, 1 being darker). */
2751 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2752 /* The additive adjustment. */
2753 int min_delta
= delta
* dimness
* factor
/ 2;
2756 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2757 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2758 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2760 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2761 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2762 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2766 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2767 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2768 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2770 /* MAC_TODO: Map to palette and retry with delta if same? */
2771 /* MAC_TODO: Free colors (if using palette)? */
2782 /* Set up the foreground color for drawing relief lines of glyph
2783 string S. RELIEF is a pointer to a struct relief containing the GC
2784 with which lines will be drawn. Use a color that is FACTOR or
2785 DELTA lighter or darker than the relief's background which is found
2786 in S->f->output_data.x->relief_background. If such a color cannot
2787 be allocated, use DEFAULT_PIXEL, instead. */
2790 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2792 struct relief
*relief
;
2795 unsigned long default_pixel
;
2798 struct mac_output
*di
= f
->output_data
.mac
;
2799 unsigned long mask
= GCForeground
;
2800 unsigned long pixel
;
2801 unsigned long background
= di
->relief_background
;
2802 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2804 /* MAC_TODO: Free colors (if using palette)? */
2806 /* Allocate new color. */
2807 xgcv
.foreground
= default_pixel
;
2809 if (dpyinfo
->n_planes
!= 1
2810 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2812 relief
->allocated_p
= 1;
2813 xgcv
.foreground
= relief
->pixel
= pixel
;
2816 if (relief
->gc
== 0)
2818 #if 0 /* MAC_TODO: stipple */
2819 xgcv
.stipple
= dpyinfo
->gray
;
2822 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2825 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2829 /* Set up colors for the relief lines around glyph string S. */
2832 x_setup_relief_colors (s
)
2833 struct glyph_string
*s
;
2835 struct mac_output
*di
= s
->f
->output_data
.mac
;
2836 unsigned long color
;
2838 if (s
->face
->use_box_color_for_shadows_p
)
2839 color
= s
->face
->box_color
;
2840 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2842 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2843 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2848 /* Get the background color of the face. */
2849 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2850 color
= xgcv
.background
;
2853 if (di
->white_relief
.gc
== 0
2854 || color
!= di
->relief_background
)
2856 di
->relief_background
= color
;
2857 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2858 WHITE_PIX_DEFAULT (s
->f
));
2859 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2860 BLACK_PIX_DEFAULT (s
->f
));
2865 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2866 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2867 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2868 relief. LEFT_P non-zero means draw a relief on the left side of
2869 the rectangle. RIGHT_P non-zero means draw a relief on the right
2870 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2874 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2875 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2877 int left_x
, top_y
, right_x
, bottom_y
, width
;
2878 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2881 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2886 gc
= f
->output_data
.mac
->white_relief
.gc
;
2888 gc
= f
->output_data
.mac
->black_relief
.gc
;
2889 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2893 for (i
= 0; i
< width
; ++i
)
2894 mac_draw_line (f
, gc
,
2895 left_x
+ i
* left_p
, top_y
+ i
,
2896 right_x
- i
* right_p
, top_y
+ i
);
2900 for (i
= 0; i
< width
; ++i
)
2901 mac_draw_line (f
, gc
,
2902 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2904 mac_reset_clip_rectangles (dpy
, gc
);
2906 gc
= f
->output_data
.mac
->black_relief
.gc
;
2908 gc
= f
->output_data
.mac
->white_relief
.gc
;
2909 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2913 for (i
= 0; i
< width
; ++i
)
2914 mac_draw_line (f
, gc
,
2915 left_x
+ i
* left_p
, bottom_y
- i
,
2916 right_x
- i
* right_p
, bottom_y
- i
);
2920 for (i
= 0; i
< width
; ++i
)
2921 mac_draw_line (f
, gc
,
2922 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2924 mac_reset_clip_rectangles (dpy
, gc
);
2928 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2929 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2930 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2931 left side of the rectangle. RIGHT_P non-zero means draw a line
2932 on the right side of the rectangle. CLIP_RECT is the clipping
2933 rectangle to use when drawing. */
2936 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2937 left_p
, right_p
, clip_rect
)
2938 struct glyph_string
*s
;
2939 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2944 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2945 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2946 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2949 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2950 right_x
- left_x
+ 1, width
);
2954 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2955 width
, bottom_y
- top_y
+ 1);
2958 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2959 right_x
- left_x
+ 1, width
);
2963 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2964 top_y
, width
, bottom_y
- top_y
+ 1);
2966 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2967 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2971 /* Draw a box around glyph string S. */
2974 x_draw_glyph_string_box (s
)
2975 struct glyph_string
*s
;
2977 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2978 int left_p
, right_p
;
2979 struct glyph
*last_glyph
;
2982 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2983 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2984 : window_box_right (s
->w
, s
->area
));
2986 /* The glyph that may have a right box line. */
2987 last_glyph
= (s
->cmp
|| s
->img
2989 : s
->first_glyph
+ s
->nchars
- 1);
2991 width
= abs (s
->face
->box_line_width
);
2992 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2994 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2996 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2998 bottom_y
= top_y
+ s
->height
- 1;
3000 left_p
= (s
->first_glyph
->left_box_line_p
3001 || (s
->hl
== DRAW_MOUSE_FACE
3003 || s
->prev
->hl
!= s
->hl
)));
3004 right_p
= (last_glyph
->right_box_line_p
3005 || (s
->hl
== DRAW_MOUSE_FACE
3007 || s
->next
->hl
!= s
->hl
)));
3009 get_glyph_string_clip_rect (s
, &clip_rect
);
3011 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3012 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3013 left_p
, right_p
, &clip_rect
);
3016 x_setup_relief_colors (s
);
3017 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3018 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3023 /* Draw foreground of image glyph string S. */
3026 x_draw_image_foreground (s
)
3027 struct glyph_string
*s
;
3030 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3032 /* If first glyph of S has a left box line, start drawing it to the
3033 right of that line. */
3034 if (s
->face
->box
!= FACE_NO_BOX
3035 && s
->first_glyph
->left_box_line_p
3037 x
+= abs (s
->face
->box_line_width
);
3039 /* If there is a margin around the image, adjust x- and y-position
3041 if (s
->slice
.x
== 0)
3042 x
+= s
->img
->hmargin
;
3043 if (s
->slice
.y
== 0)
3044 y
+= s
->img
->vmargin
;
3048 x_set_glyph_string_clipping (s
);
3051 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3052 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3053 s
->slice
.width
, s
->slice
.height
, x
, y
);
3056 mac_copy_area (s
->img
->pixmap
,
3057 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3058 s
->slice
.width
, s
->slice
.height
, x
, y
);
3060 /* When the image has a mask, we can expect that at
3061 least part of a mouse highlight or a block cursor will
3062 be visible. If the image doesn't have a mask, make
3063 a block cursor visible by drawing a rectangle around
3064 the image. I believe it's looking better if we do
3065 nothing here for mouse-face. */
3066 if (s
->hl
== DRAW_CURSOR
)
3068 int r
= s
->img
->relief
;
3070 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3071 s
->slice
.width
+ r
*2 - 1,
3072 s
->slice
.height
+ r
*2 - 1);
3077 /* Draw a rectangle if image could not be loaded. */
3078 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3079 s
->slice
.width
- 1, s
->slice
.height
- 1);
3083 /* Draw a relief around the image glyph string S. */
3086 x_draw_image_relief (s
)
3087 struct glyph_string
*s
;
3089 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3092 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3094 /* If first glyph of S has a left box line, start drawing it to the
3095 right of that line. */
3096 if (s
->face
->box
!= FACE_NO_BOX
3097 && s
->first_glyph
->left_box_line_p
3099 x
+= abs (s
->face
->box_line_width
);
3101 /* If there is a margin around the image, adjust x- and y-position
3103 if (s
->slice
.x
== 0)
3104 x
+= s
->img
->hmargin
;
3105 if (s
->slice
.y
== 0)
3106 y
+= s
->img
->vmargin
;
3108 if (s
->hl
== DRAW_IMAGE_SUNKEN
3109 || s
->hl
== DRAW_IMAGE_RAISED
)
3111 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3112 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3116 thick
= abs (s
->img
->relief
);
3117 raised_p
= s
->img
->relief
> 0;
3122 x1
= x
+ s
->slice
.width
+ thick
- 1;
3123 y1
= y
+ s
->slice
.height
+ thick
- 1;
3125 x_setup_relief_colors (s
);
3126 get_glyph_string_clip_rect (s
, &r
);
3127 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3129 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3131 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3136 /* Draw part of the background of glyph string S. X, Y, W, and H
3137 give the rectangle to draw. */
3140 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3141 struct glyph_string
*s
;
3144 #if 0 /* MAC_TODO: stipple */
3147 /* Fill background with a stipple pattern. */
3148 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3149 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3150 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3153 #endif /* MAC_TODO */
3154 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3158 /* Draw image glyph string S.
3161 s->x +-------------------------
3164 | +-------------------------
3167 | | +-------------------
3173 x_draw_image_glyph_string (s
)
3174 struct glyph_string
*s
;
3177 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3178 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3182 height
= s
->height
- 2 * box_line_vwidth
;
3185 /* Fill background with face under the image. Do it only if row is
3186 taller than image or if image has a clip mask to reduce
3188 s
->stippled_p
= s
->face
->stipple
!= 0;
3189 if (height
> s
->slice
.height
3193 || s
->img
->pixmap
== 0
3194 || s
->width
!= s
->background_width
)
3197 if (s
->first_glyph
->left_box_line_p
3199 x
+= box_line_hwidth
;
3202 if (s
->slice
.y
== 0)
3203 y
+= box_line_vwidth
;
3205 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3207 s
->background_filled_p
= 1;
3210 /* Draw the foreground. */
3211 x_draw_image_foreground (s
);
3213 /* If we must draw a relief around the image, do it. */
3215 || s
->hl
== DRAW_IMAGE_RAISED
3216 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3217 x_draw_image_relief (s
);
3221 /* Draw stretch glyph string S. */
3224 x_draw_stretch_glyph_string (s
)
3225 struct glyph_string
*s
;
3227 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3228 s
->stippled_p
= s
->face
->stipple
!= 0;
3230 if (s
->hl
== DRAW_CURSOR
3231 && !x_stretch_cursor_p
)
3233 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3234 as wide as the stretch glyph. */
3235 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3238 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3240 /* Clear rest using the GC of the original non-cursor face. */
3241 if (width
< s
->background_width
)
3243 int x
= s
->x
+ width
, y
= s
->y
;
3244 int w
= s
->background_width
- width
, h
= s
->height
;
3248 if (s
->row
->mouse_face_p
3249 && cursor_in_mouse_face_p (s
->w
))
3251 x_set_mouse_face_gc (s
);
3257 get_glyph_string_clip_rect (s
, &r
);
3258 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3260 #if 0 /* MAC_TODO: stipple */
3261 if (s
->face
->stipple
)
3263 /* Fill background with a stipple pattern. */
3264 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3265 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3266 XSetFillStyle (s
->display
, gc
, FillSolid
);
3269 #endif /* MAC_TODO */
3270 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3273 else if (!s
->background_filled_p
)
3274 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3277 s
->background_filled_p
= 1;
3281 /* Draw glyph string S. */
3284 x_draw_glyph_string (s
)
3285 struct glyph_string
*s
;
3287 int relief_drawn_p
= 0;
3289 /* If S draws into the background of its successor that does not
3290 draw a cursor, draw the background of the successor first so that
3291 S can draw into it. This makes S->next use XDrawString instead
3292 of XDrawImageString. */
3293 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3294 && s
->next
->hl
!= DRAW_CURSOR
)
3296 xassert (s
->next
->img
== NULL
);
3297 x_set_glyph_string_gc (s
->next
);
3298 x_set_glyph_string_clipping (s
->next
);
3299 x_draw_glyph_string_background (s
->next
, 1);
3302 /* Set up S->gc, set clipping and draw S. */
3303 x_set_glyph_string_gc (s
);
3305 /* Draw relief (if any) in advance for char/composition so that the
3306 glyph string can be drawn over it. */
3307 if (!s
->for_overlaps
3308 && s
->face
->box
!= FACE_NO_BOX
3309 && (s
->first_glyph
->type
== CHAR_GLYPH
3310 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3313 x_set_glyph_string_clipping (s
);
3314 x_draw_glyph_string_background (s
, 1);
3315 x_draw_glyph_string_box (s
);
3316 x_set_glyph_string_clipping (s
);
3320 x_set_glyph_string_clipping (s
);
3322 switch (s
->first_glyph
->type
)
3325 x_draw_image_glyph_string (s
);
3329 x_draw_stretch_glyph_string (s
);
3333 if (s
->for_overlaps
)
3334 s
->background_filled_p
= 1;
3336 x_draw_glyph_string_background (s
, 0);
3337 x_draw_glyph_string_foreground (s
);
3340 case COMPOSITE_GLYPH
:
3341 if (s
->for_overlaps
|| s
->gidx
> 0)
3342 s
->background_filled_p
= 1;
3344 x_draw_glyph_string_background (s
, 1);
3345 x_draw_composite_glyph_string_foreground (s
);
3352 if (!s
->for_overlaps
)
3354 /* Draw underline. */
3355 if (s
->face
->underline_p
)
3357 unsigned long h
= 1;
3358 unsigned long dy
= s
->height
- h
;
3360 if (s
->face
->underline_defaulted_p
)
3361 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3366 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3367 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3368 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3370 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3374 /* Draw overline. */
3375 if (s
->face
->overline_p
)
3377 unsigned long dy
= 0, h
= 1;
3379 if (s
->face
->overline_color_defaulted_p
)
3380 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3385 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3386 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3387 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3389 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3393 /* Draw strike-through. */
3394 if (s
->face
->strike_through_p
)
3396 unsigned long h
= 1;
3397 unsigned long dy
= (s
->height
- h
) / 2;
3399 if (s
->face
->strike_through_color_defaulted_p
)
3400 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3405 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3406 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3407 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3409 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3413 /* Draw relief if not yet drawn. */
3414 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3415 x_draw_glyph_string_box (s
);
3418 /* Reset clipping. */
3419 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3422 /* Shift display to make room for inserted glyphs. */
3425 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3427 int x
, y
, width
, height
, shift_by
;
3429 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3430 x
, y
, width
, height
,
3434 /* Delete N glyphs at the nominal cursor position. Not implemented
3445 /* Clear entire frame. If updating_frame is non-null, clear that
3446 frame. Otherwise clear the selected frame. */
3456 f
= SELECTED_FRAME ();
3458 /* Clearing the frame will erase any cursor, so mark them all as no
3460 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3461 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3462 output_cursor
.x
= -1;
3464 /* We don't set the output cursor here because there will always
3465 follow an explicit cursor_to. */
3467 mac_clear_window (f
);
3469 /* We have to clear the scroll bars, too. If we have changed
3470 colors or something like that, then they should be notified. */
3471 x_scroll_bar_clear (f
);
3473 XFlush (FRAME_MAC_DISPLAY (f
));
3479 /* Invert the middle quarter of the frame for .15 sec. */
3481 /* We use the select system call to do the waiting, so we have to make
3482 sure it's available. If it isn't, we just won't do visual bells. */
3484 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3487 /* Subtract the `struct timeval' values X and Y, storing the result in
3488 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3491 timeval_subtract (result
, x
, y
)
3492 struct timeval
*result
, x
, y
;
3494 /* Perform the carry for the later subtraction by updating y. This
3495 is safer because on some systems the tv_sec member is unsigned. */
3496 if (x
.tv_usec
< y
.tv_usec
)
3498 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3499 y
.tv_usec
-= 1000000 * nsec
;
3503 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3505 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3506 y
.tv_usec
+= 1000000 * nsec
;
3510 /* Compute the time remaining to wait. tv_usec is certainly
3512 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3513 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3515 /* Return indication of whether the result should be considered
3517 return x
.tv_sec
< y
.tv_sec
;
3524 /* Get the height not including a menu bar widget. */
3525 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3526 /* Height of each line to flash. */
3527 int flash_height
= FRAME_LINE_HEIGHT (f
);
3528 /* These will be the left and right margins of the rectangles. */
3529 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3530 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3534 /* Don't flash the area between a scroll bar and the frame
3535 edge it is next to. */
3536 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3538 case vertical_scroll_bar_left
:
3539 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3542 case vertical_scroll_bar_right
:
3543 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3550 width
= flash_right
- flash_left
;
3554 /* If window is tall, flash top and bottom line. */
3555 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3557 mac_invert_rectangle (f
, flash_left
,
3558 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3559 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3560 width
, flash_height
);
3561 mac_invert_rectangle (f
, flash_left
,
3562 (height
- flash_height
3563 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3564 width
, flash_height
);
3567 /* If it is short, flash it all. */
3568 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3569 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3574 struct timeval wakeup
;
3576 EMACS_GET_TIME (wakeup
);
3578 /* Compute time to wait until, propagating carry from usecs. */
3579 wakeup
.tv_usec
+= 150000;
3580 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3581 wakeup
.tv_usec
%= 1000000;
3583 /* Keep waiting until past the time wakeup or any input gets
3585 while (! detect_input_pending ())
3587 struct timeval current
;
3588 struct timeval timeout
;
3590 EMACS_GET_TIME (current
);
3592 /* Break if result would be negative. */
3593 if (timeval_subtract (¤t
, wakeup
, current
))
3596 /* How long `select' should wait. */
3598 timeout
.tv_usec
= 10000;
3600 /* Try to wait that long--but we might wake up sooner. */
3601 select (0, NULL
, NULL
, NULL
, &timeout
);
3605 /* If window is tall, flash top and bottom line. */
3606 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3608 mac_invert_rectangle (f
, flash_left
,
3609 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3610 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3611 width
, flash_height
);
3612 mac_invert_rectangle (f
, flash_left
,
3613 (height
- flash_height
3614 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3615 width
, flash_height
);
3618 /* If it is short, flash it all. */
3619 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3620 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3627 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3630 /* Make audible bell. */
3635 struct frame
*f
= SELECTED_FRAME ();
3637 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3645 XFlush (FRAME_MAC_DISPLAY (f
));
3651 /* Specify how many text lines, from the top of the window,
3652 should be affected by insert-lines and delete-lines operations.
3653 This, and those operations, are used only within an update
3654 that is bounded by calls to x_update_begin and x_update_end. */
3657 XTset_terminal_window (n
)
3660 /* This function intentionally left blank. */
3665 /***********************************************************************
3667 ***********************************************************************/
3669 /* Perform an insert-lines or delete-lines operation, inserting N
3670 lines or deleting -N lines at vertical position VPOS. */
3673 x_ins_del_lines (vpos
, n
)
3680 /* Scroll part of the display as described by RUN. */
3683 x_scroll_run (w
, run
)
3687 struct frame
*f
= XFRAME (w
->frame
);
3688 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3690 /* Get frame-relative bounding box of the text display area of W,
3691 without mode lines. Include in this box the left and right
3693 window_box (w
, -1, &x
, &y
, &width
, &height
);
3695 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3696 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3697 bottom_y
= y
+ height
;
3701 /* Scrolling up. Make sure we don't copy part of the mode
3702 line at the bottom. */
3703 if (from_y
+ run
->height
> bottom_y
)
3704 height
= bottom_y
- from_y
;
3706 height
= run
->height
;
3710 /* Scolling down. Make sure we don't copy over the mode line.
3712 if (to_y
+ run
->height
> bottom_y
)
3713 height
= bottom_y
- to_y
;
3715 height
= run
->height
;
3720 /* Cursor off. Will be switched on again in x_update_window_end. */
3724 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3734 /***********************************************************************
3736 ***********************************************************************/
3744 ControlRef root_control
;
3747 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3749 ActivateControl (root_control
);
3751 x_update_cursor (f
, 1);
3755 frame_unhighlight (f
)
3759 ControlRef root_control
;
3762 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3764 DeactivateControl (root_control
);
3766 x_update_cursor (f
, 1);
3769 /* The focus has changed. Update the frames as necessary to reflect
3770 the new situation. Note that we can't change the selected frame
3771 here, because the Lisp code we are interrupting might become confused.
3772 Each event gets marked with the frame in which it occurred, so the
3773 Lisp code can tell when the switch took place by examining the events. */
3776 x_new_focus_frame (dpyinfo
, frame
)
3777 struct x_display_info
*dpyinfo
;
3778 struct frame
*frame
;
3780 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3782 if (frame
!= dpyinfo
->x_focus_frame
)
3784 /* Set this before calling other routines, so that they see
3785 the correct value of x_focus_frame. */
3786 dpyinfo
->x_focus_frame
= frame
;
3788 if (old_focus
&& old_focus
->auto_lower
)
3789 x_lower_frame (old_focus
);
3792 selected_frame
= frame
;
3793 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3795 Fselect_window (selected_frame
->selected_window
, Qnil
);
3796 choose_minibuf_frame ();
3799 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3800 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3802 pending_autoraise_frame
= 0;
3805 x_frame_rehighlight (dpyinfo
);
3808 /* Handle FocusIn and FocusOut state changes for FRAME.
3809 If FRAME has focus and there exists more than one frame, puts
3810 a FOCUS_IN_EVENT into *BUFP. */
3813 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3815 struct mac_display_info
*dpyinfo
;
3816 struct frame
*frame
;
3817 struct input_event
*bufp
;
3819 if (type
== activeFlag
)
3821 if (dpyinfo
->x_focus_event_frame
!= frame
)
3823 x_new_focus_frame (dpyinfo
, frame
);
3824 dpyinfo
->x_focus_event_frame
= frame
;
3826 /* Don't stop displaying the initial startup message
3827 for a switch-frame event we don't need. */
3828 if (GC_NILP (Vterminal_frame
)
3829 && GC_CONSP (Vframe_list
)
3830 && !GC_NILP (XCDR (Vframe_list
)))
3832 bufp
->kind
= FOCUS_IN_EVENT
;
3833 XSETFRAME (bufp
->frame_or_window
, frame
);
3839 if (dpyinfo
->x_focus_event_frame
== frame
)
3841 dpyinfo
->x_focus_event_frame
= 0;
3842 x_new_focus_frame (dpyinfo
, 0);
3847 /* The focus may have changed. Figure out if it is a real focus change,
3848 by checking both FocusIn/Out and Enter/LeaveNotify events.
3850 Returns FOCUS_IN_EVENT event in *BUFP. */
3853 x_detect_focus_change (dpyinfo
, event
, bufp
)
3854 struct mac_display_info
*dpyinfo
;
3856 struct input_event
*bufp
;
3858 struct frame
*frame
;
3860 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3864 /* On Mac, this is only called from focus events, so no switch needed. */
3865 mac_focus_changed ((event
->modifiers
& activeFlag
),
3866 dpyinfo
, frame
, bufp
);
3870 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3873 x_mouse_leave (dpyinfo
)
3874 struct x_display_info
*dpyinfo
;
3876 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3879 /* The focus has changed, or we have redirected a frame's focus to
3880 another frame (this happens when a frame uses a surrogate
3881 mini-buffer frame). Shift the highlight as appropriate.
3883 The FRAME argument doesn't necessarily have anything to do with which
3884 frame is being highlighted or un-highlighted; we only use it to find
3885 the appropriate X display info. */
3888 XTframe_rehighlight (frame
)
3889 struct frame
*frame
;
3891 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3895 x_frame_rehighlight (dpyinfo
)
3896 struct x_display_info
*dpyinfo
;
3898 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3900 if (dpyinfo
->x_focus_frame
)
3902 dpyinfo
->x_highlight_frame
3903 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3904 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3905 : dpyinfo
->x_focus_frame
);
3906 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3908 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3909 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3913 dpyinfo
->x_highlight_frame
= 0;
3915 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3918 frame_unhighlight (old_highlight
);
3919 if (dpyinfo
->x_highlight_frame
)
3920 frame_highlight (dpyinfo
->x_highlight_frame
);
3926 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3928 #if 0 /* MAC_TODO */
3929 /* Initialize mode_switch_bit and modifier_meaning. */
3931 x_find_modifier_meanings (dpyinfo
)
3932 struct x_display_info
*dpyinfo
;
3934 int min_code
, max_code
;
3937 XModifierKeymap
*mods
;
3939 dpyinfo
->meta_mod_mask
= 0;
3940 dpyinfo
->shift_lock_mask
= 0;
3941 dpyinfo
->alt_mod_mask
= 0;
3942 dpyinfo
->super_mod_mask
= 0;
3943 dpyinfo
->hyper_mod_mask
= 0;
3946 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3948 min_code
= dpyinfo
->display
->min_keycode
;
3949 max_code
= dpyinfo
->display
->max_keycode
;
3952 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3953 min_code
, max_code
- min_code
+ 1,
3955 mods
= XGetModifierMapping (dpyinfo
->display
);
3957 /* Scan the modifier table to see which modifier bits the Meta and
3958 Alt keysyms are on. */
3960 int row
, col
; /* The row and column in the modifier table. */
3962 for (row
= 3; row
< 8; row
++)
3963 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3966 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3968 /* Zeroes are used for filler. Skip them. */
3972 /* Are any of this keycode's keysyms a meta key? */
3976 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3978 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3984 dpyinfo
->meta_mod_mask
|= (1 << row
);
3989 dpyinfo
->alt_mod_mask
|= (1 << row
);
3994 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3999 dpyinfo
->super_mod_mask
|= (1 << row
);
4003 /* Ignore this if it's not on the lock modifier. */
4004 if ((1 << row
) == LockMask
)
4005 dpyinfo
->shift_lock_mask
= LockMask
;
4013 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4014 if (! dpyinfo
->meta_mod_mask
)
4016 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
4017 dpyinfo
->alt_mod_mask
= 0;
4020 /* If some keys are both alt and meta,
4021 make them just meta, not alt. */
4022 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4024 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4027 XFree ((char *) syms
);
4028 XFreeModifiermap (mods
);
4031 #endif /* MAC_TODO */
4033 /* Convert between the modifier bits X uses and the modifier bits
4037 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4038 struct x_display_info
*dpyinfo
;
4039 unsigned short state
;
4041 return (((state
& shiftKey
) ? shift_modifier
: 0)
4042 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4043 | ((state
& cmdKey
) ? meta_modifier
: 0)
4044 | ((state
& optionKey
) ? alt_modifier
: 0));
4047 #if 0 /* MAC_TODO */
4048 static unsigned short
4049 x_emacs_to_x_modifiers (dpyinfo
, state
)
4050 struct x_display_info
*dpyinfo
;
4053 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4054 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4055 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4056 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4057 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4058 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4060 #endif /* MAC_TODO */
4062 /* Convert a keysym to its name. */
4065 x_get_keysym_name (keysym
)
4072 value
= XKeysymToString (keysym
);
4083 /* Function to report a mouse movement to the mainstream Emacs code.
4084 The input handler calls this.
4086 We have received a mouse movement event, which is given in *event.
4087 If the mouse is over a different glyph than it was last time, tell
4088 the mainstream emacs code by setting mouse_moved. If not, ask for
4089 another motion event, so we can check again the next time it moves. */
4091 static Point last_mouse_motion_position
;
4092 static Lisp_Object last_mouse_motion_frame
;
4095 note_mouse_movement (frame
, pos
)
4099 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4100 #if TARGET_API_MAC_CARBON
4104 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4105 last_mouse_motion_position
= *pos
;
4106 XSETFRAME (last_mouse_motion_frame
, frame
);
4108 #if TARGET_API_MAC_CARBON
4109 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4111 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4114 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4115 /* This case corresponds to LeaveNotify in X11. */
4117 /* If we move outside the frame, then we're certainly no
4118 longer on any text in the frame. */
4119 clear_mouse_face (dpyinfo
);
4120 dpyinfo
->mouse_face_mouse_frame
= 0;
4121 if (!dpyinfo
->grabbed
)
4122 rif
->define_frame_cursor (frame
,
4123 frame
->output_data
.mac
->nontext_cursor
);
4127 /* Has the mouse moved off the glyph it was on at the last sighting? */
4128 if (frame
!= last_mouse_glyph_frame
4129 || !PtInRect (*pos
, &last_mouse_glyph
))
4131 frame
->mouse_moved
= 1;
4132 last_mouse_scroll_bar
= Qnil
;
4133 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4134 /* Remember which glyph we're now on. */
4135 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4136 last_mouse_glyph_frame
= frame
;
4144 /************************************************************************
4146 ************************************************************************/
4148 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4151 redo_mouse_highlight ()
4153 if (!NILP (last_mouse_motion_frame
)
4154 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4155 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4156 last_mouse_motion_position
.h
,
4157 last_mouse_motion_position
.v
);
4161 static struct frame
*
4162 mac_focus_frame (dpyinfo
)
4163 struct mac_display_info
*dpyinfo
;
4165 if (dpyinfo
->x_focus_frame
)
4166 return dpyinfo
->x_focus_frame
;
4168 /* Mac version may get events, such as a menu bar click, even when
4169 all the frames are invisible. In this case, we regard the
4170 event came to the selected frame. */
4171 return SELECTED_FRAME ();
4175 /* Return the current position of the mouse.
4176 *FP should be a frame which indicates which display to ask about.
4178 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4179 and *PART to the frame, window, and scroll bar part that the mouse
4180 is over. Set *X and *Y to the portion and whole of the mouse's
4181 position on the scroll bar.
4183 If the mouse movement started elsewhere, set *FP to the frame the
4184 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4187 Set *TIME to the server time-stamp for the time at which the mouse
4188 was at this position.
4190 Don't store anything if we don't have a valid set of values to report.
4192 This clears the mouse_moved flag, so we can wait for the next mouse
4196 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4199 Lisp_Object
*bar_window
;
4200 enum scroll_bar_part
*part
;
4202 unsigned long *time
;
4208 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4209 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4212 Lisp_Object frame
, tail
;
4214 /* Clear the mouse-moved flag for every frame on this display. */
4215 FOR_EACH_FRAME (tail
, frame
)
4216 XFRAME (frame
)->mouse_moved
= 0;
4218 last_mouse_scroll_bar
= Qnil
;
4220 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4221 && FRAME_LIVE_P (last_mouse_frame
))
4222 f1
= last_mouse_frame
;
4224 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4228 /* Ok, we found a frame. Store all the values.
4229 last_mouse_glyph is a rectangle used to reduce the
4230 generation of mouse events. To not miss any motion
4231 events, we must divide the frame into rectangles of the
4232 size of the smallest character that could be displayed
4233 on it, i.e. into the same rectangles that matrices on
4234 the frame are divided into. */
4237 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4238 GetMouse (&mouse_pos
);
4239 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4241 last_mouse_glyph_frame
= f1
;
4246 XSETINT (*x
, mouse_pos
.h
);
4247 XSETINT (*y
, mouse_pos
.v
);
4248 *time
= last_mouse_movement_time
;
4256 /************************************************************************
4258 ************************************************************************/
4260 #ifdef USE_TOOLKIT_SCROLL_BARS
4262 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4263 static OSStatus install_scroll_bar_timer
P_ ((void));
4264 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4265 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4266 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4267 struct input_event
*));
4268 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4270 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4272 struct input_event
*));
4273 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4274 struct input_event
*));
4275 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4276 Point
, struct input_event
*));
4277 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4280 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4282 static int last_scroll_bar_part
;
4284 static EventLoopTimerRef scroll_bar_timer
;
4286 static int scroll_bar_timer_event_posted_p
;
4288 #define SCROLL_BAR_FIRST_DELAY 0.5
4289 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4292 scroll_bar_timer_callback (timer
, data
)
4293 EventLoopTimerRef timer
;
4296 EventRef event
= NULL
;
4299 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4300 kEventAttributeNone
, &event
);
4305 GetMouse (&mouse_pos
);
4306 LocalToGlobal (&mouse_pos
);
4307 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4308 sizeof (Point
), &mouse_pos
);
4312 UInt32 modifiers
= GetCurrentKeyModifiers ();
4314 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4315 sizeof (UInt32
), &modifiers
);
4318 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4319 kEventPriorityStandard
);
4321 scroll_bar_timer_event_posted_p
= 1;
4324 ReleaseEvent (event
);
4328 install_scroll_bar_timer ()
4330 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4332 if (scroll_bar_timer_callbackUPP
== NULL
)
4333 scroll_bar_timer_callbackUPP
=
4334 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4336 if (scroll_bar_timer
== NULL
)
4337 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4338 kEventDurationForever as delays. */
4340 InstallEventLoopTimer (GetCurrentEventLoop (),
4341 kEventDurationForever
, kEventDurationForever
,
4342 scroll_bar_timer_callbackUPP
, NULL
,
4347 set_scroll_bar_timer (delay
)
4348 EventTimerInterval delay
;
4350 if (scroll_bar_timer
== NULL
)
4351 install_scroll_bar_timer ();
4353 scroll_bar_timer_event_posted_p
= 0;
4355 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4359 control_part_code_to_scroll_bar_part (part_code
)
4360 ControlPartCode part_code
;
4364 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4365 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4366 case kControlPageUpPart
: return scroll_bar_above_handle
;
4367 case kControlPageDownPart
: return scroll_bar_below_handle
;
4368 case kControlIndicatorPart
: return scroll_bar_handle
;
4375 construct_scroll_bar_click (bar
, part
, bufp
)
4376 struct scroll_bar
*bar
;
4378 struct input_event
*bufp
;
4380 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4381 bufp
->frame_or_window
= bar
->window
;
4385 XSETINT (bufp
->x
, 0);
4386 XSETINT (bufp
->y
, 0);
4387 bufp
->modifiers
= 0;
4391 get_control_part_bounds (ch
, part_code
, rect
)
4393 ControlPartCode part_code
;
4396 RgnHandle region
= NewRgn ();
4399 err
= GetControlRegion (ch
, part_code
, region
);
4401 GetRegionBounds (region
, rect
);
4402 DisposeRgn (region
);
4408 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4409 struct scroll_bar
*bar
;
4410 ControlPartCode part_code
;
4411 struct input_event
*bufp
;
4413 int part
= control_part_code_to_scroll_bar_part (part_code
);
4418 if (part
!= scroll_bar_handle
)
4420 construct_scroll_bar_click (bar
, part
, bufp
);
4421 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4422 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4425 last_scroll_bar_part
= part
;
4426 bar
->dragging
= Qnil
;
4427 tracked_scroll_bar
= bar
;
4431 x_scroll_bar_handle_release (bar
, bufp
)
4432 struct scroll_bar
*bar
;
4433 struct input_event
*bufp
;
4435 if (last_scroll_bar_part
!= scroll_bar_handle
4436 || !GC_NILP (bar
->dragging
))
4437 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4439 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4440 set_scroll_bar_timer (kEventDurationForever
);
4442 last_scroll_bar_part
= -1;
4443 bar
->dragging
= Qnil
;
4444 tracked_scroll_bar
= NULL
;
4448 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4450 struct scroll_bar
*bar
;
4452 struct input_event
*bufp
;
4454 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4456 if (last_scroll_bar_part
== scroll_bar_handle
)
4461 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4462 kControlIndicatorPart
, &r
);
4464 if (GC_NILP (bar
->dragging
))
4465 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4467 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4468 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4469 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4474 if (top
> top_range
)
4477 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4478 XSETINT (bufp
->x
, top
);
4479 XSETINT (bufp
->y
, top_range
);
4483 ControlPartCode part_code
;
4484 int unhilite_p
= 0, part
;
4486 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4490 part
= control_part_code_to_scroll_bar_part (part_code
);
4492 switch (last_scroll_bar_part
)
4494 case scroll_bar_above_handle
:
4495 case scroll_bar_below_handle
:
4496 if (part
!= scroll_bar_above_handle
4497 && part
!= scroll_bar_below_handle
)
4501 case scroll_bar_up_arrow
:
4502 case scroll_bar_down_arrow
:
4503 if (part
!= scroll_bar_up_arrow
4504 && part
!= scroll_bar_down_arrow
)
4511 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4512 else if (part
!= last_scroll_bar_part
4513 || scroll_bar_timer_event_posted_p
)
4515 construct_scroll_bar_click (bar
, part
, bufp
);
4516 last_scroll_bar_part
= part
;
4517 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4518 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4523 /* Set the thumb size and position of scroll bar BAR. We are currently
4524 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4527 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4528 struct scroll_bar
*bar
;
4529 int portion
, position
, whole
;
4531 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4532 int value
, viewsize
, maximum
;
4534 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4535 value
= 0, viewsize
= 1, maximum
= 0;
4540 maximum
= max (0, whole
- portion
);
4545 if (IsControlVisible (ch
)
4546 && (GetControlViewSize (ch
) != viewsize
4547 || GetControl32BitValue (ch
) != value
4548 || GetControl32BitMaximum (ch
) != maximum
))
4550 /* Temporarily hide the scroll bar to avoid multiple redraws. */
4551 SetControlVisibility (ch
, false, false);
4553 SetControl32BitMaximum (ch
, maximum
);
4554 SetControl32BitValue (ch
, value
);
4555 SetControlViewSize (ch
, viewsize
);
4557 SetControlVisibility (ch
, true, true);
4563 #endif /* USE_TOOLKIT_SCROLL_BARS */
4567 /************************************************************************
4568 Scroll bars, general
4569 ************************************************************************/
4571 /* Create a scroll bar and return the scroll bar vector for it. W is
4572 the Emacs window on which to create the scroll bar. TOP, LEFT,
4573 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4576 static struct scroll_bar
*
4577 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4579 int top
, left
, width
, height
, disp_top
, disp_height
;
4581 struct frame
*f
= XFRAME (w
->frame
);
4582 struct scroll_bar
*bar
4583 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4591 r
.right
= left
+ width
;
4592 r
.bottom
= disp_top
+ disp_height
;
4594 #if TARGET_API_MAC_CARBON
4595 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4596 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4598 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4599 0, 0, 0, scrollBarProc
, (long) bar
);
4601 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4603 XSETWINDOW (bar
->window
, w
);
4604 XSETINT (bar
->top
, top
);
4605 XSETINT (bar
->left
, left
);
4606 XSETINT (bar
->width
, width
);
4607 XSETINT (bar
->height
, height
);
4608 XSETINT (bar
->start
, 0);
4609 XSETINT (bar
->end
, 0);
4610 bar
->dragging
= Qnil
;
4611 #ifdef USE_TOOLKIT_SCROLL_BARS
4612 bar
->track_top
= Qnil
;
4613 bar
->track_height
= Qnil
;
4616 /* Add bar to its frame's list of scroll bars. */
4617 bar
->next
= FRAME_SCROLL_BARS (f
);
4619 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4620 if (!NILP (bar
->next
))
4621 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4628 /* Draw BAR's handle in the proper position.
4630 If the handle is already drawn from START to END, don't bother
4631 redrawing it, unless REBUILD is non-zero; in that case, always
4632 redraw it. (REBUILD is handy for drawing the handle after expose
4635 Normally, we want to constrain the start and end of the handle to
4636 fit inside its rectangle, but if the user is dragging the scroll
4637 bar handle, we want to let them drag it down all the way, so that
4638 the bar's top is as far down as it goes; otherwise, there's no way
4639 to move to the very end of the buffer. */
4641 #ifndef USE_TOOLKIT_SCROLL_BARS
4644 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4645 struct scroll_bar
*bar
;
4649 int dragging
= ! NILP (bar
->dragging
);
4650 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4651 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4652 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4653 int length
= end
- start
;
4655 /* If the display is already accurate, do nothing. */
4657 && start
== XINT (bar
->start
)
4658 && end
== XINT (bar
->end
))
4663 /* Make sure the values are reasonable, and try to preserve the
4664 distance between start and end. */
4667 else if (start
> top_range
)
4669 end
= start
+ length
;
4673 else if (end
> top_range
&& ! dragging
)
4676 /* Store the adjusted setting in the scroll bar. */
4677 XSETINT (bar
->start
, start
);
4678 XSETINT (bar
->end
, end
);
4680 /* Clip the end position, just for display. */
4681 if (end
> top_range
)
4684 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4685 top positions, to make sure the handle is always at least that
4686 many pixels tall. */
4687 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4689 SetControlMinimum (ch
, 0);
4690 /* Don't inadvertently activate deactivated scroll bars */
4691 if (GetControlMaximum (ch
) != -1)
4692 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4694 SetControlValue (ch
, start
);
4695 #if TARGET_API_MAC_CARBON
4696 SetControlViewSize (ch
, end
- start
);
4702 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4704 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4708 x_scroll_bar_remove (bar
)
4709 struct scroll_bar
*bar
;
4711 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4715 /* Destroy the Mac scroll bar control */
4716 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4718 /* Disassociate this scroll bar from its window. */
4719 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4725 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4726 that we are displaying PORTION characters out of a total of WHOLE
4727 characters, starting at POSITION. If WINDOW has no scroll bar,
4731 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4733 int portion
, whole
, position
;
4735 struct frame
*f
= XFRAME (w
->frame
);
4736 struct scroll_bar
*bar
;
4737 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4738 int window_y
, window_height
;
4740 /* Get window dimensions. */
4741 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4743 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4744 height
= window_height
;
4746 /* Compute the left edge of the scroll bar area. */
4747 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4749 /* Compute the width of the scroll bar which might be less than
4750 the width of the area reserved for the scroll bar. */
4751 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4752 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4756 /* Compute the left edge of the scroll bar. */
4757 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4760 sb_left
= left
+ width
- sb_width
;
4762 /* Adjustments according to Inside Macintosh to make it look nice */
4764 disp_height
= height
;
4770 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4776 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4779 /* Does the scroll bar exist yet? */
4780 if (NILP (w
->vertical_scroll_bar
))
4783 mac_clear_area (f
, left
, top
, width
, height
);
4785 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4787 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4791 /* It may just need to be moved and resized. */
4794 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4795 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4799 /* If already correctly positioned, do nothing. */
4800 if (!(XINT (bar
->left
) == sb_left
4801 && XINT (bar
->top
) == top
4802 && XINT (bar
->width
) == sb_width
4803 && XINT (bar
->height
) == height
))
4805 /* Since toolkit scroll bars are smaller than the space reserved
4806 for them on the frame, we have to clear "under" them. */
4807 mac_clear_area (f
, left
, top
, width
, height
);
4810 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4811 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4813 if (sb_width
< disp_height
)
4816 /* Remember new settings. */
4817 XSETINT (bar
->left
, sb_left
);
4818 XSETINT (bar
->top
, top
);
4819 XSETINT (bar
->width
, sb_width
);
4820 XSETINT (bar
->height
, height
);
4821 #ifdef USE_TOOLKIT_SCROLL_BARS
4822 bar
->track_top
= Qnil
;
4823 bar
->track_height
= Qnil
;
4830 #ifdef USE_TOOLKIT_SCROLL_BARS
4831 if (NILP (bar
->track_top
))
4833 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4838 SetControl32BitMinimum (ch
, 0);
4839 SetControl32BitMaximum (ch
, 1);
4840 SetControlViewSize (ch
, 1);
4842 /* Move the scroll bar thumb to the top. */
4843 SetControl32BitValue (ch
, 0);
4844 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4846 /* Move the scroll bar thumb to the bottom. */
4847 SetControl32BitValue (ch
, 1);
4848 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4850 UnionRect (&r0
, &r1
, &r0
);
4851 XSETINT (bar
->track_top
, r0
.top
);
4852 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4857 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4858 #else /* not USE_TOOLKIT_SCROLL_BARS */
4859 /* Set the scroll bar's current state, unless we're currently being
4861 if (NILP (bar
->dragging
))
4863 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4866 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4869 int start
= ((double) position
* top_range
) / whole
;
4870 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4871 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4874 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4878 /* The following three hooks are used when we're doing a thorough
4879 redisplay of the frame. We don't explicitly know which scroll bars
4880 are going to be deleted, because keeping track of when windows go
4881 away is a real pain - "Can you say set-window-configuration, boys
4882 and girls?" Instead, we just assert at the beginning of redisplay
4883 that *all* scroll bars are to be removed, and then save a scroll bar
4884 from the fiery pit when we actually redisplay its window. */
4886 /* Arrange for all scroll bars on FRAME to be removed at the next call
4887 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4888 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4891 XTcondemn_scroll_bars (frame
)
4894 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4895 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4898 bar
= FRAME_SCROLL_BARS (frame
);
4899 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4900 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4901 XSCROLL_BAR (bar
)->prev
= Qnil
;
4902 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4903 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4904 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4909 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4910 Note that WINDOW isn't necessarily condemned at all. */
4913 XTredeem_scroll_bar (window
)
4914 struct window
*window
;
4916 struct scroll_bar
*bar
;
4919 /* We can't redeem this window's scroll bar if it doesn't have one. */
4920 if (NILP (window
->vertical_scroll_bar
))
4923 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4925 /* Unlink it from the condemned list. */
4926 f
= XFRAME (WINDOW_FRAME (window
));
4927 if (NILP (bar
->prev
))
4929 /* If the prev pointer is nil, it must be the first in one of
4931 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4932 /* It's not condemned. Everything's fine. */
4934 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4935 window
->vertical_scroll_bar
))
4936 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4938 /* If its prev pointer is nil, it must be at the front of
4939 one or the other! */
4943 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4945 if (! NILP (bar
->next
))
4946 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4948 bar
->next
= FRAME_SCROLL_BARS (f
);
4950 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4951 if (! NILP (bar
->next
))
4952 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4955 /* Remove all scroll bars on FRAME that haven't been saved since the
4956 last call to `*condemn_scroll_bars_hook'. */
4959 XTjudge_scroll_bars (f
)
4962 Lisp_Object bar
, next
;
4964 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4966 /* Clear out the condemned list now so we won't try to process any
4967 more events on the hapless scroll bars. */
4968 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4970 for (; ! NILP (bar
); bar
= next
)
4972 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4974 x_scroll_bar_remove (b
);
4977 b
->next
= b
->prev
= Qnil
;
4980 /* Now there should be no references to the condemned scroll bars,
4981 and they should get garbage-collected. */
4985 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4986 is set to something other than NO_EVENT, it is enqueued.
4988 This may be called from a signal handler, so we have to ignore GC
4992 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4993 struct scroll_bar
*bar
;
4994 ControlPartCode part_code
;
4996 struct input_event
*bufp
;
4998 int win_y
, top_range
;
5000 if (! GC_WINDOWP (bar
->window
))
5003 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5004 bufp
->frame_or_window
= bar
->window
;
5007 bar
->dragging
= Qnil
;
5011 case kControlUpButtonPart
:
5012 bufp
->part
= scroll_bar_up_arrow
;
5014 case kControlDownButtonPart
:
5015 bufp
->part
= scroll_bar_down_arrow
;
5017 case kControlPageUpPart
:
5018 bufp
->part
= scroll_bar_above_handle
;
5020 case kControlPageDownPart
:
5021 bufp
->part
= scroll_bar_below_handle
;
5023 #if TARGET_API_MAC_CARBON
5026 case kControlIndicatorPart
:
5028 if (er
->what
== mouseDown
)
5029 bar
->dragging
= make_number (0);
5030 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5031 bufp
->part
= scroll_bar_handle
;
5035 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5036 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5038 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5042 if (! NILP (bar
->dragging
))
5043 win_y
-= XINT (bar
->dragging
);
5047 if (win_y
> top_range
)
5050 XSETINT (bufp
->x
, win_y
);
5051 XSETINT (bufp
->y
, top_range
);
5054 #ifndef USE_TOOLKIT_SCROLL_BARS
5056 /* Handle some mouse motion while someone is dragging the scroll bar.
5058 This may be called from a signal handler, so we have to ignore GC
5062 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5063 struct scroll_bar
*bar
;
5067 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5069 last_mouse_movement_time
= t
;
5072 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5074 /* If we're dragging the bar, display it. */
5075 if (! GC_NILP (bar
->dragging
))
5077 /* Where should the handle be now? */
5078 int new_start
= y_pos
- 24;
5080 if (new_start
!= XINT (bar
->start
))
5082 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5084 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5089 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5091 /* Return information to the user about the current position of the mouse
5092 on the scroll bar. */
5095 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5097 Lisp_Object
*bar_window
;
5098 enum scroll_bar_part
*part
;
5100 unsigned long *time
;
5102 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5103 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5104 #if TARGET_API_MAC_CARBON
5105 WindowPtr wp
= GetControlOwner (ch
);
5107 WindowPtr wp
= (*ch
)->contrlOwner
;
5110 struct frame
*f
= mac_window_to_frame (wp
);
5111 int win_y
, top_range
;
5113 SetPortWindowPort (wp
);
5115 GetMouse (&mouse_pos
);
5117 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5118 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5120 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5124 if (! NILP (bar
->dragging
))
5125 win_y
-= XINT (bar
->dragging
);
5129 if (win_y
> top_range
)
5133 *bar_window
= bar
->window
;
5135 if (! NILP (bar
->dragging
))
5136 *part
= scroll_bar_handle
;
5137 else if (win_y
< XINT (bar
->start
))
5138 *part
= scroll_bar_above_handle
;
5139 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5140 *part
= scroll_bar_handle
;
5142 *part
= scroll_bar_below_handle
;
5144 XSETINT (*x
, win_y
);
5145 XSETINT (*y
, top_range
);
5148 last_mouse_scroll_bar
= Qnil
;
5150 *time
= last_mouse_movement_time
;
5154 /* The screen has been cleared so we may have changed foreground or
5155 background colors, and the scroll bars may need to be redrawn.
5156 Clear out the scroll bars, and ask for expose events, so we can
5160 x_scroll_bar_clear (f
)
5163 XTcondemn_scroll_bars (f
);
5164 XTjudge_scroll_bars (f
);
5168 /***********************************************************************
5170 ***********************************************************************/
5172 /* Set clipping for output in glyph row ROW. W is the window in which
5173 we operate. GC is the graphics context to set clipping in.
5175 ROW may be a text row or, e.g., a mode line. Text rows must be
5176 clipped to the interior of the window dedicated to text display,
5177 mode lines must be clipped to the whole window. */
5180 x_clip_to_row (w
, row
, area
, gc
)
5182 struct glyph_row
*row
;
5186 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5188 int window_x
, window_y
, window_width
;
5190 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5192 clip_rect
.left
= window_x
;
5193 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5194 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5195 clip_rect
.right
= clip_rect
.left
+ window_width
;
5196 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5198 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5202 /* Draw a hollow box cursor on window W in glyph row ROW. */
5205 x_draw_hollow_cursor (w
, row
)
5207 struct glyph_row
*row
;
5209 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5210 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5211 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5214 struct glyph
*cursor_glyph
;
5217 /* Get the glyph the cursor is on. If we can't tell because
5218 the current matrix is invalid or such, give up. */
5219 cursor_glyph
= get_phys_cursor_glyph (w
);
5220 if (cursor_glyph
== NULL
)
5223 /* Compute frame-relative coordinates for phys cursor. */
5224 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5225 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5226 wd
= w
->phys_cursor_width
;
5228 /* The foreground of cursor_gc is typically the same as the normal
5229 background color, which can cause the cursor box to be invisible. */
5230 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5231 if (dpyinfo
->scratch_cursor_gc
)
5232 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5234 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5235 GCForeground
, &xgcv
);
5236 gc
= dpyinfo
->scratch_cursor_gc
;
5238 /* Set clipping, draw the rectangle, and reset clipping again. */
5239 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5240 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5241 mac_reset_clip_rectangles (dpy
, gc
);
5245 /* Draw a bar cursor on window W in glyph row ROW.
5247 Implementation note: One would like to draw a bar cursor with an
5248 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5249 Unfortunately, I didn't find a font yet that has this property set.
5253 x_draw_bar_cursor (w
, row
, width
, kind
)
5255 struct glyph_row
*row
;
5257 enum text_cursor_kinds kind
;
5259 struct frame
*f
= XFRAME (w
->frame
);
5260 struct glyph
*cursor_glyph
;
5262 /* If cursor is out of bounds, don't draw garbage. This can happen
5263 in mini-buffer windows when switching between echo area glyphs
5265 cursor_glyph
= get_phys_cursor_glyph (w
);
5266 if (cursor_glyph
== NULL
)
5269 /* If on an image, draw like a normal cursor. That's usually better
5270 visible than drawing a bar, esp. if the image is large so that
5271 the bar might not be in the window. */
5272 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5274 struct glyph_row
*row
;
5275 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5276 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5280 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5281 Window window
= FRAME_MAC_WINDOW (f
);
5282 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5283 unsigned long mask
= GCForeground
| GCBackground
;
5284 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5287 /* If the glyph's background equals the color we normally draw
5288 the bar cursor in, the bar cursor in its normal color is
5289 invisible. Use the glyph's foreground color instead in this
5290 case, on the assumption that the glyph's colors are chosen so
5291 that the glyph is legible. */
5292 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5293 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5295 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5298 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5301 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5302 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5306 width
= FRAME_CURSOR_WIDTH (f
);
5307 width
= min (cursor_glyph
->pixel_width
, width
);
5309 w
->phys_cursor_width
= width
;
5310 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5312 if (kind
== BAR_CURSOR
)
5313 mac_fill_rectangle (f
, gc
,
5314 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5315 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5316 width
, row
->height
);
5318 mac_fill_rectangle (f
, gc
,
5319 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5320 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5321 row
->height
- width
),
5322 cursor_glyph
->pixel_width
,
5325 mac_reset_clip_rectangles (dpy
, gc
);
5330 /* RIF: Define cursor CURSOR on frame F. */
5333 mac_define_frame_cursor (f
, cursor
)
5337 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5339 if (dpyinfo
->x_focus_frame
== f
)
5340 SetThemeCursor (cursor
);
5344 /* RIF: Clear area on frame F. */
5347 mac_clear_frame_area (f
, x
, y
, width
, height
)
5349 int x
, y
, width
, height
;
5351 mac_clear_area (f
, x
, y
, width
, height
);
5355 /* RIF: Draw cursor on window W. */
5358 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5360 struct glyph_row
*glyph_row
;
5362 int cursor_type
, cursor_width
;
5367 w
->phys_cursor_type
= cursor_type
;
5368 w
->phys_cursor_on_p
= 1;
5370 if (glyph_row
->exact_window_width_line_p
5371 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5373 glyph_row
->cursor_in_fringe_p
= 1;
5374 draw_fringe_bitmap (w
, glyph_row
, 0);
5377 switch (cursor_type
)
5379 case HOLLOW_BOX_CURSOR
:
5380 x_draw_hollow_cursor (w
, glyph_row
);
5383 case FILLED_BOX_CURSOR
:
5384 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5388 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5392 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5396 w
->phys_cursor_width
= 0;
5408 #if 0 /* MAC_TODO: no icon support yet. */
5410 x_bitmap_icon (f
, icon
)
5416 if (FRAME_W32_WINDOW (f
) == 0)
5420 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5421 else if (STRINGP (icon
))
5422 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5423 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5424 else if (SYMBOLP (icon
))
5428 if (EQ (icon
, intern ("application")))
5429 name
= (LPCTSTR
) IDI_APPLICATION
;
5430 else if (EQ (icon
, intern ("hand")))
5431 name
= (LPCTSTR
) IDI_HAND
;
5432 else if (EQ (icon
, intern ("question")))
5433 name
= (LPCTSTR
) IDI_QUESTION
;
5434 else if (EQ (icon
, intern ("exclamation")))
5435 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5436 else if (EQ (icon
, intern ("asterisk")))
5437 name
= (LPCTSTR
) IDI_ASTERISK
;
5438 else if (EQ (icon
, intern ("winlogo")))
5439 name
= (LPCTSTR
) IDI_WINLOGO
;
5443 hicon
= LoadIcon (NULL
, name
);
5451 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5456 #endif /* MAC_TODO */
5458 /************************************************************************
5460 ************************************************************************/
5462 /* Display Error Handling functions not used on W32. Listing them here
5463 helps diff stay in step when comparing w32term.c with xterm.c.
5465 x_error_catcher (display, error)
5466 x_catch_errors (dpy)
5467 x_catch_errors_unwind (old_val)
5468 x_check_errors (dpy, format)
5469 x_had_errors_p (dpy)
5470 x_clear_errors (dpy)
5471 x_uncatch_errors (dpy, count)
5473 x_connection_signal (signalnum)
5474 x_connection_closed (dpy, error_message)
5475 x_error_quitter (display, error)
5476 x_error_handler (display, error)
5477 x_io_error_quitter (display)
5482 /* Changing the font of the frame. */
5484 /* Give frame F the font named FONTNAME as its default font, and
5485 return the full name of that font. FONTNAME may be a wildcard
5486 pattern; in that case, we choose some font that fits the pattern.
5487 The return value shows which font we chose. */
5490 x_new_font (f
, fontname
)
5492 register char *fontname
;
5494 struct font_info
*fontp
5495 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5500 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5501 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5502 FRAME_FONTSET (f
) = -1;
5504 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5505 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5506 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5508 compute_fringe_widths (f
, 1);
5510 /* Compute the scroll bar width in character columns. */
5511 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5513 int wid
= FRAME_COLUMN_WIDTH (f
);
5514 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5515 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5519 int wid
= FRAME_COLUMN_WIDTH (f
);
5520 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5523 /* Now make the frame display the given font. */
5524 if (FRAME_MAC_WINDOW (f
) != 0)
5526 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5528 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5530 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5533 /* Don't change the size of a tip frame; there's no point in
5534 doing it because it's done in Fx_show_tip, and it leads to
5535 problems because the tip frame has no widget. */
5536 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5537 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5540 return build_string (fontp
->full_name
);
5543 /* Give frame F the fontset named FONTSETNAME as its default font, and
5544 return the full name of that fontset. FONTSETNAME may be a wildcard
5545 pattern; in that case, we choose some fontset that fits the pattern.
5546 The return value shows which fontset we chose. */
5549 x_new_fontset (f
, fontsetname
)
5553 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5559 if (FRAME_FONTSET (f
) == fontset
)
5560 /* This fontset is already set in frame F. There's nothing more
5562 return fontset_name (fontset
);
5564 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5566 if (!STRINGP (result
))
5567 /* Can't load ASCII font. */
5570 /* Since x_new_font doesn't update any fontset information, do it now. */
5571 FRAME_FONTSET (f
) = fontset
;
5573 return build_string (fontsetname
);
5577 /***********************************************************************
5578 TODO: W32 Input Methods
5579 ***********************************************************************/
5580 /* Listing missing functions from xterm.c helps diff stay in step.
5582 xim_destroy_callback (xim, client_data, call_data)
5583 xim_open_dpy (dpyinfo, resource_name)
5585 xim_instantiate_callback (display, client_data, call_data)
5586 xim_initialize (dpyinfo, resource_name)
5587 xim_close_dpy (dpyinfo)
5593 mac_get_window_bounds (f
, inner
, outer
)
5595 Rect
*inner
, *outer
;
5597 #if TARGET_API_MAC_CARBON
5598 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5599 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5600 #else /* not TARGET_API_MAC_CARBON */
5601 RgnHandle region
= NewRgn ();
5603 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5604 *inner
= (*region
)->rgnBBox
;
5605 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5606 *outer
= (*region
)->rgnBBox
;
5607 DisposeRgn (region
);
5608 #endif /* not TARGET_API_MAC_CARBON */
5613 /* Calculate the absolute position in frame F
5614 from its current recorded position values and gravity. */
5617 x_calc_absolute_position (f
)
5620 int width_diff
= 0, height_diff
= 0;
5621 int flags
= f
->size_hint_flags
;
5624 /* We have nothing to do if the current position
5625 is already for the top-left corner. */
5626 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5629 /* Find the offsets of the outside upper-left corner of
5630 the inner window, with respect to the outer window. */
5631 mac_get_window_bounds (f
, &inner
, &outer
);
5633 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5634 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5636 /* Treat negative positions as relative to the leftmost bottommost
5637 position that fits on the screen. */
5638 if (flags
& XNegative
)
5639 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5641 - FRAME_PIXEL_WIDTH (f
)
5644 if (flags
& YNegative
)
5645 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5647 - FRAME_PIXEL_HEIGHT (f
)
5650 /* The left_pos and top_pos
5651 are now relative to the top and left screen edges,
5652 so the flags should correspond. */
5653 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5656 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5657 to really change the position, and 0 when calling from
5658 x_make_frame_visible (in that case, XOFF and YOFF are the current
5659 position values). It is -1 when calling from x_set_frame_parameters,
5660 which means, do adjust for borders but don't change the gravity. */
5663 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5665 register int xoff
, yoff
;
5668 if (change_gravity
> 0)
5672 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5674 f
->size_hint_flags
|= XNegative
;
5676 f
->size_hint_flags
|= YNegative
;
5677 f
->win_gravity
= NorthWestGravity
;
5679 x_calc_absolute_position (f
);
5682 x_wm_set_size_hint (f
, (long) 0, 0);
5684 #if TARGET_API_MAC_CARBON
5685 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5686 /* If the title bar is completely outside the screen, adjust the
5688 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5689 kWindowConstrainMoveRegardlessOfFit
5690 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5691 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5694 Rect inner
, outer
, screen_rect
, dummy
;
5695 RgnHandle region
= NewRgn ();
5697 mac_get_window_bounds (f
, &inner
, &outer
);
5698 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5699 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5700 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5701 f
->top_pos
+ f
->y_pixels_diff
, false);
5703 /* If the title bar is completely outside the screen, adjust the
5704 position. The variable `outer' holds the title bar rectangle.
5705 The variable `inner' holds slightly smaller one than `outer',
5706 so that the calculation of overlapping may not become too
5708 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5709 outer
= (*region
)->rgnBBox
;
5710 DisposeRgn (region
);
5712 InsetRect (&inner
, 8, 8);
5713 screen_rect
= qd
.screenBits
.bounds
;
5714 screen_rect
.top
+= GetMBarHeight ();
5716 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5718 if (inner
.right
<= screen_rect
.left
)
5719 f
->left_pos
= screen_rect
.left
;
5720 else if (inner
.left
>= screen_rect
.right
)
5721 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5723 if (inner
.bottom
<= screen_rect
.top
)
5724 f
->top_pos
= screen_rect
.top
;
5725 else if (inner
.top
>= screen_rect
.bottom
)
5726 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5728 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5729 f
->top_pos
+ f
->y_pixels_diff
, false);
5737 /* Call this to change the size of frame F's x-window.
5738 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5739 for this size change and subsequent size changes.
5740 Otherwise we leave the window gravity unchanged. */
5743 x_set_window_size (f
, change_gravity
, cols
, rows
)
5748 int pixelwidth
, pixelheight
;
5752 check_frame_size (f
, &rows
, &cols
);
5753 f
->scroll_bar_actual_width
5754 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5756 compute_fringe_widths (f
, 0);
5758 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5759 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5761 f
->win_gravity
= NorthWestGravity
;
5762 x_wm_set_size_hint (f
, (long) 0, 0);
5764 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5765 #if TARGET_API_MAC_CARBON
5766 if (f
->output_data
.mac
->hourglass_control
)
5767 MoveControl (f
->output_data
.mac
->hourglass_control
,
5768 pixelwidth
- HOURGLASS_WIDTH
, 0);
5771 /* Now, strictly speaking, we can't be sure that this is accurate,
5772 but the window manager will get around to dealing with the size
5773 change request eventually, and we'll hear how it went when the
5774 ConfigureNotify event gets here.
5776 We could just not bother storing any of this information here,
5777 and let the ConfigureNotify event set everything up, but that
5778 might be kind of confusing to the Lisp code, since size changes
5779 wouldn't be reported in the frame parameters until some random
5780 point in the future when the ConfigureNotify event arrives.
5782 We pass 1 for DELAY since we can't run Lisp code inside of
5784 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5785 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5786 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5788 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5789 receive in the ConfigureNotify event; if we get what we asked
5790 for, then the event won't cause the screen to become garbaged, so
5791 we have to make sure to do it here. */
5792 SET_FRAME_GARBAGED (f
);
5794 XFlush (FRAME_X_DISPLAY (f
));
5796 /* If cursor was outside the new size, mark it as off. */
5797 mark_window_cursors_off (XWINDOW (f
->root_window
));
5799 /* Clear out any recollection of where the mouse highlighting was,
5800 since it might be in a place that's outside the new frame size.
5801 Actually checking whether it is outside is a pain in the neck,
5802 so don't try--just let the highlighting be done afresh with new size. */
5803 cancel_mouse_face (f
);
5808 /* Mouse warping. */
5810 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5813 x_set_mouse_position (f
, x
, y
)
5819 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5820 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5822 if (pix_x
< 0) pix_x
= 0;
5823 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5825 if (pix_y
< 0) pix_y
= 0;
5826 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5828 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5832 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5836 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5839 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5840 0, 0, 0, 0, pix_x
, pix_y
);
5845 /* focus shifting, raising and lowering. */
5848 x_focus_on_frame (f
)
5851 #if 0 /* This proves to be unpleasant. */
5855 /* I don't think that the ICCCM allows programs to do things like this
5856 without the interaction of the window manager. Whatever you end up
5857 doing with this code, do it to x_unfocus_frame too. */
5858 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5859 RevertToPointerRoot
, CurrentTime
);
5869 /* Raise frame F. */
5875 if (f
->async_visible
)
5878 BringToFront (FRAME_MAC_WINDOW (f
));
5883 /* Lower frame F. */
5889 if (f
->async_visible
)
5892 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
5898 XTframe_raise_lower (f
, raise_flag
)
5908 /* Change of visibility. */
5911 mac_handle_visibility_change (f
)
5914 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5915 int visible
= 0, iconified
= 0;
5916 struct input_event buf
;
5918 if (IsWindowVisible (wp
))
5919 if (IsWindowCollapsed (wp
))
5924 if (!f
->async_visible
&& visible
)
5928 /* wait_reading_process_output will notice this and update
5929 the frame's display structures. If we were made
5930 invisible, we should not set garbaged, because that stops
5931 redrawing on Update events. */
5932 SET_FRAME_GARBAGED (f
);
5935 buf
.kind
= DEICONIFY_EVENT
;
5936 XSETFRAME (buf
.frame_or_window
, f
);
5937 kbd_buffer_store_event (&buf
);
5939 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5940 /* Force a redisplay sooner or later to update the
5941 frame titles in case this is the second frame. */
5942 record_asynch_buffer_change ();
5944 else if (f
->async_visible
&& !visible
)
5948 buf
.kind
= ICONIFY_EVENT
;
5949 XSETFRAME (buf
.frame_or_window
, f
);
5950 kbd_buffer_store_event (&buf
);
5953 f
->async_visible
= visible
;
5954 f
->async_iconified
= iconified
;
5957 /* This tries to wait until the frame is really visible.
5958 However, if the window manager asks the user where to position
5959 the frame, this will return before the user finishes doing that.
5960 The frame will not actually be visible at that time,
5961 but it will become visible later when the window manager
5962 finishes with it. */
5965 x_make_frame_visible (f
)
5969 int original_top
, original_left
;
5973 if (! FRAME_VISIBLE_P (f
))
5975 /* We test FRAME_GARBAGED_P here to make sure we don't
5976 call x_set_offset a second time
5977 if we get to x_make_frame_visible a second time
5978 before the window gets really visible. */
5979 if (! FRAME_ICONIFIED_P (f
)
5980 && ! f
->output_data
.mac
->asked_for_visible
)
5981 #if TARGET_API_MAC_CARBON
5982 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5984 struct frame
*sf
= SELECTED_FRAME ();
5985 if (!FRAME_MAC_P (sf
))
5986 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5987 kWindowCenterOnMainScreen
);
5989 RepositionWindow (FRAME_MAC_WINDOW (f
),
5990 FRAME_MAC_WINDOW (sf
),
5991 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5992 kWindowCascadeStartAtParentWindowScreen
5994 kWindowCascadeOnParentWindowScreen
5997 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
6001 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6003 f
->output_data
.mac
->asked_for_visible
= 1;
6005 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6006 ShowWindow (FRAME_MAC_WINDOW (f
));
6009 XFlush (FRAME_MAC_DISPLAY (f
));
6011 /* Synchronize to ensure Emacs knows the frame is visible
6012 before we do anything else. We do this loop with input not blocked
6013 so that incoming events are handled. */
6018 /* This must come after we set COUNT. */
6021 XSETFRAME (frame
, f
);
6023 /* Wait until the frame is visible. Process X events until a
6024 MapNotify event has been seen, or until we think we won't get a
6025 MapNotify at all.. */
6026 for (count
= input_signal_count
+ 10;
6027 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6029 /* Force processing of queued events. */
6032 /* Machines that do polling rather than SIGIO have been
6033 observed to go into a busy-wait here. So we'll fake an
6034 alarm signal to let the handler know that there's something
6035 to be read. We used to raise a real alarm, but it seems
6036 that the handler isn't always enabled here. This is
6038 if (input_polling_used ())
6040 /* It could be confusing if a real alarm arrives while
6041 processing the fake one. Turn it off and let the
6042 handler reset it. */
6043 extern void poll_for_input_1
P_ ((void));
6044 int old_poll_suppress_count
= poll_suppress_count
;
6045 poll_suppress_count
= 1;
6046 poll_for_input_1 ();
6047 poll_suppress_count
= old_poll_suppress_count
;
6050 /* See if a MapNotify event has been processed. */
6051 FRAME_SAMPLE_VISIBILITY (f
);
6056 /* Change from mapped state to withdrawn state. */
6058 /* Make the frame visible (mapped and not iconified). */
6061 x_make_frame_invisible (f
)
6064 /* A deactivate event does not occur when the last visible frame is
6065 made invisible. So if we clear the highlight here, it will not
6066 be rehighlighted when it is made visible. */
6068 /* Don't keep the highlight on an invisible frame. */
6069 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6070 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6075 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6076 that the current position of the window is user-specified, rather than
6077 program-specified, so that when the window is mapped again, it will be
6078 placed at the same location, without forcing the user to position it
6079 by hand again (they have already done that once for this window.) */
6080 x_wm_set_size_hint (f
, (long) 0, 1);
6082 HideWindow (FRAME_MAC_WINDOW (f
));
6086 #if !USE_CARBON_EVENTS
6087 mac_handle_visibility_change (f
);
6091 /* Change window state from mapped to iconified. */
6099 /* A deactivate event does not occur when the last visible frame is
6100 iconified. So if we clear the highlight here, it will not be
6101 rehighlighted when it is deiconified. */
6103 /* Don't keep the highlight on an invisible frame. */
6104 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6105 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6108 if (f
->async_iconified
)
6113 FRAME_SAMPLE_VISIBILITY (f
);
6115 if (! FRAME_VISIBLE_P (f
))
6116 ShowWindow (FRAME_MAC_WINDOW (f
));
6118 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6123 error ("Can't notify window manager of iconification");
6125 #if !USE_CARBON_EVENTS
6126 mac_handle_visibility_change (f
);
6131 /* Free X resources of frame F. */
6134 x_free_frame_resources (f
)
6137 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6138 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6142 if (wp
!= tip_window
)
6143 remove_window_handler (wp
);
6146 if (wp
== tip_window
)
6147 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6148 closed' event. So we reset tip_window here. */
6151 free_frame_menubar (f
);
6153 if (FRAME_FACE_CACHE (f
))
6154 free_frame_faces (f
);
6158 if (FRAME_SIZE_HINTS (f
))
6159 xfree (FRAME_SIZE_HINTS (f
));
6161 xfree (f
->output_data
.mac
);
6162 f
->output_data
.mac
= NULL
;
6164 if (f
== dpyinfo
->x_focus_frame
)
6165 dpyinfo
->x_focus_frame
= 0;
6166 if (f
== dpyinfo
->x_focus_event_frame
)
6167 dpyinfo
->x_focus_event_frame
= 0;
6168 if (f
== dpyinfo
->x_highlight_frame
)
6169 dpyinfo
->x_highlight_frame
= 0;
6171 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6173 dpyinfo
->mouse_face_beg_row
6174 = dpyinfo
->mouse_face_beg_col
= -1;
6175 dpyinfo
->mouse_face_end_row
6176 = dpyinfo
->mouse_face_end_col
= -1;
6177 dpyinfo
->mouse_face_window
= Qnil
;
6178 dpyinfo
->mouse_face_deferred_gc
= 0;
6179 dpyinfo
->mouse_face_mouse_frame
= 0;
6186 /* Destroy the X window of frame F. */
6189 x_destroy_window (f
)
6192 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6194 x_free_frame_resources (f
);
6196 dpyinfo
->reference_count
--;
6200 /* Setting window manager hints. */
6202 /* Set the normal size hints for the window manager, for frame F.
6203 FLAGS is the flags word to use--or 0 meaning preserve the flags
6204 that the window now has.
6205 If USER_POSITION is nonzero, we set the USPosition
6206 flag (this is useful when FLAGS is 0). */
6208 x_wm_set_size_hint (f
, flags
, user_position
)
6213 int base_width
, base_height
, width_inc
, height_inc
;
6214 int min_rows
= 0, min_cols
= 0;
6215 XSizeHints
*size_hints
;
6217 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6218 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6219 width_inc
= FRAME_COLUMN_WIDTH (f
);
6220 height_inc
= FRAME_LINE_HEIGHT (f
);
6222 check_frame_size (f
, &min_rows
, &min_cols
);
6224 size_hints
= FRAME_SIZE_HINTS (f
);
6225 if (size_hints
== NULL
)
6227 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6228 bzero (size_hints
, sizeof (XSizeHints
));
6231 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6232 size_hints
->width_inc
= width_inc
;
6233 size_hints
->height_inc
= height_inc
;
6234 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6235 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6236 size_hints
->base_width
= base_width
;
6237 size_hints
->base_height
= base_height
;
6240 size_hints
->flags
= flags
;
6241 else if (user_position
)
6243 size_hints
->flags
&= ~ PPosition
;
6244 size_hints
->flags
|= USPosition
;
6248 #if 0 /* MAC_TODO: hide application instead of iconify? */
6249 /* Used for IconicState or NormalState */
6252 x_wm_set_window_state (f
, state
)
6256 #ifdef USE_X_TOOLKIT
6259 XtSetArg (al
[0], XtNinitialState
, state
);
6260 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6261 #else /* not USE_X_TOOLKIT */
6262 Window window
= FRAME_X_WINDOW (f
);
6264 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6265 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6267 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6268 #endif /* not USE_X_TOOLKIT */
6272 x_wm_set_icon_pixmap (f
, pixmap_id
)
6278 #ifndef USE_X_TOOLKIT
6279 Window window
= FRAME_X_WINDOW (f
);
6284 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6285 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6289 /* It seems there is no way to turn off use of an icon pixmap.
6290 The following line does it, only if no icon has yet been created,
6291 for some window managers. But with mwm it crashes.
6292 Some people say it should clear the IconPixmapHint bit in this case,
6293 but that doesn't work, and the X consortium said it isn't the
6294 right thing at all. Since there is no way to win,
6295 best to explicitly give up. */
6297 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6303 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6307 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6308 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6311 #else /* not USE_X_TOOLKIT */
6313 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6314 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6316 #endif /* not USE_X_TOOLKIT */
6319 #endif /* MAC_TODO */
6322 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6326 #if 0 /* MAC_TODO: no icons on Mac */
6327 #ifdef USE_X_TOOLKIT
6328 Window window
= XtWindow (f
->output_data
.x
->widget
);
6330 Window window
= FRAME_X_WINDOW (f
);
6333 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6334 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6335 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6337 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6338 #endif /* MAC_TODO */
6342 /***********************************************************************
6344 ***********************************************************************/
6346 /* An XLFD pattern is divided into blocks delimited by '*'. This
6347 structure holds information for each block. */
6348 struct xlfdpat_block
6350 /* Length of the pattern string in this block. Non-zero except for
6351 the first and the last blocks. */
6354 /* Pattern string except the last character in this block. The last
6355 character is replaced with NUL in order to use it as a
6357 unsigned char *pattern
;
6359 /* Last character of the pattern string. Must not be '?'. */
6360 unsigned char last_char
;
6362 /* One of the tables for the Boyer-Moore string search. It
6363 specifies the number of positions to proceed for each character
6364 with which the match fails. */
6367 /* The skip value for the last character in the above `skip' is
6368 assigned to `infinity' in order to simplify a loop condition.
6369 The original value is saved here. */
6375 /* Normalized pattern string. "Normalized" means that capital
6376 letters are lowered, blocks are not empty except the first and
6377 the last ones, and trailing '?'s in a block that is not the last
6378 one are moved to the next one. The last character in each block
6379 is replaced with NUL. */
6382 /* Number of characters except '*'s and trailing '?'s in the
6383 normalized pattern string. */
6386 /* Number of trailing '?'s in the normalized pattern string. */
6387 int trailing_anychars
;
6389 /* Number of blocks and information for each block. The latter is
6390 NULL if the pattern is exact (no '*' or '?' in it). */
6392 struct xlfdpat_block
*blocks
;
6396 xlfdpat_destroy (pat
)
6397 struct xlfdpat
*pat
;
6404 xfree (pat
->blocks
);
6411 static struct xlfdpat
*
6412 xlfdpat_create (pattern
)
6415 struct xlfdpat
*pat
;
6416 int nblocks
, i
, skip
;
6417 unsigned char last_char
, *p
, *q
, *anychar_head
;
6418 struct xlfdpat_block
*blk
;
6420 pat
= xmalloc (sizeof (struct xlfdpat
));
6424 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6425 if (pat
->buf
== NULL
)
6428 /* Normalize the pattern string and store it to `pat->buf'. */
6430 anychar_head
= NULL
;
6433 for (p
= pattern
; *p
; p
++)
6435 unsigned char c
= *p
;
6438 if (last_char
== '*')
6439 /* ...a** -> ...a* */
6443 if (last_char
== '?')
6444 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6445 /* ...*??* -> ...*?? */
6448 /* ...a??* -> ...a*?? */
6450 *anychar_head
++ = '*';
6457 if (last_char
!= '?')
6461 /* On Mac OS X 10.3, tolower also converts non-ASCII
6462 characters for some locales. */
6466 *q
++ = last_char
= c
;
6470 pat
->nblocks
= nblocks
;
6471 if (last_char
!= '?')
6472 pat
->trailing_anychars
= 0;
6475 pat
->trailing_anychars
= q
- anychar_head
;
6478 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6480 if (anychar_head
== NULL
&& nblocks
== 1)
6482 /* The pattern is exact. */
6487 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6488 if (pat
->blocks
== NULL
)
6491 /* Divide the normalized pattern into blocks. */
6493 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6498 blk
->len
= p
- blk
->pattern
;
6502 blk
->len
= q
- blk
->pattern
;
6504 /* Setup a table for the Boyer-Moore string search. */
6505 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6508 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6509 blk
->pattern
[blk
->len
- 1] = '\0';
6511 for (skip
= 1; skip
< blk
->len
; skip
++)
6512 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6515 for (i
= 0; i
< 256; i
++)
6516 blk
->skip
[i
] = skip
;
6518 p
= blk
->pattern
+ (blk
->len
- skip
);
6520 blk
->skip
[*p
++] = skip
;
6522 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6528 xlfdpat_destroy (pat
);
6533 xlfdpat_exact_p (pat
)
6534 struct xlfdpat
*pat
;
6536 return pat
->blocks
== NULL
;
6539 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6540 that the pattern in *BLK matches with its prefix. Return NULL
6541 there is no such strings. STRING must be lowered in advance. */
6544 xlfdpat_block_match_1 (blk
, string
, start_max
)
6545 struct xlfdpat_block
*blk
;
6546 unsigned char *string
;
6549 int start
, infinity
;
6550 unsigned char *p
, *s
;
6552 xassert (blk
->len
> 0);
6553 xassert (start_max
+ blk
->len
<= strlen (string
));
6554 xassert (blk
->last_char
!= '?');
6556 /* See the comments in the function `boyer_moore' (search.c) for the
6557 use of `infinity'. */
6558 infinity
= start_max
+ blk
->len
+ 1;
6559 blk
->skip
[blk
->last_char
] = infinity
;
6564 /* Check the last character of the pattern. */
6565 s
= string
+ blk
->len
- 1;
6568 start
+= blk
->skip
[*(s
+ start
)];
6570 while (start
<= start_max
);
6572 if (start
< infinity
)
6573 /* Couldn't find the last character. */
6576 /* No less than `infinity' means we could find the last
6577 character at `s[start - infinity]'. */
6580 /* Check the remaining characters. We prefer making no-'?'
6581 cases faster because the use of '?' is really rare. */
6586 while (*p
++ == *s
++)
6589 while (*(p
- 1) == '?');
6591 if (*(p
- 1) == '\0')
6593 return string
+ start
;
6596 start
+= blk
->last_char_skip
;
6598 while (start
<= start_max
);
6603 #define xlfdpat_block_match(b, s, m) \
6604 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6605 : xlfdpat_block_match_1 (b, s, m))
6607 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6608 matches with STRING. STRING must be lowered in advance. */
6611 xlfdpat_match (pat
, string
)
6612 struct xlfdpat
*pat
;
6613 unsigned char *string
;
6615 int str_len
, nblocks
, i
, start_max
;
6616 struct xlfdpat_block
*blk
;
6619 xassert (pat
->nblocks
> 0);
6621 if (xlfdpat_exact_p (pat
))
6622 return strcmp (pat
->buf
, string
) == 0;
6624 /* The number of the characters in the string must not be smaller
6625 than that in the pattern. */
6626 str_len
= strlen (string
);
6627 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6630 /* Chop off the trailing '?'s. */
6631 str_len
-= pat
->trailing_anychars
;
6633 /* The last block. When it is non-empty, it must match at the end
6635 nblocks
= pat
->nblocks
;
6636 blk
= pat
->blocks
+ (nblocks
- 1);
6638 /* The last block is also the first one. */
6639 return (str_len
== blk
->len
6640 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6641 else if (blk
->len
!= 0)
6642 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6645 /* The first block. When it is non-empty, it must match at the
6646 beginning of the string. */
6650 s
= xlfdpat_block_match (blk
, string
, 0);
6653 string
= s
+ blk
->len
;
6656 /* The rest of the blocks. */
6657 start_max
= str_len
- pat
->nchars
;
6658 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6660 s
= xlfdpat_block_match (blk
, string
, start_max
);
6663 start_max
-= s
- string
;
6664 string
= s
+ blk
->len
;
6671 /***********************************************************************
6673 ***********************************************************************/
6675 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6678 x_get_font_info (f
, font_idx
)
6682 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6685 /* the global font name table */
6686 static char **font_name_table
= NULL
;
6687 static int font_name_table_size
= 0;
6688 static int font_name_count
= 0;
6690 /* Alist linking font family names to Font Manager font family
6691 references (which can also be used as QuickDraw font IDs). We use
6692 an alist because hash tables are not ready when the terminal frame
6693 for Mac OS Classic is created. */
6694 static Lisp_Object fm_font_family_alist
;
6696 /* Hash table linking font family names to ATSU font IDs. */
6697 static Lisp_Object atsu_font_id_hash
;
6700 /* Alist linking character set strings to Mac text encoding and Emacs
6702 static Lisp_Object Vmac_charset_info_alist
;
6705 create_text_encoding_info_alist ()
6707 Lisp_Object result
= Qnil
, rest
;
6709 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6711 Lisp_Object charset_info
= XCAR (rest
);
6712 Lisp_Object charset
, coding_system
, text_encoding
;
6713 Lisp_Object existing_info
;
6715 if (!(CONSP (charset_info
)
6716 && STRINGP (charset
= XCAR (charset_info
))
6717 && CONSP (XCDR (charset_info
))
6718 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6719 && CONSP (XCDR (XCDR (charset_info
)))
6720 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6723 existing_info
= assq_no_quit (text_encoding
, result
);
6724 if (NILP (existing_info
))
6725 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6728 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6729 XSETCDR (XCDR (existing_info
),
6730 Fcons (charset
, XCDR (XCDR (existing_info
))));
6738 decode_mac_font_name (name
, size
, coding_system
)
6741 Lisp_Object coding_system
;
6743 struct coding_system coding
;
6746 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6748 for (p
= name
; *p
; p
++)
6749 if (!isascii (*p
) || iscntrl (*p
))
6754 setup_coding_system (coding_system
, &coding
);
6755 coding
.src_multibyte
= 0;
6756 coding
.dst_multibyte
= 1;
6757 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6758 coding
.composing
= COMPOSITION_DISABLED
;
6759 buf
= (char *) alloca (size
);
6761 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6762 bcopy (buf
, name
, coding
.produced
);
6763 name
[coding
.produced
] = '\0';
6767 /* If there's just one occurrence of '-' in the family name, it is
6768 replaced with '_'. (More than one occurrence of '-' means a
6769 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6770 p
= strchr (name
, '-');
6771 if (p
&& strchr (p
+ 1, '-') == NULL
)
6774 for (p
= name
; *p
; p
++)
6775 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6776 for some locales. */
6783 mac_to_x_fontname (name
, size
, style
, charset
)
6791 char xf
[256], *result
;
6794 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6798 strcpy(foundry
, "Apple");
6799 strcpy(family
, name
);
6802 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6803 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6804 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6806 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6807 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6808 for (p
= result
; *p
; p
++)
6809 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6810 for some locales. */
6817 /* Parse fully-specified and instantiated X11 font spec XF, and store
6818 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6819 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6820 caller must allocate at least 256 and 32 bytes respectively. For
6821 ordinary Mac fonts, the value stored to FAMILY should just be their
6822 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6823 intlfonts collection contain their charset designation in their
6824 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6825 types of font names are handled accordingly. */
6827 const int kDefaultFontSize
= 12;
6830 parse_x_font_name (xf
, family
, size
, style
, charset
)
6836 Str31 foundry
, weight
;
6837 int point_size
, avgwidth
;
6840 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6841 foundry
, family
, weight
, slant
, size
,
6842 &point_size
, &avgwidth
, charset
) != 8
6843 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6844 foundry
, family
, weight
, slant
, size
,
6845 &point_size
, &avgwidth
, charset
) != 8)
6851 *size
= point_size
/ 10;
6852 else if (avgwidth
> 0)
6853 *size
= avgwidth
/ 10;
6856 *size
= kDefaultFontSize
;
6859 if (strcmp (weight
, "bold") == 0)
6864 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6866 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6868 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6870 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6871 but take overlap into account. */
6872 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6873 memcpy (family
, foundry
, foundry_len
);
6874 family
[foundry_len
] = '-';
6875 family
[foundry_len
+ 1 + family_len
] = '-';
6876 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6882 for (p
= family
; *p
; p
++)
6883 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6884 for some locales. */
6893 add_font_name_table_entry (char *font_name
)
6895 if (font_name_table_size
== 0)
6897 font_name_table_size
= 256;
6898 font_name_table
= (char **)
6899 xmalloc (font_name_table_size
* sizeof (char *));
6901 else if (font_name_count
+ 1 >= font_name_table_size
)
6903 font_name_table_size
*= 2;
6904 font_name_table
= (char **)
6905 xrealloc (font_name_table
,
6906 font_name_table_size
* sizeof (char *));
6909 font_name_table
[font_name_count
++] = font_name
;
6912 /* Sets up the table font_name_table to contain the list of all fonts
6913 in the system the first time the table is used so that the Resource
6914 Manager need not be accessed every time this information is
6918 init_font_name_table ()
6920 #if TARGET_API_MAC_CARBON
6921 FMFontFamilyIterator ffi
;
6922 FMFontFamilyInstanceIterator ffii
;
6924 Lisp_Object text_encoding_info_alist
;
6925 struct gcpro gcpro1
;
6927 text_encoding_info_alist
= create_text_encoding_info_alist ();
6930 #if USE_CG_TEXT_DRAWING
6931 init_cg_text_anti_aliasing_threshold ();
6933 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6934 text_encoding_info_alist
)))
6937 ItemCount nfonts
, i
;
6938 ATSUFontID
*font_ids
= NULL
;
6939 Ptr name
, prev_name
= NULL
;
6943 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6944 make_float (DEFAULT_REHASH_SIZE
),
6945 make_float (DEFAULT_REHASH_THRESHOLD
),
6947 err
= ATSUFontCount (&nfonts
);
6949 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6951 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6953 for (i
= 0; i
< nfonts
; i
++)
6955 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6956 kFontMacintoshPlatform
, kFontNoScript
,
6957 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6960 name
= xmalloc (name_len
+ 1);
6963 name
[name_len
] = '\0';
6964 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6965 kFontMacintoshPlatform
, kFontNoScript
,
6966 kFontNoLanguage
, name_len
, name
,
6969 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6972 && (prev_name
== NULL
6973 || strcmp (name
, prev_name
) != 0))
6975 static char *cs
= "iso10646-1";
6977 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6979 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6981 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6983 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6984 italic
| bold
, cs
));
6985 Fputhash (make_unibyte_string (name
, name_len
),
6986 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
7000 /* Create a dummy instance iterator here to avoid creating and
7001 destroying it in the loop. */
7002 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7004 /* Create an iterator to enumerate the font families. */
7005 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7008 FMDisposeFontFamilyInstanceIterator (&ffii
);
7012 GCPRO1 (text_encoding_info_alist
);
7014 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7020 TextEncoding encoding
;
7021 TextEncodingBase sc
;
7022 Lisp_Object text_encoding_info
;
7024 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7030 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7032 sc
= GetTextEncodingBase (encoding
);
7033 text_encoding_info
= assq_no_quit (make_number (sc
),
7034 text_encoding_info_alist
);
7035 if (NILP (text_encoding_info
))
7036 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7037 text_encoding_info_alist
);
7038 decode_mac_font_name (name
, sizeof (name
),
7039 XCAR (XCDR (text_encoding_info
)));
7040 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7042 fm_font_family_alist
);
7044 /* Point the instance iterator at the current font family. */
7045 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7048 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7051 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7053 if (size
> 0 || style
== normal
)
7054 for (; !NILP (rest
); rest
= XCDR (rest
))
7056 char *cs
= SDATA (XCAR (rest
));
7060 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7062 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7064 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7066 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7072 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7081 /* Dispose of the iterators. */
7082 FMDisposeFontFamilyIterator (&ffi
);
7083 FMDisposeFontFamilyInstanceIterator (&ffii
);
7084 #else /* !TARGET_API_MAC_CARBON */
7086 SInt16 fontnum
, old_fontnum
;
7087 int num_mac_fonts
= CountResources('FOND');
7089 Handle font_handle
, font_handle_2
;
7090 short id
, scriptcode
;
7093 struct FontAssoc
*fat
;
7094 struct AsscEntry
*assc_entry
;
7095 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7096 struct gcpro gcpro1
;
7098 GetPort (&port
); /* save the current font number used */
7099 old_fontnum
= port
->txFont
;
7101 text_encoding_info_alist
= create_text_encoding_info_alist ();
7103 GCPRO1 (text_encoding_info_alist
);
7105 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7107 font_handle
= GetIndResource ('FOND', i
);
7111 GetResInfo (font_handle
, &id
, &type
, name
);
7112 GetFNum (name
, &fontnum
);
7118 scriptcode
= FontToScript (fontnum
);
7119 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7120 text_encoding_info_alist
);
7121 if (NILP (text_encoding_info
))
7122 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7123 text_encoding_info_alist
);
7124 decode_mac_font_name (name
, sizeof (name
),
7125 XCAR (XCDR (text_encoding_info
)));
7126 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7127 make_number (fontnum
)),
7128 fm_font_family_alist
);
7131 HLock (font_handle
);
7133 if (GetResourceSizeOnDisk (font_handle
)
7134 >= sizeof (struct FamRec
))
7136 fat
= (struct FontAssoc
*) (*font_handle
7137 + sizeof (struct FamRec
));
7139 = (struct AsscEntry
*) (*font_handle
7140 + sizeof (struct FamRec
)
7141 + sizeof (struct FontAssoc
));
7143 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7145 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7147 for (; !NILP (rest
); rest
= XCDR (rest
))
7149 char *cs
= SDATA (XCAR (rest
));
7151 add_font_name_table_entry (mac_to_x_fontname (name
,
7152 assc_entry
->fontSize
,
7153 assc_entry
->fontStyle
,
7159 HUnlock (font_handle
);
7160 font_handle_2
= GetNextFOND (font_handle
);
7161 ReleaseResource (font_handle
);
7162 font_handle
= font_handle_2
;
7164 while (ResError () == noErr
&& font_handle
);
7169 TextFont (old_fontnum
);
7170 #endif /* !TARGET_API_MAC_CARBON */
7175 mac_clear_font_name_table ()
7179 for (i
= 0; i
< font_name_count
; i
++)
7180 xfree (font_name_table
[i
]);
7181 xfree (font_name_table
);
7182 font_name_table
= NULL
;
7183 font_name_table_size
= font_name_count
= 0;
7184 fm_font_family_alist
= Qnil
;
7188 enum xlfd_scalable_field_index
7190 XLFD_SCL_PIXEL_SIZE
,
7191 XLFD_SCL_POINT_SIZE
,
7196 static int xlfd_scalable_fields
[] =
7205 mac_do_list_fonts (pattern
, maxnames
)
7210 Lisp_Object font_list
= Qnil
;
7211 struct xlfdpat
*pat
;
7213 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7216 if (font_name_table
== NULL
) /* Initialize when first used. */
7217 init_font_name_table ();
7219 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7222 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7223 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7224 fonts are scaled according to the specified size. */
7227 field
= xlfd_scalable_fields
;
7235 if ('0' <= *ptr
&& *ptr
<= '9')
7237 *val
= *ptr
++ - '0';
7238 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7239 *val
= *val
* 10 + *ptr
++ - '0';
7246 ptr
= strchr (ptr
, '-');
7249 while (ptr
&& i
< 14);
7251 if (i
== 14 && ptr
== NULL
)
7253 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7254 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7255 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7256 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7258 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7259 scl_val
[XLFD_SCL_POINT_SIZE
] =
7260 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7261 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7263 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7264 scl_val
[XLFD_SCL_AVGWIDTH
] =
7265 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7266 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7270 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7272 pat
= xlfdpat_create (pattern
);
7276 exact
= xlfdpat_exact_p (pat
);
7278 for (i
= 0; i
< font_name_count
; i
++)
7280 if (xlfdpat_match (pat
, font_name_table
[i
]))
7282 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7283 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7286 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7287 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7289 int former_len
= ptr
- font_name_table
[i
];
7291 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7294 memcpy (scaled
, font_name_table
[i
], former_len
);
7295 sprintf (scaled
+ former_len
,
7296 "-%d-%d-72-72-m-%d-%s",
7297 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7298 scl_val
[XLFD_SCL_POINT_SIZE
],
7299 scl_val
[XLFD_SCL_AVGWIDTH
],
7300 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7302 if (xlfdpat_match (pat
, scaled
))
7304 font_list
= Fcons (build_string (scaled
), font_list
);
7306 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7314 xlfdpat_destroy (pat
);
7319 /* Return a list of names of available fonts matching PATTERN on frame F.
7321 Frame F null means we have not yet created any frame on Mac, and
7322 consult the first display in x_display_list. MAXNAMES sets a limit
7323 on how many fonts to match. */
7326 x_list_fonts (f
, pattern
, size
, maxnames
)
7328 Lisp_Object pattern
;
7331 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7332 struct mac_display_info
*dpyinfo
7333 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7335 xassert (size
<= 0);
7337 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7338 if (NILP (patterns
))
7339 patterns
= Fcons (pattern
, Qnil
);
7341 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7343 pattern
= XCAR (patterns
);
7345 if (!STRINGP (pattern
))
7348 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7349 key
= Fcons (pattern
, make_number (maxnames
));
7351 list
= Fassoc (key
, tem
);
7354 list
= Fcdr_safe (list
);
7355 /* We have a cashed list. Don't have to get the list again. */
7360 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7363 /* MAC_TODO: add code for matching outline fonts here */
7365 /* Now store the result in the cache. */
7366 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7367 Fcons (Fcons (key
, list
),
7368 XCAR (XCDR (dpyinfo
->name_list_element
))));
7371 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7380 /* Check that FONT is valid on frame F. It is if it can be found in F's
7384 x_check_font (f
, font
)
7389 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7391 xassert (font
!= NULL
);
7393 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7394 if (dpyinfo
->font_table
[i
].name
7395 && font
== dpyinfo
->font_table
[i
].font
)
7398 xassert (i
< dpyinfo
->n_fonts
);
7401 #endif /* GLYPH_DEBUG != 0 */
7403 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7404 Note: There are (broken) X fonts out there with invalid XFontStruct
7405 min_bounds contents. For example, handa@etl.go.jp reports that
7406 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7407 have font->min_bounds.width == 0. */
7410 x_font_min_bounds (font
, w
, h
)
7411 MacFontStruct
*font
;
7414 *h
= FONT_HEIGHT (font
);
7415 *w
= font
->min_bounds
.width
;
7419 /* Compute the smallest character width and smallest font height over
7420 all fonts available on frame F. Set the members smallest_char_width
7421 and smallest_font_height in F's x_display_info structure to
7422 the values computed. Value is non-zero if smallest_font_height or
7423 smallest_char_width become smaller than they were before. */
7426 x_compute_min_glyph_bounds (f
)
7430 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7431 MacFontStruct
*font
;
7432 int old_width
= dpyinfo
->smallest_char_width
;
7433 int old_height
= dpyinfo
->smallest_font_height
;
7435 dpyinfo
->smallest_font_height
= 100000;
7436 dpyinfo
->smallest_char_width
= 100000;
7438 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7439 if (dpyinfo
->font_table
[i
].name
)
7441 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7444 font
= (MacFontStruct
*) fontp
->font
;
7445 xassert (font
!= (MacFontStruct
*) ~0);
7446 x_font_min_bounds (font
, &w
, &h
);
7448 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7449 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7452 xassert (dpyinfo
->smallest_char_width
> 0
7453 && dpyinfo
->smallest_font_height
> 0);
7455 return (dpyinfo
->n_fonts
== 1
7456 || dpyinfo
->smallest_char_width
< old_width
7457 || dpyinfo
->smallest_font_height
< old_height
);
7461 /* Determine whether given string is a fully-specified XLFD: all 14
7462 fields are present, none is '*'. */
7465 is_fully_specified_xlfd (char *p
)
7473 for (i
= 0; i
< 13; i
++)
7475 q
= strchr (p
+ 1, '-');
7478 if (q
- p
== 2 && *(p
+ 1) == '*')
7483 if (strchr (p
+ 1, '-') != NULL
)
7486 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7493 /* XLoadQueryFont creates and returns an internal representation for a
7494 font in a MacFontStruct struct. There is really no concept
7495 corresponding to "loading" a font on the Mac. But we check its
7496 existence and find the font number and all other information for it
7497 and store them in the returned MacFontStruct. */
7499 static MacFontStruct
*
7500 XLoadQueryFont (Display
*dpy
, char *fontname
)
7508 static ATSUFontID font_id
;
7509 ATSUStyle mac_style
= NULL
;
7512 #if TARGET_API_MAC_CARBON
7513 TextEncoding encoding
;
7518 MacFontStruct
*font
;
7519 XCharStruct
*space_bounds
= NULL
, *pcm
;
7521 if (is_fully_specified_xlfd (fontname
))
7525 Lisp_Object matched_fonts
;
7527 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7528 if (NILP (matched_fonts
))
7530 name
= SDATA (XCAR (matched_fonts
));
7533 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7537 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7540 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7541 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7542 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7543 sizeof (Boolean
), sizeof (Boolean
)};
7544 static Fixed size_fixed
;
7545 static Boolean bold_p
, italic_p
;
7546 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7547 &bold_p
, &italic_p
};
7548 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7550 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7551 kDecomposeDiacriticsSelector
};
7552 Lisp_Object font_id_cons
;
7554 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7555 atsu_font_id_hash
, Qnil
);
7556 if (NILP (font_id_cons
))
7558 font_id
= cons_to_long (font_id_cons
);
7559 size_fixed
= Long2Fix (size
);
7560 bold_p
= (fontface
& bold
) != 0;
7561 italic_p
= (fontface
& italic
) != 0;
7562 err
= ATSUCreateStyle (&mac_style
);
7565 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7569 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7570 tags
, sizes
, values
);
7572 scriptcode
= kTextEncodingMacUnicode
;
7577 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7581 fontnum
= XINT (XCDR (tmp
));
7582 #if TARGET_API_MAC_CARBON
7583 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7585 scriptcode
= GetTextEncodingBase (encoding
);
7587 scriptcode
= FontToScript (fontnum
);
7591 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7593 font
->mac_fontnum
= fontnum
;
7594 font
->mac_fontsize
= size
;
7595 font
->mac_fontface
= fontface
;
7596 font
->mac_scriptcode
= scriptcode
;
7598 font
->mac_style
= mac_style
;
7599 #if USE_CG_TEXT_DRAWING
7600 font
->cg_font
= NULL
;
7601 font
->cg_glyphs
= NULL
;
7605 /* Apple Japanese (SJIS) font is listed as both
7606 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7607 (Roman script) in init_font_name_table (). The latter should be
7608 treated as a one-byte font. */
7609 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7610 font
->mac_scriptcode
= smRoman
;
7612 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7615 if (font
->mac_style
)
7620 font
->min_byte1
= 0;
7621 font
->max_byte1
= 0xff;
7622 font
->min_char_or_byte2
= 0;
7623 font
->max_char_or_byte2
= 0xff;
7625 font
->bounds
.rows
= xmalloc (sizeof (XCharStructRow
*) * 0x100);
7626 if (font
->bounds
.rows
== NULL
)
7628 mac_unload_font (&one_mac_display_info
, font
);
7631 bzero (font
->bounds
.rows
, sizeof (XCharStructRow
*) * 0x100);
7632 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStructRow
));
7633 if (font
->bounds
.rows
[0] == NULL
)
7635 mac_unload_font (&one_mac_display_info
, font
);
7638 bzero (font
->bounds
.rows
[0], sizeof (XCharStructRow
));
7640 #if USE_CG_TEXT_DRAWING
7642 FMFontFamily font_family
;
7644 ATSFontRef ats_font
;
7646 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7648 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7650 /* Use CG text drawing if italic/bold is not synthesized. */
7651 if (err
== noErr
&& style
== fontface
)
7653 ats_font
= FMGetATSFontRefFromFont (font_id
);
7654 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7659 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7660 if (font
->cg_glyphs
)
7661 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7663 space_bounds
= font
->bounds
.rows
[0]->per_char
+ 0x20;
7664 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7665 &font
->ascent
, &font
->descent
,
7667 #if USE_CG_TEXT_DRAWING
7668 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7676 mac_unload_font (&one_mac_display_info
, font
);
7679 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], 0x20);
7681 pcm
= font
->bounds
.rows
[0]->per_char
;
7682 for (c
= 0x21; c
<= 0xff; c
++)
7685 /* Soft hyphen is not supported in ATSUI. */
7693 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7694 #if USE_CG_TEXT_DRAWING
7695 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7701 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], c
);
7703 #if USE_CG_TEXT_DRAWING
7704 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7706 /* Don't use CG text drawing if font substitution occurs in
7707 ASCII or Latin-1 characters. */
7708 CGFontRelease (font
->cg_font
);
7709 font
->cg_font
= NULL
;
7710 xfree (font
->cg_glyphs
);
7711 font
->cg_glyphs
= NULL
;
7720 SInt16 old_fontnum
, old_fontsize
;
7722 FontInfo the_fontinfo
;
7723 int is_two_byte_font
;
7725 /* Save the current font number used. */
7727 #if TARGET_API_MAC_CARBON
7728 old_fontnum
= GetPortTextFont (port
);
7729 old_fontsize
= GetPortTextSize (port
);
7730 old_fontface
= GetPortTextFace (port
);
7732 old_fontnum
= port
->txFont
;
7733 old_fontsize
= port
->txSize
;
7734 old_fontface
= port
->txFace
;
7739 TextFace (fontface
);
7741 GetFontInfo (&the_fontinfo
);
7743 font
->ascent
= the_fontinfo
.ascent
;
7744 font
->descent
= the_fontinfo
.descent
;
7746 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7747 || font
->mac_scriptcode
== smTradChinese
7748 || font
->mac_scriptcode
== smSimpChinese
7749 || font
->mac_scriptcode
== smKorean
);
7751 if (is_two_byte_font
)
7755 font
->min_byte1
= 0xa1;
7756 font
->max_byte1
= 0xfe;
7757 font
->min_char_or_byte2
= 0xa1;
7758 font
->max_char_or_byte2
= 0xfe;
7760 /* Use the width of an "ideographic space" of that font
7761 because the_fontinfo.widMax returns the wrong width for
7763 switch (font
->mac_scriptcode
)
7766 font
->min_byte1
= 0x81;
7767 font
->max_byte1
= 0xfc;
7768 font
->min_char_or_byte2
= 0x40;
7769 font
->max_char_or_byte2
= 0xfc;
7770 char_width
= StringWidth("\p\x81\x40");
7773 font
->min_char_or_byte2
= 0x40;
7774 char_width
= StringWidth("\p\xa1\x40");
7777 char_width
= StringWidth("\p\xa1\xa1");
7780 char_width
= StringWidth("\p\xa1\xa1");
7784 font
->bounds
.per_char
= NULL
;
7786 if (fontface
& italic
)
7787 font
->max_bounds
.rbearing
= char_width
+ 1;
7789 font
->max_bounds
.rbearing
= char_width
;
7790 font
->max_bounds
.lbearing
= 0;
7791 font
->max_bounds
.width
= char_width
;
7792 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7793 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7795 font
->min_bounds
= font
->max_bounds
;
7801 font
->min_byte1
= font
->max_byte1
= 0;
7802 font
->min_char_or_byte2
= 0x20;
7803 font
->max_char_or_byte2
= 0xff;
7805 font
->bounds
.per_char
=
7806 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7807 if (font
->bounds
.per_char
== NULL
)
7809 mac_unload_font (&one_mac_display_info
, font
);
7812 bzero (font
->bounds
.per_char
,
7813 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7815 space_bounds
= font
->bounds
.per_char
;
7816 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
7817 space_bounds
, NULL
);
7819 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
7820 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
7823 /* Restore previous font number, size and face. */
7824 TextFont (old_fontnum
);
7825 TextSize (old_fontsize
);
7826 TextFace (old_fontface
);
7833 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
7834 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
7837 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
7839 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
7841 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
7843 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
7846 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
7848 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
7850 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
7852 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
7857 font
->mac_style
== NULL
&&
7859 font
->max_bounds
.width
== font
->min_bounds
.width
7860 && font
->min_bounds
.lbearing
>= 0
7861 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
7863 /* Fixed width and no overhangs. */
7864 xfree (font
->bounds
.per_char
);
7865 font
->bounds
.per_char
= NULL
;
7869 #if !defined (MAC_OS8) || USE_ATSUI
7870 /* AppKit and WebKit do some adjustment to the heights of Courier,
7871 Helvetica, and Times. This only works on the environments where
7872 srcCopy text transfer mode is never used. */
7874 #ifdef MAC_OS8 /* implies USE_ATSUI */
7877 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7878 || strcmp (family
, "times") == 0))
7879 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7887 mac_unload_font (dpyinfo
, font
)
7888 struct mac_display_info
*dpyinfo
;
7891 xfree (font
->full_name
);
7893 if (font
->mac_style
)
7897 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
7898 if (font
->bounds
.rows
[i
])
7899 xfree (font
->bounds
.rows
[i
]);
7900 xfree (font
->bounds
.rows
);
7901 ATSUDisposeStyle (font
->mac_style
);
7905 if (font
->bounds
.per_char
)
7906 xfree (font
->bounds
.per_char
);
7907 #if USE_CG_TEXT_DRAWING
7909 CGFontRelease (font
->cg_font
);
7910 if (font
->cg_glyphs
)
7911 xfree (font
->cg_glyphs
);
7917 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7918 pointer to the structure font_info while allocating it dynamically.
7919 If SIZE is 0, load any size of font.
7920 If loading is failed, return NULL. */
7923 x_load_font (f
, fontname
, size
)
7925 register char *fontname
;
7928 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7929 Lisp_Object font_names
;
7931 /* Get a list of all the fonts that match this name. Once we
7932 have a list of matching fonts, we compare them against the fonts
7933 we already have by comparing names. */
7934 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7936 if (!NILP (font_names
))
7941 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7942 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7943 if (dpyinfo
->font_table
[i
].name
7944 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7945 SDATA (XCAR (tail
)))
7946 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7947 SDATA (XCAR (tail
)))))
7948 return (dpyinfo
->font_table
+ i
);
7953 /* Load the font and add it to the table. */
7956 struct MacFontStruct
*font
;
7957 struct font_info
*fontp
;
7958 unsigned long value
;
7961 fontname
= (char *) SDATA (XCAR (font_names
));
7964 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7969 /* Find a free slot in the font table. */
7970 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7971 if (dpyinfo
->font_table
[i
].name
== NULL
)
7974 /* If no free slot found, maybe enlarge the font table. */
7975 if (i
== dpyinfo
->n_fonts
7976 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7979 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7980 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7982 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7985 fontp
= dpyinfo
->font_table
+ i
;
7986 if (i
== dpyinfo
->n_fonts
)
7989 /* Now fill in the slots of *FONTP. */
7991 bzero (fontp
, sizeof (*fontp
));
7993 fontp
->font_idx
= i
;
7994 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7995 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7997 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7999 /* Fixed width font. */
8000 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8007 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8008 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8010 fontp
->space_width
= pcm
->width
;
8012 fontp
->space_width
= FONT_WIDTH (font
);
8016 int width
= pcm
->width
;
8017 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8018 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8019 width
+= pcm
->width
;
8020 fontp
->average_width
= width
/ 95;
8023 fontp
->average_width
= FONT_WIDTH (font
);
8026 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8027 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8029 fontp
->size
= font
->max_bounds
.width
;
8030 fontp
->height
= FONT_HEIGHT (font
);
8032 /* For some font, ascent and descent in max_bounds field is
8033 larger than the above value. */
8034 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8035 if (max_height
> fontp
->height
)
8036 fontp
->height
= max_height
;
8039 /* The slot `encoding' specifies how to map a character
8040 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8041 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8042 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8043 2:0xA020..0xFF7F). For the moment, we don't know which charset
8044 uses this font. So, we set information in fontp->encoding[1]
8045 which is never used by any charset. If mapping can't be
8046 decided, set FONT_ENCODING_NOT_DECIDED. */
8047 if (font
->mac_scriptcode
== smJapanese
)
8048 fontp
->encoding
[1] = 4;
8052 = (font
->max_byte1
== 0
8054 ? (font
->min_char_or_byte2
< 0x80
8055 ? (font
->max_char_or_byte2
< 0x80
8056 ? 0 /* 0x20..0x7F */
8057 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8058 : 1) /* 0xA0..0xFF */
8060 : (font
->min_byte1
< 0x80
8061 ? (font
->max_byte1
< 0x80
8062 ? (font
->min_char_or_byte2
< 0x80
8063 ? (font
->max_char_or_byte2
< 0x80
8064 ? 0 /* 0x2020..0x7F7F */
8065 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8066 : 3) /* 0x20A0..0x7FFF */
8067 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8068 : (font
->min_char_or_byte2
< 0x80
8069 ? (font
->max_char_or_byte2
< 0x80
8070 ? 2 /* 0xA020..0xFF7F */
8071 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8072 : 1))); /* 0xA0A0..0xFFFF */
8075 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8076 fontp
->baseline_offset
8077 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8078 ? (long) value
: 0);
8079 fontp
->relative_compose
8080 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8081 ? (long) value
: 0);
8082 fontp
->default_ascent
8083 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8084 ? (long) value
: 0);
8086 fontp
->baseline_offset
= 0;
8087 fontp
->relative_compose
= 0;
8088 fontp
->default_ascent
= 0;
8091 /* Set global flag fonts_changed_p to non-zero if the font loaded
8092 has a character with a smaller width than any other character
8093 before, or if the font loaded has a smaller height than any
8094 other font loaded before. If this happens, it will make a
8095 glyph matrix reallocation necessary. */
8096 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8103 /* Return a pointer to struct font_info of a font named FONTNAME for
8104 frame F. If no such font is loaded, return NULL. */
8107 x_query_font (f
, fontname
)
8109 register char *fontname
;
8111 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8114 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8115 if (dpyinfo
->font_table
[i
].name
8116 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8117 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8118 return (dpyinfo
->font_table
+ i
);
8123 /* Find a CCL program for a font specified by FONTP, and set the member
8124 `encoder' of the structure. */
8127 x_find_ccl_program (fontp
)
8128 struct font_info
*fontp
;
8130 Lisp_Object list
, elt
;
8132 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8136 && STRINGP (XCAR (elt
))
8137 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8143 struct ccl_program
*ccl
8144 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8146 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8149 fontp
->font_encoder
= ccl
;
8155 /* The Mac Event loop code */
8157 #if !TARGET_API_MAC_CARBON
8159 #include <Quickdraw.h>
8160 #include <Balloons.h>
8161 #include <Devices.h>
8163 #include <Gestalt.h>
8165 #include <Processes.h>
8167 #include <ToolUtils.h>
8168 #include <TextUtils.h>
8169 #include <Dialogs.h>
8172 #include <Resources.h>
8177 #endif /* ! TARGET_API_MAC_CARBON */
8182 #define WINDOW_RESOURCE 128
8183 #define TERM_WINDOW_RESOURCE 129
8185 #define DEFAULT_NUM_COLS 80
8187 #define MIN_DOC_SIZE 64
8188 #define MAX_DOC_SIZE 32767
8190 #define EXTRA_STACK_ALLOC (256 * 1024)
8192 #define ARGV_STRING_LIST_ID 129
8193 #define ABOUT_ALERT_ID 128
8194 #define RAM_TOO_LARGE_ALERT_ID 129
8196 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8197 Lisp_Object Qreverse
;
8200 /* Modifier associated with the control key, or nil to ignore. */
8201 Lisp_Object Vmac_control_modifier
;
8203 /* Modifier associated with the option key, or nil to ignore. */
8204 Lisp_Object Vmac_option_modifier
;
8206 /* Modifier associated with the command key, or nil to ignore. */
8207 Lisp_Object Vmac_command_modifier
;
8209 /* Modifier associated with the function key, or nil to ignore. */
8210 Lisp_Object Vmac_function_modifier
;
8212 /* True if the option and command modifiers should be used to emulate
8213 a three button mouse */
8214 Lisp_Object Vmac_emulate_three_button_mouse
;
8216 #if USE_CARBON_EVENTS
8217 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8218 mouse-2, instead of mouse-3. */
8219 int mac_wheel_button_is_mouse_2
;
8221 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8222 for processing before Emacs sees it. */
8223 int mac_pass_command_to_system
;
8225 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8226 for processing before Emacs sees it. */
8227 int mac_pass_control_to_system
;
8230 /* Points to the variable `inev' in the function XTread_socket. It is
8231 used for passing an input event to the function back from
8232 Carbon/Apple event handlers. */
8233 static struct input_event
*read_socket_inev
= NULL
;
8235 Point saved_menu_event_location
;
8238 #if USE_CARBON_EVENTS
8239 static Lisp_Object Qhicommand
;
8241 extern int mac_ready_for_apple_events
;
8242 extern Lisp_Object Qundefined
;
8243 extern void init_apple_event_handler
P_ ((void));
8244 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8245 Lisp_Object
*, Lisp_Object
*,
8247 extern OSErr init_coercion_handler
P_ ((void));
8249 #if TARGET_API_MAC_CARBON
8251 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8252 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8253 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8254 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8257 #if USE_CARBON_EVENTS
8259 extern void init_service_handler ();
8260 static Lisp_Object Qservices
, Qpaste
, Qperform
;
8262 /* Window Event Handler */
8263 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8266 OSErr
install_window_handler (WindowPtr
);
8268 extern void init_emacs_passwd_dir ();
8269 extern int emacs_main (int, char **, char **);
8271 extern void initialize_applescript();
8272 extern void terminate_applescript();
8275 #if USE_CARBON_EVENTS
8276 mac_to_emacs_modifiers (UInt32 mods
)
8278 mac_to_emacs_modifiers (EventModifiers mods
)
8281 unsigned int result
= 0;
8282 if (mods
& shiftKey
)
8283 result
|= shift_modifier
;
8285 /* Deactivated to simplify configuration:
8286 if Vmac_option_modifier is non-NIL, we fully process the Option
8287 key. Otherwise, we only process it if an additional Ctrl or Command
8288 is pressed. That way the system may convert the character to a
8290 if ((mods & optionKey) &&
8291 (( !NILP(Vmac_option_modifier) ||
8292 ((mods & cmdKey) || (mods & controlKey))))) */
8294 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8295 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8297 result
|= XUINT(val
);
8299 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8300 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8302 result
|= XUINT(val
);
8304 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8305 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8307 result
|= XUINT(val
);
8311 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8312 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8314 result
|= XUINT(val
);
8322 mac_get_emulated_btn ( UInt32 modifiers
)
8325 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8326 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8327 if (modifiers
& cmdKey
)
8328 result
= cmdIs3
? 2 : 1;
8329 else if (modifiers
& optionKey
)
8330 result
= cmdIs3
? 1 : 2;
8335 #if USE_CARBON_EVENTS
8336 /* Obtains the event modifiers from the event ref and then calls
8337 mac_to_emacs_modifiers. */
8339 mac_event_to_emacs_modifiers (EventRef eventRef
)
8342 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8343 sizeof (UInt32
), NULL
, &mods
);
8344 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8345 GetEventClass(eventRef
) == kEventClassMouse
)
8347 mods
&= ~(optionKey
| cmdKey
);
8349 return mac_to_emacs_modifiers (mods
);
8352 /* Given an event ref, return the code to use for the mouse button
8353 code in the emacs input_event. */
8355 mac_get_mouse_btn (EventRef ref
)
8357 EventMouseButton result
= kEventMouseButtonPrimary
;
8358 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8359 sizeof (EventMouseButton
), NULL
, &result
);
8362 case kEventMouseButtonPrimary
:
8363 if (NILP (Vmac_emulate_three_button_mouse
))
8367 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8368 sizeof (UInt32
), NULL
, &mods
);
8369 return mac_get_emulated_btn(mods
);
8371 case kEventMouseButtonSecondary
:
8372 return mac_wheel_button_is_mouse_2
? 2 : 1;
8373 case kEventMouseButtonTertiary
:
8374 case 4: /* 4 is the number for the mouse wheel button */
8375 return mac_wheel_button_is_mouse_2
? 1 : 2;
8381 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8382 events. However the click of the mouse wheel is not converted to a
8383 mouseDown or mouseUp event. Likewise for dead key down events.
8384 This calls ConvertEventRef, but then checks to see if it is a mouse
8385 up/down, or a dead key down carbon event that has not been
8386 converted, and if so, converts it by hand (to be picked up in the
8387 XTread_socket loop). */
8388 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8390 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8395 switch (GetEventClass (eventRef
))
8397 case kEventClassMouse
:
8398 switch (GetEventKind (eventRef
))
8400 case kEventMouseDown
:
8401 eventRec
->what
= mouseDown
;
8406 eventRec
->what
= mouseUp
;
8415 case kEventClassKeyboard
:
8416 switch (GetEventKind (eventRef
))
8418 case kEventRawKeyDown
:
8420 unsigned char char_codes
;
8423 eventRec
->what
= keyDown
;
8424 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8425 NULL
, sizeof (char), NULL
, &char_codes
);
8426 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8427 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8428 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8444 /* Need where and when. */
8447 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8448 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8449 /* Use two step process because new event modifiers are 32-bit
8450 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8451 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8452 NULL
, sizeof (UInt32
), NULL
, &mods
);
8453 eventRec
->modifiers
= mods
;
8455 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8466 Handle menubar_handle
;
8467 MenuHandle menu_handle
;
8469 menubar_handle
= GetNewMBar (128);
8470 if(menubar_handle
== NULL
)
8472 SetMenuBar (menubar_handle
);
8475 #if !TARGET_API_MAC_CARBON
8476 menu_handle
= GetMenuHandle (M_APPLE
);
8477 if(menu_handle
!= NULL
)
8478 AppendResMenu (menu_handle
,'DRVR');
8486 do_init_managers (void)
8488 #if !TARGET_API_MAC_CARBON
8489 InitGraf (&qd
.thePort
);
8491 FlushEvents (everyEvent
, 0);
8496 #endif /* !TARGET_API_MAC_CARBON */
8499 #if !TARGET_API_MAC_CARBON
8500 /* set up some extra stack space for use by emacs */
8501 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8503 /* MaxApplZone must be called for AppleScript to execute more
8504 complicated scripts */
8507 #endif /* !TARGET_API_MAC_CARBON */
8511 do_check_ram_size (void)
8513 SInt32 physical_ram_size
, logical_ram_size
;
8515 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8516 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8517 || physical_ram_size
> (1 << VALBITS
)
8518 || logical_ram_size
> (1 << VALBITS
))
8520 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8526 do_window_update (WindowPtr win
)
8528 struct frame
*f
= mac_window_to_frame (win
);
8532 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8534 if (win
!= tip_window
)
8536 if (f
->async_visible
== 0)
8538 /* Update events may occur when a frame gets iconified. */
8540 f
->async_visible
= 1;
8541 f
->async_iconified
= 0;
8542 SET_FRAME_GARBAGED (f
);
8548 #if TARGET_API_MAC_CARBON
8549 RgnHandle region
= NewRgn ();
8551 GetPortVisibleRegion (GetWindowPort (win
), region
);
8552 GetRegionBounds (region
, &r
);
8553 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8554 UpdateControls (win
, region
);
8555 DisposeRgn (region
);
8557 r
= (*win
->visRgn
)->rgnBBox
;
8558 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8559 UpdateControls (win
, win
->visRgn
);
8568 is_emacs_window (WindowPtr win
)
8570 Lisp_Object tail
, frame
;
8575 FOR_EACH_FRAME (tail
, frame
)
8576 if (FRAME_MAC_P (XFRAME (frame
)))
8577 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8586 /* Window-activate events will do the job. */
8592 /* Window-deactivate events will do the job. */
8597 do_apple_menu (SInt16 menu_item
)
8599 #if !TARGET_API_MAC_CARBON
8601 SInt16 da_driver_refnum
;
8603 if (menu_item
== I_ABOUT
)
8604 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8607 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8608 da_driver_refnum
= OpenDeskAcc (item_name
);
8610 #endif /* !TARGET_API_MAC_CARBON */
8614 do_menu_choice (SInt32 menu_choice
)
8616 SInt16 menu_id
, menu_item
;
8618 menu_id
= HiWord (menu_choice
);
8619 menu_item
= LoWord (menu_choice
);
8627 do_apple_menu (menu_item
);
8632 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8633 MenuHandle menu
= GetMenuHandle (menu_id
);
8638 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8639 menubar_selection_callback (f
, refcon
);
8648 /* Handle drags in size box. Based on code contributed by Ben
8649 Mesander and IM - Window Manager A. */
8652 do_grow_window (WindowPtr w
, EventRecord
*e
)
8655 int rows
, columns
, width
, height
;
8656 struct frame
*f
= mac_window_to_frame (w
);
8657 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8658 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8659 #if TARGET_API_MAC_CARBON
8665 if (size_hints
->flags
& PMinSize
)
8667 min_width
= size_hints
->min_width
;
8668 min_height
= size_hints
->min_height
;
8670 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8672 #if TARGET_API_MAC_CARBON
8673 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8675 height
= new_rect
.bottom
- new_rect
.top
;
8676 width
= new_rect
.right
- new_rect
.left
;
8678 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8679 /* see if it really changed size */
8682 height
= HiWord (grow_size
);
8683 width
= LoWord (grow_size
);
8686 if (width
!= FRAME_PIXEL_WIDTH (f
)
8687 || height
!= FRAME_PIXEL_HEIGHT (f
))
8689 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8690 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8692 x_set_window_size (f
, 0, columns
, rows
);
8697 /* Handle clicks in zoom box. Calculation of "standard state" based
8698 on code in IM - Window Manager A and code contributed by Ben
8699 Mesander. The standard state of an Emacs window is 80-characters
8700 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8703 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8706 Rect zoom_rect
, port_rect
;
8708 int w_title_height
, columns
, rows
, width
, height
;
8709 struct frame
*f
= mac_window_to_frame (w
);
8710 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8712 #if TARGET_API_MAC_CARBON
8714 Point standard_size
;
8716 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8717 standard_size
.v
= dpyinfo
->height
;
8719 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8720 zoom_in_or_out
= inZoomIn
;
8723 /* Adjust the standard size according to character boundaries. */
8725 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8726 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8727 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8728 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8729 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8730 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8731 && port_rect
.left
== zoom_rect
.left
8732 && port_rect
.top
== zoom_rect
.top
)
8733 zoom_in_or_out
= inZoomIn
;
8735 zoom_in_or_out
= inZoomOut
;
8738 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8740 #else /* not TARGET_API_MAC_CARBON */
8741 GetPort (&save_port
);
8743 SetPortWindowPort (w
);
8745 /* Clear window to avoid flicker. */
8746 EraseRect (&(w
->portRect
));
8747 if (zoom_in_or_out
== inZoomOut
)
8749 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8750 LocalToGlobal (&top_left
);
8752 /* calculate height of window's title bar */
8753 w_title_height
= top_left
.v
- 1
8754 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8756 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8757 zoom_rect
= qd
.screenBits
.bounds
;
8758 zoom_rect
.top
+= w_title_height
;
8759 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8761 zoom_rect
.right
= zoom_rect
.left
8762 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8764 /* Adjust the standard size according to character boundaries. */
8765 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8767 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8769 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8773 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8775 SetPort (save_port
);
8776 #endif /* not TARGET_API_MAC_CARBON */
8778 /* retrieve window size and update application values */
8779 #if TARGET_API_MAC_CARBON
8780 GetWindowPortBounds (w
, &port_rect
);
8782 port_rect
= w
->portRect
;
8784 height
= port_rect
.bottom
- port_rect
.top
;
8785 width
= port_rect
.right
- port_rect
.left
;
8787 if (width
!= FRAME_PIXEL_WIDTH (f
)
8788 || height
!= FRAME_PIXEL_HEIGHT (f
))
8790 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8791 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8793 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8794 SET_FRAME_GARBAGED (f
);
8795 cancel_mouse_face (f
);
8797 FRAME_PIXEL_WIDTH (f
) = width
;
8798 FRAME_PIXEL_HEIGHT (f
) = height
;
8800 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8804 mac_store_apple_event (class, id
, desc
)
8805 Lisp_Object
class, id
;
8809 struct input_event buf
;
8812 desc_copy
= xmalloc (sizeof (AEDesc
));
8813 if (desc_copy
== NULL
)
8816 err
= AEDuplicateDesc (desc
, desc_copy
);
8821 buf
.kind
= MAC_APPLE_EVENT
;
8824 buf
.code
= (int)desc_copy
;
8825 XSETFRAME (buf
.frame_or_window
,
8826 mac_focus_frame (&one_mac_display_info
));
8828 kbd_buffer_store_event (&buf
);
8835 mac_make_lispy_event_code (code
)
8838 AEDesc
*desc
= (AEDesc
*)code
;
8841 obj
= mac_aedesc_to_lisp (desc
);
8842 AEDisposeDesc (desc
);
8848 #if USE_CARBON_EVENTS
8849 static pascal OSStatus
8850 mac_handle_command_event (next_handler
, event
, data
)
8851 EventHandlerCallRef next_handler
;
8858 Lisp_Object class_key
, id_key
, binding
;
8860 result
= CallNextEventHandler (next_handler
, event
);
8861 if (result
!= eventNotHandledErr
)
8864 GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8865 sizeof (HICommand
), NULL
, &command
);
8867 if (command
.commandID
== 0)
8868 return eventNotHandledErr
;
8870 /* A HICommand event is mapped to an Apple event whose event class
8871 symbol is `hicommand' and event ID is its command ID. */
8872 class_key
= Qhicommand
;
8873 mac_find_apple_event_spec (0, command
.commandID
,
8874 &class_key
, &id_key
, &binding
);
8875 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
8876 if (INTEGERP (binding
))
8877 return XINT (binding
);
8880 AppleEvent apple_event
;
8882 static EventParamName names
[] = {kEventParamDirectObject
,
8883 kEventParamKeyModifiers
};
8884 static EventParamType types
[] = {typeHICommand
,
8886 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
8890 err
= mac_store_apple_event (class_key
, id_key
, &apple_event
);
8891 AEDisposeDesc (&apple_event
);
8897 return eventNotHandledErr
;
8901 init_command_handler ()
8904 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8905 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8907 if (handle_command_eventUPP
== NULL
)
8908 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8909 return InstallApplicationEventHandler (handle_command_eventUPP
,
8910 GetEventTypeCount (specs
), specs
,
8914 static pascal OSStatus
8915 mac_handle_window_event (next_handler
, event
, data
)
8916 EventHandlerCallRef next_handler
;
8923 XSizeHints
*size_hints
;
8925 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8926 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8928 switch (GetEventKind (event
))
8930 case kEventWindowUpdate
:
8931 result
= CallNextEventHandler (next_handler
, event
);
8932 if (result
!= eventNotHandledErr
)
8935 do_window_update (wp
);
8938 case kEventWindowBoundsChanging
:
8939 result
= CallNextEventHandler (next_handler
, event
);
8940 if (result
!= eventNotHandledErr
)
8943 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8944 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8945 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8946 if ((attributes
& kWindowBoundsChangeUserResize
)
8947 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8948 == (PResizeInc
| PBaseSize
| PMinSize
)))
8953 GetEventParameter (event
, kEventParamCurrentBounds
,
8955 NULL
, sizeof (Rect
), NULL
, &bounds
);
8956 width
= bounds
.right
- bounds
.left
;
8957 height
= bounds
.bottom
- bounds
.top
;
8959 if (width
< size_hints
->min_width
)
8960 width
= size_hints
->min_width
;
8962 width
= size_hints
->base_width
8963 + (int) ((width
- size_hints
->base_width
)
8964 / (float) size_hints
->width_inc
+ .5)
8965 * size_hints
->width_inc
;
8967 if (height
< size_hints
->min_height
)
8968 height
= size_hints
->min_height
;
8970 height
= size_hints
->base_height
8971 + (int) ((height
- size_hints
->base_height
)
8972 / (float) size_hints
->height_inc
+ .5)
8973 * size_hints
->height_inc
;
8975 bounds
.right
= bounds
.left
+ width
;
8976 bounds
.bottom
= bounds
.top
+ height
;
8977 SetEventParameter (event
, kEventParamCurrentBounds
,
8978 typeQDRectangle
, sizeof (Rect
), &bounds
);
8983 case kEventWindowShown
:
8984 case kEventWindowHidden
:
8985 case kEventWindowExpanded
:
8986 case kEventWindowCollapsed
:
8987 result
= CallNextEventHandler (next_handler
, event
);
8989 mac_handle_visibility_change (mac_window_to_frame (wp
));
8995 return eventNotHandledErr
;
8998 static pascal OSStatus
8999 mac_handle_mouse_event (next_handler
, event
, data
)
9000 EventHandlerCallRef next_handler
;
9006 switch (GetEventKind (event
))
9008 case kEventMouseWheelMoved
:
9012 EventMouseWheelAxis axis
;
9016 result
= CallNextEventHandler (next_handler
, event
);
9017 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9020 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9021 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9022 f
= mac_window_to_frame (wp
);
9023 if (f
!= mac_focus_frame (&one_mac_display_info
))
9026 GetEventParameter (event
, kEventParamMouseWheelAxis
,
9027 typeMouseWheelAxis
, NULL
,
9028 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9029 if (axis
!= kEventMouseWheelAxisY
)
9032 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
9033 NULL
, sizeof (SInt32
), NULL
, &delta
);
9034 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9035 NULL
, sizeof (Point
), NULL
, &point
);
9036 read_socket_inev
->kind
= WHEEL_EVENT
;
9037 read_socket_inev
->code
= 0;
9038 read_socket_inev
->modifiers
=
9039 (mac_event_to_emacs_modifiers (event
)
9040 | ((delta
< 0) ? down_modifier
: up_modifier
));
9041 SetPortWindowPort (wp
);
9042 GlobalToLocal (&point
);
9043 XSETINT (read_socket_inev
->x
, point
.h
);
9044 XSETINT (read_socket_inev
->y
, point
.v
);
9045 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9055 return eventNotHandledErr
;
9060 mac_store_services_event (event
)
9064 AppleEvent apple_event
;
9067 switch (GetEventKind (event
))
9069 case kEventServicePaste
:
9071 err
= create_apple_event_from_event_ref (event
, 0, NULL
, NULL
,
9075 case kEventServicePerform
:
9077 static EventParamName names
[] = {kEventParamServiceMessageName
,
9078 kEventParamServiceUserData
};
9079 static EventParamType types
[] = {typeCFStringRef
,
9083 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9094 err
= mac_store_apple_event (Qservices
, id_key
, &apple_event
);
9095 AEDisposeDesc (&apple_event
);
9100 #endif /* MAC_OSX */
9101 #endif /* USE_CARBON_EVENTS */
9105 install_window_handler (window
)
9109 #if USE_CARBON_EVENTS
9110 EventTypeSpec specs_window
[] =
9111 {{kEventClassWindow
, kEventWindowUpdate
},
9112 {kEventClassWindow
, kEventWindowBoundsChanging
},
9113 {kEventClassWindow
, kEventWindowShown
},
9114 {kEventClassWindow
, kEventWindowHidden
},
9115 {kEventClassWindow
, kEventWindowExpanded
},
9116 {kEventClassWindow
, kEventWindowCollapsed
}};
9117 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9118 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9119 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9121 if (handle_window_eventUPP
== NULL
)
9122 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9123 if (handle_mouse_eventUPP
== NULL
)
9124 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9125 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9126 GetEventTypeCount (specs_window
),
9127 specs_window
, NULL
, NULL
);
9129 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9130 GetEventTypeCount (specs_mouse
),
9131 specs_mouse
, NULL
, NULL
);
9133 #if TARGET_API_MAC_CARBON
9134 if (mac_do_track_dragUPP
== NULL
)
9135 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9136 if (mac_do_receive_dragUPP
== NULL
)
9137 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9140 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9142 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9148 remove_window_handler (window
)
9151 #if TARGET_API_MAC_CARBON
9152 if (mac_do_track_dragUPP
)
9153 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9154 if (mac_do_receive_dragUPP
)
9155 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9159 #if TARGET_API_MAC_CARBON
9161 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9162 void *handlerRefCon
, DragReference theDrag
)
9164 static int can_accept
;
9167 ItemReference theItem
;
9168 FlavorFlags theFlags
;
9171 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9172 return dragNotAcceptedErr
;
9176 case kDragTrackingEnterHandler
:
9177 CountDragItems (theDrag
, &items
);
9179 for (index
= 1; index
<= items
; index
++)
9181 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9182 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9183 if (result
== noErr
)
9191 case kDragTrackingEnterWindow
:
9194 RgnHandle hilite_rgn
= NewRgn ();
9196 struct frame
*f
= mac_window_to_frame (window
);
9198 GetWindowPortBounds (window
, &r
);
9199 OffsetRect (&r
, -r
.left
, -r
.top
);
9200 RectRgn (hilite_rgn
, &r
);
9201 ShowDragHilite (theDrag
, hilite_rgn
, true);
9202 DisposeRgn (hilite_rgn
);
9203 SetThemeCursor (kThemeCopyArrowCursor
);
9207 case kDragTrackingInWindow
:
9210 case kDragTrackingLeaveWindow
:
9213 struct frame
*f
= mac_window_to_frame (window
);
9215 HideDragHilite (theDrag
);
9216 SetThemeCursor (kThemeArrowCursor
);
9220 case kDragTrackingLeaveHandler
:
9228 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9229 DragReference theDrag
)
9233 FlavorFlags theFlags
;
9236 ItemReference theItem
;
9238 Size size
= sizeof (HFSFlavor
);
9239 Lisp_Object file_list
;
9241 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9242 return dragNotAcceptedErr
;
9245 GetDragMouse (theDrag
, &mouse
, 0L);
9246 CountDragItems (theDrag
, &items
);
9247 for (index
= 1; index
<= items
; index
++)
9249 /* Only handle file references. */
9250 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9251 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9252 if (result
== noErr
)
9257 err
= GetFlavorData (theDrag
, theItem
, flavorTypeHFS
,
9260 err
= AECoercePtr (typeFSS
, &data
.fileSpec
, sizeof (FSSpec
),
9261 TYPE_FILE_NAME
, &desc
);
9266 /* x-dnd functions expect undecoded filenames. */
9267 file
= make_uninit_string (AEGetDescDataSize (&desc
));
9268 err
= AEGetDescData (&desc
, SDATA (file
), SBYTES (file
));
9270 file_list
= Fcons (file
, file_list
);
9271 AEDisposeDesc (&desc
);
9275 /* If there are items in the list, construct an event and post it to
9276 the queue like an interrupt using kbd_buffer_store_event. */
9277 if (!NILP (file_list
))
9279 struct input_event event
;
9281 struct frame
*f
= mac_window_to_frame (window
);
9284 GlobalToLocal (&mouse
);
9285 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9287 event
.kind
= DRAG_N_DROP_EVENT
;
9289 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9290 event
.timestamp
= TickCount () * (1000 / 60);
9291 XSETINT (event
.x
, mouse
.h
);
9292 XSETINT (event
.y
, mouse
.v
);
9293 XSETFRAME (frame
, f
);
9294 event
.frame_or_window
= frame
;
9295 event
.arg
= file_list
;
9296 /* Post to the interrupt queue */
9297 kbd_buffer_store_event (&event
);
9298 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9300 ProcessSerialNumber psn
;
9301 GetCurrentProcess (&psn
);
9302 SetFrontProcess (&psn
);
9308 return dragNotAcceptedErr
;
9315 profiler_exit_proc ()
9317 ProfilerDump ("\pEmacs.prof");
9322 /* These few functions implement Emacs as a normal Mac application
9323 (almost): set up the heap and the Toolbox, handle necessary system
9324 events plus a few simple menu events. They also set up Emacs's
9325 access to functions defined in the rest of this file. Emacs uses
9326 function hooks to perform all its terminal I/O. A complete list of
9327 these functions appear in termhooks.h. For what they do, read the
9328 comments there and see also w32term.c and xterm.c. What's
9329 noticeably missing here is the event loop, which is normally
9330 present in most Mac application. After performing the necessary
9331 Mac initializations, main passes off control to emacs_main
9332 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9333 (defined further below) to read input. This is where
9334 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9341 #if __profile__ /* is the profiler on? */
9342 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9347 /* set creator and type for files created by MSL */
9352 do_init_managers ();
9357 do_check_ram_size ();
9360 init_emacs_passwd_dir ();
9364 init_coercion_handler ();
9366 initialize_applescript ();
9368 init_apple_event_handler ();
9374 /* set up argv array from STR# resource */
9375 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9379 /* free up AppleScript resources on exit */
9380 atexit (terminate_applescript
);
9382 #if __profile__ /* is the profiler on? */
9383 atexit (profiler_exit_proc
);
9386 /* 3rd param "envp" never used in emacs_main */
9387 (void) emacs_main (argc
, argv
, 0);
9390 /* Never reached - real exit in Fkill_emacs */
9395 /* Table for translating Mac keycode to X keysym values. Contributed
9397 Mapping for special keys is now identical to that in Apple X11
9398 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9399 on the right of the Cmd key on laptops, and fn + `enter' (->
9401 static unsigned char keycode_to_xkeysym_table
[] = {
9402 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9403 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9404 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9406 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9407 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9408 /*0x38*/ 0, 0, 0, 0,
9409 /*0x3C*/ 0, 0, 0, 0,
9411 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9412 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9413 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9414 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9416 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9417 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9418 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9419 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9421 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9422 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9423 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9424 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9426 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9427 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9428 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9429 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9434 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9436 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9437 return *xKeySym
!= 0;
9440 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9441 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9442 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9443 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9445 /*0x30*/ 0, 0, 0, 0,
9446 /*0x34*/ 0, 0, 0, 0,
9447 /*0x38*/ 0, 0, 0, 0,
9448 /*0x3C*/ 0, 0, 0, 0,
9450 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9451 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9452 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9453 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9455 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9456 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9457 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9458 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9460 /*0x60*/ 0, 0, 0, 0,
9461 /*0x64*/ 0, 0, 0, 0,
9462 /*0x68*/ 0, 0, 0, 0,
9463 /*0x6C*/ 0, 0, 0, 0,
9465 /*0x70*/ 0, 0, 0, 0,
9466 /*0x74*/ 0, 0, 0, 0,
9467 /*0x78*/ 0, 0, 0, 0,
9471 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9474 /* Use the special map to translate keys when function modifier is
9475 to be caught. KeyTranslate can't be used in that case.
9476 We can't detect the function key using the input_event.modifiers,
9477 because this uses the high word of an UInt32. Therefore,
9478 we'll just read it out of the original eventRef.
9482 /* TODO / known issues
9484 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9485 The above table always translates to lower characters. We need to use
9486 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9488 - The table is meant for English language keyboards, and it will work
9489 for many others with the exception of key combinations like Fn-ö on
9490 a German keyboard, which is currently mapped to Fn-;.
9491 How to solve this without keeping separate tables for all keyboards
9492 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9493 value for keycode with the modifiers in he high byte, i.e. no room for the
9494 Fn modifier. That's why we need the table.
9499 if (!NILP(Vmac_function_modifier
))
9501 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9502 sizeof (UInt32
), NULL
, &mods
);
9503 if (mods
& kEventKeyModifierFnMask
)
9504 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9506 return (*newCode
!= 0);
9514 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9516 EventModifiers mapped_modifiers
=
9517 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9518 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9519 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9521 if (mods
& mapped_modifiers
)
9523 /* This code comes from Keyboard Resource,
9524 Appendix C of IM - Text. This is necessary
9525 since shift is ignored in KCHR table
9526 translation when option or command is pressed.
9527 It also does not translate correctly
9528 control-shift chars like C-% so mask off shift
9531 Not done for combinations with the option key (alt)
9532 unless it is to be caught by Emacs: this is
9533 to preserve key combinations translated by the OS
9536 /* Mask off modifier keys that are mapped to some Emacs
9538 int new_modifiers
= mods
& ~mapped_modifiers
;
9539 /* set high byte of keycode to modifier high byte*/
9540 int new_keycode
= keycode
| new_modifiers
;
9541 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9542 unsigned long some_state
= 0;
9543 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9544 &some_state
) & 0xff;
9545 /* TO DO: Recognize two separate resulting characters, "for
9546 example, when the user presses Option-E followed by N, you
9547 can map this through the KeyTranslate function using the
9548 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9549 returns as two characters in the bytes labeled Character code
9550 1 and Character code 2." (from Carbon API doc) */
9558 #if !USE_CARBON_EVENTS
9559 static RgnHandle mouse_region
= NULL
;
9562 mac_wait_next_event (er
, sleep_time
, dequeue
)
9567 static EventRecord er_buf
= {nullEvent
};
9568 UInt32 target_tick
, current_tick
;
9569 EventMask event_mask
;
9571 if (mouse_region
== NULL
)
9572 mouse_region
= NewRgn ();
9574 event_mask
= everyEvent
;
9575 if (!mac_ready_for_apple_events
)
9576 event_mask
-= highLevelEventMask
;
9578 current_tick
= TickCount ();
9579 target_tick
= current_tick
+ sleep_time
;
9581 if (er_buf
.what
== nullEvent
)
9582 while (!WaitNextEvent (event_mask
, &er_buf
,
9583 target_tick
- current_tick
, mouse_region
))
9585 current_tick
= TickCount ();
9586 if (target_tick
<= current_tick
)
9592 er_buf
.what
= nullEvent
;
9595 #endif /* not USE_CARBON_EVENTS */
9597 /* Emacs calls this whenever it wants to read an input event from the
9600 XTread_socket (sd
, expected
, hold_quit
)
9602 struct input_event
*hold_quit
;
9604 struct input_event inev
;
9606 #if USE_CARBON_EVENTS
9608 EventTargetRef toolbox_dispatcher
;
9611 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9613 if (interrupt_input_blocked
)
9615 interrupt_input_pending
= 1;
9619 interrupt_input_pending
= 0;
9622 /* So people can tell when we have read the available input. */
9623 input_signal_count
++;
9627 #if USE_CARBON_EVENTS
9628 toolbox_dispatcher
= GetEventDispatcherTarget ();
9630 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9631 kEventRemoveFromQueue
, &eventRef
))
9632 #else /* !USE_CARBON_EVENTS */
9633 while (mac_wait_next_event (&er
, 0, true))
9634 #endif /* !USE_CARBON_EVENTS */
9638 unsigned long timestamp
;
9640 /* It is necessary to set this (additional) argument slot of an
9641 event to nil because keyboard.c protects incompletely
9642 processed event from being garbage collected by placing them
9643 in the kbd_buffer_gcpro vector. */
9645 inev
.kind
= NO_EVENT
;
9648 #if USE_CARBON_EVENTS
9649 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9651 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9654 #if USE_CARBON_EVENTS
9655 /* Handle new events */
9656 if (!mac_convert_event_ref (eventRef
, &er
))
9658 /* There used to be a handler for the kEventMouseWheelMoved
9659 event here. But as of Mac OS X 10.4, this kind of event
9660 is not directly posted to the main event queue by
9661 two-finger scrolling on the trackpad. Instead, some
9662 private event is posted and it is converted to a wheel
9663 event by the default handler for the application target.
9664 The converted one can be received by a Carbon event
9665 handler installed on a window target. */
9666 read_socket_inev
= &inev
;
9667 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9668 read_socket_inev
= NULL
;
9671 #endif /* USE_CARBON_EVENTS */
9677 WindowPtr window_ptr
;
9678 ControlPartCode part_code
;
9681 #if USE_CARBON_EVENTS
9682 /* This is needed to send mouse events like aqua window
9683 buttons to the correct handler. */
9684 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9685 != eventNotHandledErr
)
9688 last_mouse_glyph_frame
= 0;
9690 if (dpyinfo
->grabbed
&& last_mouse_frame
9691 && FRAME_LIVE_P (last_mouse_frame
))
9693 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9694 part_code
= inContent
;
9698 part_code
= FindWindow (er
.where
, &window_ptr
);
9699 if (tip_window
&& window_ptr
== tip_window
)
9701 HideWindow (tip_window
);
9702 part_code
= FindWindow (er
.where
, &window_ptr
);
9706 if (er
.what
!= mouseDown
&&
9707 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9713 f
= mac_focus_frame (dpyinfo
);
9714 saved_menu_event_location
= er
.where
;
9715 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9716 XSETFRAME (inev
.frame_or_window
, f
);
9720 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9721 SelectWindow (window_ptr
);
9724 ControlPartCode control_part_code
;
9726 Point mouse_loc
= er
.where
;
9728 ControlKind control_kind
;
9731 f
= mac_window_to_frame (window_ptr
);
9732 /* convert to local coordinates of new window */
9733 SetPortWindowPort (window_ptr
);
9735 GlobalToLocal (&mouse_loc
);
9736 #if TARGET_API_MAC_CARBON
9737 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9738 &control_part_code
);
9741 GetControlKind (ch
, &control_kind
);
9744 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9748 #if USE_CARBON_EVENTS
9749 inev
.code
= mac_get_mouse_btn (eventRef
);
9750 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9752 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9753 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9755 XSETINT (inev
.x
, mouse_loc
.h
);
9756 XSETINT (inev
.y
, mouse_loc
.v
);
9758 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9760 #ifndef USE_TOOLKIT_SCROLL_BARS
9761 /* control_part_code becomes kControlNoPart if
9762 a progress indicator is clicked. */
9763 && control_part_code
!= kControlNoPart
9764 #else /* USE_TOOLKIT_SCROLL_BARS */
9766 && control_kind
.kind
== kControlKindScrollBar
9767 #endif /* MAC_OSX */
9768 #endif /* USE_TOOLKIT_SCROLL_BARS */
9771 struct scroll_bar
*bar
;
9773 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9775 bar
= tracked_scroll_bar
;
9776 #ifndef USE_TOOLKIT_SCROLL_BARS
9777 control_part_code
= kControlIndicatorPart
;
9781 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9782 #ifdef USE_TOOLKIT_SCROLL_BARS
9783 /* Make the "Ctrl-Mouse-2 splits window" work
9784 for toolkit scroll bars. */
9785 if (er
.modifiers
& controlKey
)
9786 x_scroll_bar_handle_click (bar
, control_part_code
,
9788 else if (er
.what
== mouseDown
)
9789 x_scroll_bar_handle_press (bar
, control_part_code
,
9792 x_scroll_bar_handle_release (bar
, &inev
);
9793 #else /* not USE_TOOLKIT_SCROLL_BARS */
9794 x_scroll_bar_handle_click (bar
, control_part_code
,
9796 if (er
.what
== mouseDown
9797 && control_part_code
== kControlIndicatorPart
)
9798 tracked_scroll_bar
= bar
;
9800 tracked_scroll_bar
= NULL
;
9801 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9806 int x
= mouse_loc
.h
;
9807 int y
= mouse_loc
.v
;
9809 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9810 if (EQ (window
, f
->tool_bar_window
))
9812 if (er
.what
== mouseDown
)
9813 handle_tool_bar_click (f
, x
, y
, 1, 0);
9815 handle_tool_bar_click (f
, x
, y
, 0,
9821 XSETFRAME (inev
.frame_or_window
, f
);
9822 inev
.kind
= MOUSE_CLICK_EVENT
;
9826 if (er
.what
== mouseDown
)
9828 dpyinfo
->grabbed
|= (1 << inev
.code
);
9829 last_mouse_frame
= f
;
9832 last_tool_bar_item
= -1;
9836 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9837 /* If a button is released though it was not
9838 previously pressed, that would be because
9839 of multi-button emulation. */
9840 dpyinfo
->grabbed
= 0;
9842 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9845 /* Ignore any mouse motion that happened before
9846 this event; any subsequent mouse-movement Emacs
9847 events should reflect only motion after the
9852 #ifdef USE_TOOLKIT_SCROLL_BARS
9853 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9858 inev
.modifiers
|= down_modifier
;
9861 inev
.modifiers
|= up_modifier
;
9868 #if TARGET_API_MAC_CARBON
9869 DragWindow (window_ptr
, er
.where
, NULL
);
9870 #else /* not TARGET_API_MAC_CARBON */
9871 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9872 #endif /* not TARGET_API_MAC_CARBON */
9873 /* Update the frame parameters. */
9875 struct frame
*f
= mac_window_to_frame (window_ptr
);
9877 if (f
&& !f
->async_iconified
)
9878 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9883 if (TrackGoAway (window_ptr
, er
.where
))
9885 inev
.kind
= DELETE_WINDOW_EVENT
;
9886 XSETFRAME (inev
.frame_or_window
,
9887 mac_window_to_frame (window_ptr
));
9891 /* window resize handling added --ben */
9893 do_grow_window (window_ptr
, &er
);
9896 /* window zoom handling added --ben */
9899 if (TrackBox (window_ptr
, er
.where
, part_code
))
9900 do_zoom_window (window_ptr
, part_code
);
9910 #if USE_CARBON_EVENTS
9911 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9912 != eventNotHandledErr
)
9915 do_window_update ((WindowPtr
) er
.message
);
9920 #if USE_CARBON_EVENTS
9921 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9922 != eventNotHandledErr
)
9925 switch ((er
.message
>> 24) & 0x000000FF)
9927 case suspendResumeMessage
:
9928 if ((er
.message
& resumeFlag
) == 1)
9934 case mouseMovedMessage
:
9935 #if !USE_CARBON_EVENTS
9936 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9937 er
.where
.h
+ 1, er
.where
.v
+ 1);
9939 previous_help_echo_string
= help_echo_string
;
9940 help_echo_string
= Qnil
;
9942 if (dpyinfo
->grabbed
&& last_mouse_frame
9943 && FRAME_LIVE_P (last_mouse_frame
))
9944 f
= last_mouse_frame
;
9946 f
= dpyinfo
->x_focus_frame
;
9948 if (dpyinfo
->mouse_face_hidden
)
9950 dpyinfo
->mouse_face_hidden
= 0;
9951 clear_mouse_face (dpyinfo
);
9956 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9957 Point mouse_pos
= er
.where
;
9959 SetPortWindowPort (wp
);
9961 GlobalToLocal (&mouse_pos
);
9963 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9964 #ifdef USE_TOOLKIT_SCROLL_BARS
9965 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9967 #else /* not USE_TOOLKIT_SCROLL_BARS */
9968 x_scroll_bar_note_movement (tracked_scroll_bar
,
9970 - XINT (tracked_scroll_bar
->top
),
9971 er
.when
* (1000 / 60));
9972 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9975 /* Generate SELECT_WINDOW_EVENTs when needed. */
9976 if (mouse_autoselect_window
)
9980 window
= window_from_coordinates (f
,
9985 /* Window will be selected only when it is
9986 not selected now and last mouse movement
9987 event was not in it. Minibuffer window
9988 will be selected iff it is active. */
9989 if (WINDOWP (window
)
9990 && !EQ (window
, last_window
)
9991 && !EQ (window
, selected_window
))
9993 inev
.kind
= SELECT_WINDOW_EVENT
;
9994 inev
.frame_or_window
= window
;
9999 if (!note_mouse_movement (f
, &mouse_pos
))
10000 help_echo_string
= previous_help_echo_string
;
10004 /* If the contents of the global variable
10005 help_echo_string has changed, generate a
10007 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10015 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10017 #if USE_CARBON_EVENTS
10018 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10019 != eventNotHandledErr
)
10022 if (window_ptr
== tip_window
)
10024 HideWindow (tip_window
);
10028 if (!is_emacs_window (window_ptr
))
10031 if ((er
.modifiers
& activeFlag
) != 0)
10033 /* A window has been activated */
10034 Point mouse_loc
= er
.where
;
10036 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10038 SetPortWindowPort (window_ptr
);
10039 GlobalToLocal (&mouse_loc
);
10040 /* Window-activated event counts as mouse movement,
10041 so update things that depend on mouse position. */
10042 note_mouse_movement (mac_window_to_frame (window_ptr
),
10047 /* A window has been deactivated */
10048 #if USE_TOOLKIT_SCROLL_BARS
10049 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10051 struct input_event event
;
10053 EVENT_INIT (event
);
10054 event
.kind
= NO_EVENT
;
10055 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10056 if (event
.kind
!= NO_EVENT
)
10058 event
.timestamp
= timestamp
;
10059 kbd_buffer_store_event_hold (&event
, hold_quit
);
10064 dpyinfo
->grabbed
= 0;
10066 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10068 f
= mac_window_to_frame (window_ptr
);
10069 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10071 /* If we move outside the frame, then we're
10072 certainly no longer on any text in the
10074 clear_mouse_face (dpyinfo
);
10075 dpyinfo
->mouse_face_mouse_frame
= 0;
10078 /* Generate a nil HELP_EVENT to cancel a help-echo.
10079 Do it only if there's something to cancel.
10080 Otherwise, the startup message is cleared when the
10081 mouse leaves the frame. */
10082 if (any_help_event_p
)
10091 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10094 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10095 /* When using Carbon Events, we need to pass raw keyboard
10096 events to the TSM ourselves. If TSM handles it, it
10097 will pass back noErr, otherwise it will pass back
10098 "eventNotHandledErr" and we can process it
10100 if ((mac_pass_command_to_system
10101 || !(er
.modifiers
& cmdKey
))
10102 && (mac_pass_control_to_system
10103 || !(er
.modifiers
& controlKey
))
10104 && (NILP (Vmac_option_modifier
)
10105 || !(er
.modifiers
& optionKey
)))
10106 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10107 != eventNotHandledErr
)
10112 if (dpyinfo
->x_focus_frame
== NULL
)
10114 /* Beep if keyboard input occurs when all the frames
10122 static SInt16 last_key_script
= -1;
10123 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10125 if (last_key_script
!= current_key_script
)
10127 struct input_event event
;
10129 EVENT_INIT (event
);
10130 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10132 event
.code
= current_key_script
;
10133 event
.timestamp
= timestamp
;
10134 kbd_buffer_store_event (&event
);
10137 last_key_script
= current_key_script
;
10142 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10144 clear_mouse_face (dpyinfo
);
10145 dpyinfo
->mouse_face_hidden
= 1;
10148 /* translate the keycode back to determine the original key */
10149 /* Convert key code if function key is pressed.
10150 Otherwise, if non-ASCII-event, take care of that
10151 without re-translating the key code. */
10152 #if USE_CARBON_EVENTS
10153 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10155 inev
.code
= xkeysym
;
10156 /* this doesn't work - tried to add shift modifiers */
10158 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10159 xkeysym
| 0x80, xkeysym
);
10160 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10164 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10166 inev
.code
= 0xff00 | xkeysym
;
10167 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10172 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10173 er
.message
& charCodeMask
);
10174 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10178 #if USE_CARBON_EVENTS
10179 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10181 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10183 inev
.modifiers
|= (extra_keyboard_modifiers
10184 & (meta_modifier
| alt_modifier
10185 | hyper_modifier
| super_modifier
));
10186 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10189 case kHighLevelEvent
:
10190 read_socket_inev
= &inev
;
10191 AEProcessAppleEvent (&er
);
10192 read_socket_inev
= NULL
;
10198 #if USE_CARBON_EVENTS
10199 ReleaseEvent (eventRef
);
10202 if (inev
.kind
!= NO_EVENT
)
10204 inev
.timestamp
= timestamp
;
10205 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10210 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10215 XSETFRAME (frame
, f
);
10221 any_help_event_p
= 1;
10222 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10223 help_echo_object
, help_echo_pos
);
10227 help_echo_string
= Qnil
;
10228 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10235 /* If the focus was just given to an autoraising frame,
10237 /* ??? This ought to be able to handle more than one such frame. */
10238 if (pending_autoraise_frame
)
10240 x_raise_frame (pending_autoraise_frame
);
10241 pending_autoraise_frame
= 0;
10244 #if !USE_CARBON_EVENTS
10245 /* Check which frames are still visible. We do this here because
10246 there doesn't seem to be any direct notification from the Window
10247 Manager that the visibility of a window has changed (at least,
10248 not in all cases). */
10250 Lisp_Object tail
, frame
;
10252 FOR_EACH_FRAME (tail
, frame
)
10254 struct frame
*f
= XFRAME (frame
);
10256 /* The tooltip has been drawn already. Avoid the
10257 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10258 if (EQ (frame
, tip_frame
))
10261 if (FRAME_MAC_P (f
))
10262 mac_handle_visibility_change (f
);
10273 /* Need to override CodeWarrior's input function so no conversion is
10274 done on newlines Otherwise compiled functions in .elc files will be
10275 read incorrectly. Defined in ...:MSL C:MSL
10276 Common:Source:buffer_io.c. */
10279 __convert_to_newlines (unsigned char * p
, size_t * n
)
10281 #pragma unused(p,n)
10285 __convert_from_newlines (unsigned char * p
, size_t * n
)
10287 #pragma unused(p,n)
10293 make_mac_terminal_frame (struct frame
*f
)
10298 XSETFRAME (frame
, f
);
10300 f
->output_method
= output_mac
;
10301 f
->output_data
.mac
= (struct mac_output
*)
10302 xmalloc (sizeof (struct mac_output
));
10303 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10305 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10307 FRAME_COLS (f
) = 96;
10308 FRAME_LINES (f
) = 4;
10310 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10311 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10313 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10315 f
->output_data
.mac
->cursor_pixel
= 0;
10316 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10317 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10318 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10320 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10321 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10322 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10323 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10324 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10325 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10327 FRAME_FONTSET (f
) = -1;
10328 f
->output_data
.mac
->explicit_parent
= 0;
10331 f
->border_width
= 0;
10333 f
->internal_border_width
= 0;
10338 f
->new_text_cols
= 0;
10339 f
->new_text_lines
= 0;
10341 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10342 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10343 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10347 if (!(FRAME_MAC_WINDOW (f
) =
10348 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10349 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10351 /* so that update events can find this mac_output struct */
10352 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10358 /* Need to be initialized for unshow_buffer in window.c. */
10359 selected_window
= f
->selected_window
;
10361 Fmodify_frame_parameters (frame
,
10362 Fcons (Fcons (Qfont
,
10363 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10364 Fmodify_frame_parameters (frame
,
10365 Fcons (Fcons (Qforeground_color
,
10366 build_string ("black")), Qnil
));
10367 Fmodify_frame_parameters (frame
,
10368 Fcons (Fcons (Qbackground_color
,
10369 build_string ("white")), Qnil
));
10374 /***********************************************************************
10376 ***********************************************************************/
10378 int mac_initialized
= 0;
10381 mac_initialize_display_info ()
10383 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10384 GDHandle main_device_handle
;
10386 bzero (dpyinfo
, sizeof (*dpyinfo
));
10389 dpyinfo
->mac_id_name
10390 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10391 + SCHARS (Vsystem_name
)
10393 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10394 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10396 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10397 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10400 main_device_handle
= LMGetMainDevice();
10402 dpyinfo
->reference_count
= 0;
10403 dpyinfo
->resx
= 72.0;
10404 dpyinfo
->resy
= 72.0;
10405 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10407 /* HasDepth returns true if it is possible to have a 32 bit display,
10408 but this may not be what is actually used. Mac OSX can do better.
10409 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10410 header for CGGetActiveDisplayList says that the first display returned
10411 is the active one, so we use that. */
10413 CGDirectDisplayID disp_id
[1];
10414 CGDisplayCount disp_count
;
10415 CGDisplayErr error_code
;
10417 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10418 if (error_code
!= 0)
10419 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10421 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10424 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10425 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10426 gdDevType
, dpyinfo
->color_p
))
10429 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10430 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10431 dpyinfo
->grabbed
= 0;
10432 dpyinfo
->root_window
= NULL
;
10433 dpyinfo
->image_cache
= make_image_cache ();
10435 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10436 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10437 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10438 dpyinfo
->mouse_face_window
= Qnil
;
10439 dpyinfo
->mouse_face_overlay
= Qnil
;
10440 dpyinfo
->mouse_face_hidden
= 0;
10445 mac_make_rdb (xrm_option
)
10448 XrmDatabase database
;
10450 database
= xrm_get_preference_database (NULL
);
10452 xrm_merge_string_database (database
, xrm_option
);
10457 struct mac_display_info
*
10458 mac_term_init (display_name
, xrm_option
, resource_name
)
10459 Lisp_Object display_name
;
10461 char *resource_name
;
10463 struct mac_display_info
*dpyinfo
;
10467 if (!mac_initialized
)
10470 mac_initialized
= 1;
10473 if (x_display_list
)
10474 error ("Sorry, this version can only handle one display");
10476 mac_initialize_display_info ();
10478 dpyinfo
= &one_mac_display_info
;
10480 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10482 /* Put this display on the chain. */
10483 dpyinfo
->next
= x_display_list
;
10484 x_display_list
= dpyinfo
;
10486 /* Put it on x_display_name_list. */
10487 x_display_name_list
= Fcons (Fcons (display_name
,
10488 Fcons (Qnil
, dpyinfo
->xrdb
)),
10489 x_display_name_list
);
10490 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10496 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10499 x_delete_display (dpyinfo
)
10500 struct mac_display_info
*dpyinfo
;
10504 /* Discard this display from x_display_name_list and x_display_list.
10505 We can't use Fdelq because that can quit. */
10506 if (! NILP (x_display_name_list
)
10507 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10508 x_display_name_list
= XCDR (x_display_name_list
);
10513 tail
= x_display_name_list
;
10514 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10516 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10518 XSETCDR (tail
, XCDR (XCDR (tail
)));
10521 tail
= XCDR (tail
);
10525 if (x_display_list
== dpyinfo
)
10526 x_display_list
= dpyinfo
->next
;
10529 struct x_display_info
*tail
;
10531 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10532 if (tail
->next
== dpyinfo
)
10533 tail
->next
= tail
->next
->next
;
10536 /* Free the font names in the font table. */
10537 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10538 if (dpyinfo
->font_table
[i
].name
)
10540 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10541 xfree (dpyinfo
->font_table
[i
].full_name
);
10542 xfree (dpyinfo
->font_table
[i
].name
);
10545 if (dpyinfo
->font_table
->font_encoder
)
10546 xfree (dpyinfo
->font_table
->font_encoder
);
10548 xfree (dpyinfo
->font_table
);
10549 xfree (dpyinfo
->mac_id_name
);
10551 if (x_display_list
== 0)
10553 mac_clear_font_name_table ();
10554 bzero (dpyinfo
, sizeof (*dpyinfo
));
10563 extern int inhibit_window_system
;
10564 extern int noninteractive
;
10565 CFBundleRef appsBundle
;
10568 /* No need to test if already -nw*/
10569 if (inhibit_window_system
|| noninteractive
)
10572 appsBundle
= CFBundleGetMainBundle();
10573 if (appsBundle
!= NULL
)
10575 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10576 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10577 /* We found the bundle identifier, now we know we are valid. */
10584 /* MAC_TODO: Have this start the bundled executable */
10586 /* For now, prevent the fatal error by bringing it up in the terminal */
10587 inhibit_window_system
= 1;
10591 MakeMeTheFrontProcess ()
10593 ProcessSerialNumber psn
;
10596 err
= GetCurrentProcess (&psn
);
10598 (void) SetFrontProcess (&psn
);
10601 /***** Code to handle C-g testing *****/
10603 /* Contains the Mac modifier formed from quit_char */
10604 int mac_quit_char_modifiers
= 0;
10605 int mac_quit_char_keycode
;
10606 extern int quit_char
;
10609 mac_determine_quit_char_modifiers()
10611 /* Todo: Determine modifiers from quit_char. */
10612 UInt32 qc_modifiers
= ctrl_modifier
;
10614 /* Map modifiers */
10615 mac_quit_char_modifiers
= 0;
10616 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10617 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10618 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10622 init_quit_char_handler ()
10624 /* TODO: Let this support keys other the 'g' */
10625 mac_quit_char_keycode
= 5;
10626 /* Look at <architecture/adb_kb_map.h> for details */
10627 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10629 mac_determine_quit_char_modifiers();
10631 #endif /* MAC_OSX */
10639 MenuItemIndex menu_index
;
10641 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10642 &menu
, &menu_index
);
10644 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10645 #if USE_CARBON_EVENTS
10646 EnableMenuCommand (NULL
, kHICommandPreferences
);
10647 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10648 &menu
, &menu_index
);
10651 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10652 InsertMenuItemTextWithCFString (menu
, NULL
,
10653 0, kMenuItemAttrSeparator
, 0);
10654 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10655 0, 0, kHICommandAbout
);
10657 #endif /* USE_CARBON_EVENTS */
10658 #else /* !MAC_OSX */
10659 #if USE_CARBON_EVENTS
10660 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10666 /* Set up use of X before we make the first connection. */
10668 extern frame_parm_handler mac_frame_parm_handlers
[];
10670 static struct redisplay_interface x_redisplay_interface
=
10672 mac_frame_parm_handlers
,
10676 x_clear_end_of_line
,
10678 x_after_update_window_line
,
10679 x_update_window_begin
,
10680 x_update_window_end
,
10683 0, /* flush_display_optional */
10684 x_clear_window_mouse_face
,
10685 x_get_glyph_overhangs
,
10686 x_fix_overlapping_area
,
10687 x_draw_fringe_bitmap
,
10688 0, /* define_fringe_bitmap */
10689 0, /* destroy_fringe_bitmap */
10690 mac_per_char_metric
,
10692 mac_compute_glyph_string_overhangs
,
10693 x_draw_glyph_string
,
10694 mac_define_frame_cursor
,
10695 mac_clear_frame_area
,
10696 mac_draw_window_cursor
,
10697 mac_draw_vertical_window_border
,
10698 mac_shift_glyphs_for_insert
10704 rif
= &x_redisplay_interface
;
10706 clear_frame_hook
= x_clear_frame
;
10707 ins_del_lines_hook
= x_ins_del_lines
;
10708 delete_glyphs_hook
= x_delete_glyphs
;
10709 ring_bell_hook
= XTring_bell
;
10710 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10711 set_terminal_modes_hook
= XTset_terminal_modes
;
10712 update_begin_hook
= x_update_begin
;
10713 update_end_hook
= x_update_end
;
10714 set_terminal_window_hook
= XTset_terminal_window
;
10715 read_socket_hook
= XTread_socket
;
10716 frame_up_to_date_hook
= XTframe_up_to_date
;
10717 mouse_position_hook
= XTmouse_position
;
10718 frame_rehighlight_hook
= XTframe_rehighlight
;
10719 frame_raise_lower_hook
= XTframe_raise_lower
;
10721 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10722 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10723 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10724 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10726 scroll_region_ok
= 1; /* we'll scroll partial frames */
10727 char_ins_del_ok
= 1;
10728 line_ins_del_ok
= 1; /* we'll just blt 'em */
10729 fast_clear_end_of_line
= 1; /* X does this well */
10730 memory_below_frame
= 0; /* we don't remember what scrolls
10734 last_tool_bar_item
= -1;
10735 any_help_event_p
= 0;
10737 /* Try to use interrupt input; if we can't, then start polling. */
10738 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10742 #if TARGET_API_MAC_CARBON
10744 #if USE_CARBON_EVENTS
10746 init_service_handler ();
10748 init_quit_char_handler ();
10749 #endif /* MAC_OSX */
10751 init_command_handler ();
10754 #endif /* USE_CARBON_EVENTS */
10757 init_coercion_handler ();
10759 init_apple_event_handler ();
10761 if (!inhibit_window_system
)
10762 MakeMeTheFrontProcess ();
10773 staticpro (&x_error_message_string
);
10774 x_error_message_string
= Qnil
;
10777 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10778 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10779 Qalt
= intern ("alt"); staticpro (&Qalt
);
10780 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10781 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10782 Qmodifier_value
= intern ("modifier-value");
10783 staticpro (&Qmodifier_value
);
10785 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10786 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10787 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10788 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10789 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10791 #if USE_CARBON_EVENTS
10792 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
10794 Qservices
= intern ("services"); staticpro (&Qservices
);
10795 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10796 Qperform
= intern ("perform"); staticpro (&Qperform
);
10801 Fprovide (intern ("mac-carbon"), Qnil
);
10804 staticpro (&Qreverse
);
10805 Qreverse
= intern ("reverse");
10807 staticpro (&x_display_name_list
);
10808 x_display_name_list
= Qnil
;
10810 staticpro (&last_mouse_scroll_bar
);
10811 last_mouse_scroll_bar
= Qnil
;
10813 staticpro (&fm_font_family_alist
);
10814 fm_font_family_alist
= Qnil
;
10817 staticpro (&atsu_font_id_hash
);
10818 atsu_font_id_hash
= Qnil
;
10821 /* We don't yet support this, but defining this here avoids whining
10822 from cus-start.el and other places, like "M-x set-variable". */
10823 DEFVAR_BOOL ("x-use-underline-position-properties",
10824 &x_use_underline_position_properties
,
10825 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10826 nil means ignore them. If you encounter fonts with bogus
10827 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10828 to 4.1, set this to nil.
10830 NOTE: Not supported on Mac yet. */);
10831 x_use_underline_position_properties
= 0;
10833 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10834 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10835 #ifdef USE_TOOLKIT_SCROLL_BARS
10836 Vx_toolkit_scroll_bars
= Qt
;
10838 Vx_toolkit_scroll_bars
= Qnil
;
10841 staticpro (&last_mouse_motion_frame
);
10842 last_mouse_motion_frame
= Qnil
;
10844 /* Variables to configure modifier key assignment. */
10846 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
10847 doc
: /* *Modifier key assumed when the Mac control key is pressed.
10848 The value can be `control', `meta', `alt', `hyper', or `super' for the
10849 respective modifier. The default is `control'. */);
10850 Vmac_control_modifier
= Qcontrol
;
10852 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10853 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
10854 The value can be `control', `meta', `alt', `hyper', or `super' for the
10855 respective modifier. If the value is nil then the key will act as the
10856 normal Mac control modifier, and the option key can be used to compose
10857 characters depending on the chosen Mac keyboard setting. */);
10858 Vmac_option_modifier
= Qnil
;
10860 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
10861 doc
: /* *Modifier key assumed when the Mac command key is pressed.
10862 The value can be `control', `meta', `alt', `hyper', or `super' for the
10863 respective modifier. The default is `meta'. */);
10864 Vmac_command_modifier
= Qmeta
;
10866 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
10867 doc
: /* *Modifier key assumed when the Mac function key is pressed.
10868 The value can be `control', `meta', `alt', `hyper', or `super' for the
10869 respective modifier. Note that remapping the function key may lead to
10870 unexpected results for some keys on non-US/GB keyboards. */);
10871 Vmac_function_modifier
= Qnil
;
10873 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10874 &Vmac_emulate_three_button_mouse
,
10875 doc
: /* *Specify a way of three button mouse emulation.
10876 The value can be nil, t, or the symbol `reverse'.
10877 nil means that no emulation should be done and the modifiers should be
10878 placed on the mouse-1 event.
10879 t means that when the option-key is held down while pressing the mouse
10880 button, the click will register as mouse-2 and while the command-key
10881 is held down, the click will register as mouse-3.
10882 The symbol `reverse' means that the option-key will register for
10883 mouse-3 and the command-key will register for mouse-2. */);
10884 Vmac_emulate_three_button_mouse
= Qnil
;
10886 #if USE_CARBON_EVENTS
10887 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
10888 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
10889 Otherwise, the right click will be treated as mouse-2 and the wheel
10890 button will be mouse-3. */);
10891 mac_wheel_button_is_mouse_2
= 1;
10893 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
10894 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
10895 mac_pass_command_to_system
= 1;
10897 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
10898 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
10899 mac_pass_control_to_system
= 1;
10903 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
10904 doc
: /* *If non-nil, allow anti-aliasing.
10905 The text will be rendered using Core Graphics text rendering which
10906 may anti-alias the text. */);
10907 mac_use_core_graphics
= 0;
10909 /* Register an entry for `mac-roman' so that it can be used when
10910 creating the terminal frame on Mac OS 9 before loading
10911 term/mac-win.elc. */
10912 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10913 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
10914 Each entry should be of the form:
10916 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10918 where CHARSET-NAME is a string used in font names to identify the
10919 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
10920 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
10921 Vmac_charset_info_alist
=
10922 Fcons (list3 (build_string ("mac-roman"),
10923 make_number (smRoman
), Qnil
), Qnil
);
10926 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10927 (do not change this comment) */