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 GC_CLIP_REGION(gc) ((gc)->clip_region)
271 #define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc)
273 static RgnHandle saved_port_clip_region
= NULL
;
276 mac_begin_clip (region
)
279 static RgnHandle new_region
= NULL
;
281 if (saved_port_clip_region
== NULL
)
282 saved_port_clip_region
= NewRgn ();
283 if (new_region
== NULL
)
284 new_region
= NewRgn ();
286 if (region
&& !EmptyRgn (region
))
288 GetClip (saved_port_clip_region
);
289 SectRgn (saved_port_clip_region
, region
, new_region
);
290 SetClip (new_region
);
295 mac_end_clip (region
)
298 if (region
&& !EmptyRgn (region
))
299 SetClip (saved_port_clip_region
);
303 /* X display function emulation */
306 XFreePixmap (display
, pixmap
)
307 Display
*display
; /* not used */
310 DisposeGWorld (pixmap
);
314 /* Mac version of XDrawLine. */
317 mac_draw_line (f
, gc
, x1
, y1
, x2
, y2
)
322 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
324 RGBForeColor (GC_FORE_COLOR (gc
));
326 mac_begin_clip (GC_CLIP_REGION (gc
));
329 mac_end_clip (GC_CLIP_REGION (gc
));
333 mac_draw_line_to_pixmap (display
, p
, gc
, x1
, y1
, x2
, y2
)
342 GetGWorld (&old_port
, &old_gdh
);
345 RGBForeColor (GC_FORE_COLOR (gc
));
347 LockPixels (GetGWorldPixMap (p
));
350 UnlockPixels (GetGWorldPixMap (p
));
352 SetGWorld (old_port
, old_gdh
);
357 mac_erase_rectangle (f
, gc
, x
, y
, width
, height
)
361 unsigned int width
, height
;
365 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
367 RGBBackColor (GC_BACK_COLOR (gc
));
368 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
370 mac_begin_clip (GC_CLIP_REGION (gc
));
372 mac_end_clip (GC_CLIP_REGION (gc
));
374 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
378 /* Mac version of XClearArea. */
381 mac_clear_area (f
, x
, y
, width
, height
)
384 unsigned int width
, height
;
386 mac_erase_rectangle (f
, FRAME_NORMAL_GC (f
), x
, y
, width
, height
);
389 /* Mac version of XClearWindow. */
395 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
397 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
399 #if TARGET_API_MAC_CARBON
403 GetWindowPortBounds (FRAME_MAC_WINDOW (f
), &r
);
406 #else /* not TARGET_API_MAC_CARBON */
407 EraseRect (&(FRAME_MAC_WINDOW (f
)->portRect
));
408 #endif /* not TARGET_API_MAC_CARBON */
412 /* Mac replacement for XCopyArea. */
415 mac_draw_bitmap (f
, gc
, x
, y
, width
, height
, bits
, overlay_p
)
418 int x
, y
, width
, height
;
419 unsigned short *bits
;
425 bitmap
.rowBytes
= sizeof(unsigned short);
426 bitmap
.baseAddr
= (char *)bits
;
427 SetRect (&(bitmap
.bounds
), 0, 0, width
, height
);
429 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
431 RGBForeColor (GC_FORE_COLOR (gc
));
432 RGBBackColor (GC_BACK_COLOR (gc
));
433 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
435 mac_begin_clip (GC_CLIP_REGION (gc
));
436 #if TARGET_API_MAC_CARBON
442 CopyBits (&bitmap
, GetPortBitMapForCopyBits (port
),
443 &(bitmap
.bounds
), &r
, overlay_p
? srcOr
: srcCopy
, 0);
444 UnlockPortBits (port
);
446 #else /* not TARGET_API_MAC_CARBON */
447 CopyBits (&bitmap
, &(FRAME_MAC_WINDOW (f
)->portBits
), &(bitmap
.bounds
), &r
,
448 overlay_p
? srcOr
: srcCopy
, 0);
449 #endif /* not TARGET_API_MAC_CARBON */
450 mac_end_clip (GC_CLIP_REGION (gc
));
452 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
456 /* Mac replacement for XCreateBitmapFromBitmapData. */
459 mac_create_bitmap_from_bitmap_data (bitmap
, bits
, w
, h
)
464 static unsigned char swap_nibble
[16]
465 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
466 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
467 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
468 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
472 w1
= (w
+ 7) / 8; /* nb of 8bits elt in X bitmap */
473 bitmap
->rowBytes
= ((w
+ 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
474 bitmap
->baseAddr
= xmalloc (bitmap
->rowBytes
* h
);
475 bzero (bitmap
->baseAddr
, bitmap
->rowBytes
* h
);
476 for (i
= 0; i
< h
; i
++)
478 p
= bitmap
->baseAddr
+ i
* bitmap
->rowBytes
;
479 for (j
= 0; j
< w1
; j
++)
481 /* Bitswap XBM bytes to match how Mac does things. */
482 unsigned char c
= *bits
++;
483 *p
++ = (unsigned char)((swap_nibble
[c
& 0xf] << 4)
484 | (swap_nibble
[(c
>>4) & 0xf]));;
488 SetRect (&(bitmap
->bounds
), 0, 0, w
, h
);
493 mac_free_bitmap (bitmap
)
496 xfree (bitmap
->baseAddr
);
501 XCreatePixmap (display
, w
, width
, height
, depth
)
502 Display
*display
; /* not used */
504 unsigned int width
, height
;
511 SetPortWindowPort (w
);
513 SetRect (&r
, 0, 0, width
, height
);
514 err
= NewGWorld (&pixmap
, depth
, &r
, NULL
, NULL
, 0);
522 XCreatePixmapFromBitmapData (display
, w
, data
, width
, height
, fg
, bg
, depth
)
523 Display
*display
; /* not used */
526 unsigned int width
, height
;
527 unsigned long fg
, bg
;
534 static GC gc
= NULL
; /* not reentrant */
537 gc
= XCreateGC (display
, w
, 0, NULL
);
539 pixmap
= XCreatePixmap (display
, w
, width
, height
, depth
);
543 GetGWorld (&old_port
, &old_gdh
);
544 SetGWorld (pixmap
, NULL
);
545 mac_create_bitmap_from_bitmap_data (&bitmap
, data
, width
, height
);
546 XSetForeground (display
, gc
, fg
);
547 XSetBackground (display
, gc
, bg
);
548 RGBForeColor (GC_FORE_COLOR (gc
));
549 RGBBackColor (GC_BACK_COLOR (gc
));
550 LockPixels (GetGWorldPixMap (pixmap
));
551 #if TARGET_API_MAC_CARBON
552 CopyBits (&bitmap
, GetPortBitMapForCopyBits (pixmap
),
553 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
554 #else /* not TARGET_API_MAC_CARBON */
555 CopyBits (&bitmap
, &(((GrafPtr
)pixmap
)->portBits
),
556 &bitmap
.bounds
, &bitmap
.bounds
, srcCopy
, 0);
557 #endif /* not TARGET_API_MAC_CARBON */
558 UnlockPixels (GetGWorldPixMap (pixmap
));
559 SetGWorld (old_port
, old_gdh
);
560 mac_free_bitmap (&bitmap
);
566 /* Mac replacement for XFillRectangle. */
569 mac_fill_rectangle (f
, gc
, x
, y
, width
, height
)
573 unsigned int width
, height
;
577 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
579 RGBForeColor (GC_FORE_COLOR (gc
));
580 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
582 mac_begin_clip (GC_CLIP_REGION (gc
));
583 PaintRect (&r
); /* using foreground color of gc */
584 mac_end_clip (GC_CLIP_REGION (gc
));
588 /* Mac replacement for XDrawRectangle: dest is a window. */
591 mac_draw_rectangle (f
, gc
, x
, y
, width
, height
)
595 unsigned int width
, height
;
599 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
601 RGBForeColor (GC_FORE_COLOR (gc
));
602 SetRect (&r
, x
, y
, x
+ width
+ 1, y
+ height
+ 1);
604 mac_begin_clip (GC_CLIP_REGION (gc
));
605 FrameRect (&r
); /* using foreground color of gc */
606 mac_end_clip (GC_CLIP_REGION (gc
));
612 atsu_get_text_layout_with_text_ptr (text
, text_length
, style
, text_layout
)
613 ConstUniCharArrayPtr text
;
614 UniCharCount text_length
;
616 ATSUTextLayout
*text_layout
;
619 static ATSUTextLayout saved_text_layout
= NULL
; /* not reentrant */
621 if (saved_text_layout
== NULL
)
623 UniCharCount lengths
[] = {kATSUToTextEnd
};
624 ATSUAttributeTag tags
[] = {kATSULineLayoutOptionsTag
};
625 ByteCount sizes
[] = {sizeof (ATSLineLayoutOptions
)};
626 static ATSLineLayoutOptions line_layout
=
627 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
628 kATSLineDisableAllLayoutOperations
| kATSLineUseDeviceMetrics
629 | kATSLineUseQDRendering
631 kATSLineIsDisplayOnly
| kATSLineFractDisable
634 ATSUAttributeValuePtr values
[] = {&line_layout
};
636 err
= ATSUCreateTextLayoutWithTextPtr (text
,
637 kATSUFromTextBeginning
,
643 err
= ATSUSetLayoutControls (saved_text_layout
,
644 sizeof (tags
) / sizeof (tags
[0]),
645 tags
, sizes
, values
);
646 /* XXX: Should we do this? */
648 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
652 err
= ATSUSetRunStyle (saved_text_layout
, style
,
653 kATSUFromTextBeginning
, kATSUToTextEnd
);
655 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
656 kATSUFromTextBeginning
,
662 *text_layout
= saved_text_layout
;
669 mac_invert_rectangle (f
, x
, y
, width
, height
)
672 unsigned int width
, height
;
676 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
678 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
685 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, bytes_per_char
)
690 int nchars
, bg_width
, bytes_per_char
;
692 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
695 if (GC_FONT (gc
)->mac_style
)
698 ATSUTextLayout text_layout
;
700 xassert (bytes_per_char
== 2);
702 #ifndef WORDS_BIG_ENDIAN
705 UniChar
*text
= (UniChar
*)buf
;
707 for (i
= 0; i
< nchars
; i
++)
708 text
[i
] = EndianU16_BtoN (text
[i
]);
711 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
713 GC_FONT (gc
)->mac_style
,
718 if (!mac_use_core_graphics
)
721 mac_begin_clip (GC_CLIP_REGION (gc
));
722 RGBForeColor (GC_FORE_COLOR (gc
));
727 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
728 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
729 RGBBackColor (GC_BACK_COLOR (gc
));
731 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
734 ATSUDrawText (text_layout
,
735 kATSUFromTextBeginning
, kATSUToTextEnd
,
736 kATSUUseGrafPortPenLoc
, kATSUUseGrafPortPenLoc
);
737 mac_end_clip (GC_CLIP_REGION (gc
));
743 CGContextRef context
;
744 float port_height
= FRAME_PIXEL_HEIGHT (f
);
745 ATSUAttributeTag tags
[] = {kATSUCGContextTag
};
746 ByteCount sizes
[] = {sizeof (CGContextRef
)};
747 ATSUAttributeValuePtr values
[] = {&context
};
750 QDBeginCGContext (port
, &context
);
751 if (gc
->n_clip_rects
|| bg_width
)
753 CGContextTranslateCTM (context
, 0, port_height
);
754 CGContextScaleCTM (context
, 1, -1);
755 if (gc
->n_clip_rects
)
756 CGContextClipToRects (context
, gc
->clip_rects
,
760 CGContextSetRGBFillColor
762 RED_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
763 GREEN_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
764 BLUE_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
768 CGRectMake (x
, y
- FONT_BASE (GC_FONT (gc
)),
769 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
771 CGContextScaleCTM (context
, 1, -1);
772 CGContextTranslateCTM (context
, 0, -port_height
);
774 CGContextSetRGBFillColor
776 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
777 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
778 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
780 err
= ATSUSetLayoutControls (text_layout
,
781 sizeof (tags
) / sizeof (tags
[0]),
782 tags
, sizes
, values
);
784 ATSUDrawText (text_layout
,
785 kATSUFromTextBeginning
, kATSUToTextEnd
,
786 Long2Fix (x
), Long2Fix (port_height
- y
));
787 CGContextSynchronize (context
);
788 QDEndCGContext (port
, &context
);
790 /* This doesn't work on Mac OS X 10.1. */
791 ATSUClearLayoutControls (text_layout
,
792 sizeof (tags
) / sizeof (tags
[0]), tags
);
794 ATSUSetLayoutControls (text_layout
,
795 sizeof (tags
) / sizeof (tags
[0]),
796 tags
, sizes
, values
);
802 #endif /* USE_ATSUI */
804 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
807 if (mac_use_core_graphics
)
808 savedFlags
= SwapQDTextFlags (kQDUseCGTextRendering
);
810 mac_begin_clip (GC_CLIP_REGION (gc
));
811 RGBForeColor (GC_FORE_COLOR (gc
));
815 RGBBackColor (GC_BACK_COLOR (gc
));
821 /* We prefer not to use srcCopy text transfer mode on Mac OS X
823 - Screen is double-buffered. (In srcCopy mode, a text is
824 drawn into an offscreen graphics world first. So
825 performance gain cannot be expected.)
826 - It lowers rendering quality.
827 - Some fonts leave garbage on cursor movement. */
832 RGBBackColor (GC_BACK_COLOR (gc
));
833 SetRect (&r
, x
, y
- FONT_BASE (GC_FONT (gc
)),
834 x
+ bg_width
, y
+ FONT_DESCENT (GC_FONT (gc
)));
839 TextFont (GC_FONT (gc
)->mac_fontnum
);
840 TextSize (GC_FONT (gc
)->mac_fontsize
);
841 TextFace (GC_FONT (gc
)->mac_fontface
);
843 DrawText (buf
, 0, nchars
* bytes_per_char
);
845 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
846 mac_end_clip (GC_CLIP_REGION (gc
));
848 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
849 if (mac_use_core_graphics
)
850 SwapQDTextFlags(savedFlags
);
856 /* Mac replacement for XDrawString. */
859 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
866 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, 0, 1);
870 /* Mac replacement for XDrawString16. */
873 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
880 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, 0, 2);
884 /* Mac replacement for XDrawImageString. */
887 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
892 int nchars
, bg_width
;
894 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, bg_width
, 1);
898 /* Mac replacement for XDrawString16. */
901 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
906 int nchars
, bg_width
;
908 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, bg_width
, 2);
912 /* Mac replacement for XQueryTextExtents, but takes a character. If
913 STYLE is NULL, measurement is done by QuickDraw Text routines for
914 the font of the current graphics port. If CG_GLYPH is not NULL,
915 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
918 mac_query_char_extents (style
, c
,
919 font_ascent_return
, font_descent_return
,
920 overall_return
, cg_glyph
)
927 int *font_ascent_return
, *font_descent_return
;
928 XCharStruct
*overall_return
;
929 #if USE_CG_TEXT_DRAWING
942 ATSUTextLayout text_layout
;
945 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
948 ATSTrapezoid glyph_bounds
;
950 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
951 kATSUFromTextBeginning
, kATSUToTextEnd
,
952 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
953 kATSUseFractionalOrigins
,
955 kATSUseDeviceOrigins
,
957 1, &glyph_bounds
, NULL
);
960 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
961 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
963 width
= Fix2Long (glyph_bounds
.upperRight
.x
964 - glyph_bounds
.upperLeft
.x
);
965 if (font_ascent_return
)
966 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
967 if (font_descent_return
)
968 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
971 if (err
== noErr
&& overall_return
)
973 err
= ATSUMeasureTextImage (text_layout
,
974 kATSUFromTextBeginning
, kATSUToTextEnd
,
977 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
978 #if USE_CG_TEXT_DRAWING
979 if (err
== noErr
&& cg_glyph
)
982 ATSUGlyphInfoArray glyph_info_array
;
983 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
985 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
986 kATSUToTextEnd
, NULL
, NULL
, NULL
);
988 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
989 kATSUToTextEnd
, &count
,
993 xassert (glyph_info_array
.glyphs
[0].glyphID
);
994 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
1005 if (font_ascent_return
|| font_descent_return
)
1009 GetFontInfo (&font_info
);
1010 if (font_ascent_return
)
1011 *font_ascent_return
= font_info
.ascent
;
1012 if (font_descent_return
)
1013 *font_descent_return
= font_info
.descent
;
1019 width
= CharWidth (ch
);
1020 QDTextBounds (1, &ch
, &char_bounds
);
1021 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
1029 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
1032 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
1033 XFontStruct
*font_struct
;
1036 XCharStruct
*overall_return
;
1039 short width
= 0, lbearing
= 0, rbearing
= 0;
1042 for (i
= 0; i
< nchars
; i
++)
1044 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1046 width
+= FONT_WIDTH (font_struct
);
1049 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1050 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1051 width
+= pcm
->width
;
1056 overall_return
->lbearing
= lbearing
;
1057 overall_return
->rbearing
= rbearing
;
1058 overall_return
->width
= width
;
1060 /* What's the meaning of the return value of XTextExtents16? */
1064 #if USE_CG_TEXT_DRAWING
1065 static int cg_text_anti_aliasing_threshold
= 8;
1068 init_cg_text_anti_aliasing_threshold ()
1074 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"),
1075 kCFPreferencesCurrentApplication
,
1078 cg_text_anti_aliasing_threshold
= threshold
;
1082 mac_draw_image_string_cg (f
, gc
, x
, y
, buf
, nchars
, bg_width
)
1087 int nchars
, bg_width
;
1090 float port_height
, gx
, gy
;
1092 CGContextRef context
;
1096 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1099 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1100 port_height
= FRAME_PIXEL_HEIGHT (f
);
1102 gy
= port_height
- y
;
1103 glyphs
= (CGGlyph
*)buf
;
1104 advances
= alloca (sizeof (CGSize
) * nchars
);
1105 if (advances
== NULL
)
1107 for (i
= 0; i
< nchars
; i
++)
1109 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1111 advances
[i
].width
= pcm
->width
;
1112 advances
[i
].height
= 0;
1113 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1117 QDBeginCGContext (port
, &context
);
1118 if (gc
->n_clip_rects
|| bg_width
)
1120 CGContextTranslateCTM (context
, 0, port_height
);
1121 CGContextScaleCTM (context
, 1, -1);
1122 if (gc
->n_clip_rects
)
1123 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1126 CGContextSetRGBFillColor
1128 RED_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
1129 GREEN_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
1130 BLUE_FROM_ULONG (gc
->xgcv
.background
) / 255.0f
,
1134 CGRectMake (gx
, y
- FONT_BASE (GC_FONT (gc
)),
1135 bg_width
, FONT_HEIGHT (GC_FONT (gc
))));
1137 CGContextScaleCTM (context
, 1, -1);
1138 CGContextTranslateCTM (context
, 0, -port_height
);
1140 CGContextSetRGBFillColor (context
,
1141 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
1142 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
1143 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0f
,
1145 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1146 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1147 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1148 CGContextSetShouldAntialias (context
, false);
1149 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1150 CGContextSetTextPosition (context
, gx
, gy
);
1151 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1153 for (i
= 0; i
< nchars
; i
++)
1155 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1156 gx
+= advances
[i
].width
;
1159 CGContextSynchronize (context
);
1160 QDEndCGContext (port
, &context
);
1167 /* Mac replacement for XCopyArea: dest must be window. */
1170 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1175 unsigned int width
, height
;
1180 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1182 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1183 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1185 ForeColor (blackColor
);
1186 BackColor (whiteColor
);
1188 mac_begin_clip (GC_CLIP_REGION (gc
));
1189 LockPixels (GetGWorldPixMap (src
));
1190 #if TARGET_API_MAC_CARBON
1195 LockPortBits (port
);
1196 CopyBits (GetPortBitMapForCopyBits (src
),
1197 GetPortBitMapForCopyBits (port
),
1198 &src_r
, &dest_r
, srcCopy
, 0);
1199 UnlockPortBits (port
);
1201 #else /* not TARGET_API_MAC_CARBON */
1202 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1203 &src_r
, &dest_r
, srcCopy
, 0);
1204 #endif /* not TARGET_API_MAC_CARBON */
1205 UnlockPixels (GetGWorldPixMap (src
));
1206 mac_end_clip (GC_CLIP_REGION (gc
));
1208 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1213 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1214 width
, height
, dest_x
, dest_y
)
1219 unsigned int width
, height
;
1224 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1226 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1227 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1229 ForeColor (blackColor
);
1230 BackColor (whiteColor
);
1232 mac_begin_clip (GC_CLIP_REGION (gc
));
1233 LockPixels (GetGWorldPixMap (src
));
1234 LockPixels (GetGWorldPixMap (mask
));
1235 #if TARGET_API_MAC_CARBON
1240 LockPortBits (port
);
1241 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1242 GetPortBitMapForCopyBits (port
),
1243 &src_r
, &src_r
, &dest_r
);
1244 UnlockPortBits (port
);
1246 #else /* not TARGET_API_MAC_CARBON */
1247 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1248 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1249 #endif /* not TARGET_API_MAC_CARBON */
1250 UnlockPixels (GetGWorldPixMap (mask
));
1251 UnlockPixels (GetGWorldPixMap (src
));
1252 mac_end_clip (GC_CLIP_REGION (gc
));
1254 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1258 /* Mac replacement for XCopyArea: used only for scrolling. */
1261 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1265 unsigned int width
, height
;
1268 #if TARGET_API_MAC_CARBON
1270 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1272 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1273 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1274 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1275 kScrollWindowNoOptions
, dummy
);
1277 #else /* not TARGET_API_MAC_CARBON */
1279 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1283 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1284 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1286 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1287 color mapping in CopyBits. Otherwise, it will be slow. */
1288 ForeColor (blackColor
);
1289 BackColor (whiteColor
);
1290 mac_begin_clip (GC_CLIP_REGION (gc
));
1291 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1292 mac_end_clip (GC_CLIP_REGION (gc
));
1294 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1295 #endif /* not TARGET_API_MAC_CARBON */
1299 /* Mac replacement for XChangeGC. */
1302 XChangeGC (display
, gc
, mask
, xgcv
)
1308 if (mask
& GCForeground
)
1309 XSetForeground (display
, gc
, xgcv
->foreground
);
1310 if (mask
& GCBackground
)
1311 XSetBackground (display
, gc
, xgcv
->background
);
1313 XSetFont (display
, gc
, xgcv
->font
);
1317 /* Mac replacement for XCreateGC. */
1320 XCreateGC (display
, window
, mask
, xgcv
)
1326 GC gc
= xmalloc (sizeof (*gc
));
1330 bzero (gc
, sizeof (*gc
));
1331 XChangeGC (display
, gc
, mask
, xgcv
);
1338 /* Used in xfaces.c. */
1341 XFreeGC (display
, gc
)
1345 if (gc
->clip_region
)
1346 DisposeRgn (gc
->clip_region
);
1351 /* Mac replacement for XGetGCValues. */
1354 XGetGCValues (display
, gc
, mask
, xgcv
)
1360 if (mask
& GCForeground
)
1361 xgcv
->foreground
= gc
->xgcv
.foreground
;
1362 if (mask
& GCBackground
)
1363 xgcv
->background
= gc
->xgcv
.background
;
1365 xgcv
->font
= gc
->xgcv
.font
;
1369 /* Mac replacement for XSetForeground. */
1372 XSetForeground (display
, gc
, color
)
1375 unsigned long color
;
1377 if (gc
->xgcv
.foreground
!= color
)
1379 gc
->xgcv
.foreground
= color
;
1380 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1381 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1382 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1387 /* Mac replacement for XSetBackground. */
1390 XSetBackground (display
, gc
, color
)
1393 unsigned long color
;
1395 if (gc
->xgcv
.background
!= color
)
1397 gc
->xgcv
.background
= color
;
1398 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1399 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1400 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1405 /* Mac replacement for XSetFont. */
1408 XSetFont (display
, gc
, font
)
1413 gc
->xgcv
.font
= font
;
1417 /* Mac replacement for XSetClipRectangles. */
1420 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1428 if (n
< 0 || n
> MAX_CLIP_RECTS
)
1432 if (gc
->clip_region
)
1433 SetEmptyRgn (gc
->clip_region
);
1437 if (gc
->clip_region
== NULL
)
1438 gc
->clip_region
= NewRgn ();
1439 RectRgn (gc
->clip_region
, rectangles
);
1442 RgnHandle region
= NewRgn ();
1444 for (i
= 1; i
< n
; i
++)
1446 RectRgn (region
, rectangles
+ i
);
1447 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1449 DisposeRgn (region
);
1452 #if defined (MAC_OSX) && USE_ATSUI
1453 gc
->n_clip_rects
= n
;
1455 for (i
= 0; i
< n
; i
++)
1457 Rect
*rect
= rectangles
+ i
;
1459 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1460 rect
->right
- rect
->left
,
1461 rect
->bottom
- rect
->top
);
1467 /* Mac replacement for XSetClipMask. */
1470 mac_reset_clip_rectangles (display
, gc
)
1474 mac_set_clip_rectangles (display
, gc
, NULL
, 0);
1478 /* Mac replacement for XSetWindowBackground. */
1481 XSetWindowBackground (display
, w
, color
)
1484 unsigned long color
;
1486 #if !TARGET_API_MAC_CARBON
1487 AuxWinHandle aw_handle
;
1488 CTabHandle ctab_handle
;
1489 ColorSpecPtr ct_table
;
1494 bg_color
.red
= RED16_FROM_ULONG (color
);
1495 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1496 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1498 #if TARGET_API_MAC_CARBON
1499 SetWindowContentColor (w
, &bg_color
);
1501 if (GetAuxWin (w
, &aw_handle
))
1503 ctab_handle
= (*aw_handle
)->awCTable
;
1504 HandToHand ((Handle
*) &ctab_handle
);
1505 ct_table
= (*ctab_handle
)->ctTable
;
1506 ct_size
= (*ctab_handle
)->ctSize
;
1507 while (ct_size
> -1)
1509 if (ct_table
->value
== 0)
1511 ct_table
->rgb
= bg_color
;
1512 CTabChanged (ctab_handle
);
1513 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1521 /* x_sync is a no-op on Mac. */
1529 /* Flush display of frame F, or of all frames if F is null. */
1535 #if TARGET_API_MAC_CARBON
1538 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1540 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1546 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1547 Calls to XFlush should be unnecessary because the X output buffer
1548 is flushed automatically as needed by calls to XPending,
1549 XNextEvent, or XWindowEvent according to the XFlush man page.
1550 XTread_socket calls XPending. Removing XFlush improves
1553 #define XFlush(DISPLAY) (void) 0
1556 /* Return the struct mac_display_info corresponding to DPY. There's
1559 struct mac_display_info
*
1560 mac_display_info_for_display (dpy
)
1563 return &one_mac_display_info
;
1568 /***********************************************************************
1569 Starting and ending an update
1570 ***********************************************************************/
1572 /* Start an update of frame F. This function is installed as a hook
1573 for update_begin, i.e. it is called when update_begin is called.
1574 This function is called prior to calls to x_update_window_begin for
1575 each window being updated. */
1581 #if TARGET_API_MAC_CARBON
1582 /* During update of a frame, availability of input events is
1583 periodically checked with ReceiveNextEvent if
1584 redisplay-dont-pause is nil. That normally flushes window buffer
1585 changes for every check, and thus screen update looks waving even
1586 if no input is available. So we disable screen updates during
1587 update of a frame. */
1589 DisableScreenUpdates ();
1595 /* Start update of window W. Set the global variable updated_window
1596 to the window being updated and set output_cursor to the cursor
1600 x_update_window_begin (w
)
1603 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1604 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1607 set_output_cursor (&w
->cursor
);
1611 if (f
== display_info
->mouse_face_mouse_frame
)
1613 /* Don't do highlighting for mouse motion during the update. */
1614 display_info
->mouse_face_defer
= 1;
1616 /* If F needs to be redrawn, simply forget about any prior mouse
1618 if (FRAME_GARBAGED_P (f
))
1619 display_info
->mouse_face_window
= Qnil
;
1621 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1622 their mouse_face_p flag set, which means that they are always
1623 unequal to rows in a desired matrix which never have that
1624 flag set. So, rows containing mouse-face glyphs are never
1625 scrolled, and we don't have to switch the mouse highlight off
1626 here to prevent it from being scrolled. */
1628 /* Can we tell that this update does not affect the window
1629 where the mouse highlight is? If so, no need to turn off.
1630 Likewise, don't do anything if the frame is garbaged;
1631 in that case, the frame's current matrix that we would use
1632 is all wrong, and we will redisplay that line anyway. */
1633 if (!NILP (display_info
->mouse_face_window
)
1634 && w
== XWINDOW (display_info
->mouse_face_window
))
1638 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1639 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1642 if (i
< w
->desired_matrix
->nrows
)
1643 clear_mouse_face (display_info
);
1652 /* Draw a vertical window border from (x,y0) to (x,y1) */
1655 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1659 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1662 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1664 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1667 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1670 /* End update of window W (which is equal to updated_window).
1672 Draw vertical borders between horizontally adjacent windows, and
1673 display W's cursor if CURSOR_ON_P is non-zero.
1675 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1676 glyphs in mouse-face were overwritten. In that case we have to
1677 make sure that the mouse-highlight is properly redrawn.
1679 W may be a menu bar pseudo-window in case we don't have X toolkit
1680 support. Such windows don't have a cursor, so don't display it
1684 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1686 int cursor_on_p
, mouse_face_overwritten_p
;
1688 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1690 if (!w
->pseudo_window_p
)
1695 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1697 output_cursor
.x
, output_cursor
.y
);
1699 if (draw_window_fringes (w
, 1))
1700 x_draw_vertical_border (w
);
1705 /* If a row with mouse-face was overwritten, arrange for
1706 XTframe_up_to_date to redisplay the mouse highlight. */
1707 if (mouse_face_overwritten_p
)
1709 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1710 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1711 dpyinfo
->mouse_face_window
= Qnil
;
1714 updated_window
= NULL
;
1718 /* End update of frame F. This function is installed as a hook in
1725 /* Mouse highlight may be displayed again. */
1726 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1729 #if TARGET_API_MAC_CARBON
1730 EnableScreenUpdates ();
1732 XFlush (FRAME_MAC_DISPLAY (f
));
1737 /* This function is called from various places in xdisp.c whenever a
1738 complete update has been performed. The global variable
1739 updated_window is not available here. */
1742 XTframe_up_to_date (f
)
1745 if (FRAME_MAC_P (f
))
1747 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1749 if (dpyinfo
->mouse_face_deferred_gc
1750 || f
== dpyinfo
->mouse_face_mouse_frame
)
1753 if (dpyinfo
->mouse_face_mouse_frame
)
1754 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1755 dpyinfo
->mouse_face_mouse_x
,
1756 dpyinfo
->mouse_face_mouse_y
);
1757 dpyinfo
->mouse_face_deferred_gc
= 0;
1764 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1765 arrow bitmaps, or clear the fringes if no bitmaps are required
1766 before DESIRED_ROW is made current. The window being updated is
1767 found in updated_window. This function is called from
1768 update_window_line only if it is known that there are differences
1769 between bitmaps to be drawn between current row and DESIRED_ROW. */
1772 x_after_update_window_line (desired_row
)
1773 struct glyph_row
*desired_row
;
1775 struct window
*w
= updated_window
;
1781 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1782 desired_row
->redraw_fringe_bitmaps_p
= 1;
1784 /* When a window has disappeared, make sure that no rest of
1785 full-width rows stays visible in the internal border. Could
1786 check here if updated_window is the leftmost/rightmost window,
1787 but I guess it's not worth doing since vertically split windows
1788 are almost never used, internal border is rarely set, and the
1789 overhead is very small. */
1790 if (windows_or_buffers_changed
1791 && desired_row
->full_width_p
1792 && (f
= XFRAME (w
->frame
),
1793 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1795 && (height
= desired_row
->visible_height
,
1798 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1800 /* Internal border is drawn below the tool bar. */
1801 if (WINDOWP (f
->tool_bar_window
)
1802 && w
== XWINDOW (f
->tool_bar_window
))
1806 mac_clear_area (f
, 0, y
, width
, height
);
1807 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1813 /* Draw the bitmap WHICH in one of the left or right fringes of
1814 window W. ROW is the glyph row for which to display the bitmap; it
1815 determines the vertical position at which the bitmap has to be
1819 x_draw_fringe_bitmap (w
, row
, p
)
1821 struct glyph_row
*row
;
1822 struct draw_fringe_bitmap_params
*p
;
1824 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1825 Display
*display
= FRAME_MAC_DISPLAY (f
);
1826 struct face
*face
= p
->face
;
1829 /* Must clip because of partially visible lines. */
1830 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1833 /* Adjust position of "bottom aligned" bitmap on partially
1834 visible last row. */
1836 int oldVH
= row
->visible_height
;
1837 row
->visible_height
= p
->h
;
1838 row
->y
-= rowY
- p
->y
;
1839 x_clip_to_row (w
, row
, -1, face
->gc
);
1841 row
->visible_height
= oldVH
;
1844 x_clip_to_row (w
, row
, -1, face
->gc
);
1846 if (p
->bx
>= 0 && !p
->overlay_p
)
1848 #if 0 /* MAC_TODO: stipple */
1849 /* In case the same realized face is used for fringes and
1850 for something displayed in the text (e.g. face `region' on
1851 mono-displays, the fill style may have been changed to
1852 FillSolid in x_draw_glyph_string_background. */
1854 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1856 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1859 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1861 #if 0 /* MAC_TODO: stipple */
1863 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1869 unsigned short *bits
= p
->bits
+ p
->dh
;
1872 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1873 XSetForeground (display
, face
->gc
,
1875 ? (p
->overlay_p
? face
->background
1876 : f
->output_data
.mac
->cursor_pixel
)
1877 : face
->foreground
));
1878 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1879 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1880 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1883 mac_reset_clip_rectangles (display
, face
->gc
);
1888 /* This is called when starting Emacs and when restarting after
1889 suspend. When starting Emacs, no window is mapped. And nothing
1890 must be done to Emacs's own window if it is suspended (though that
1894 XTset_terminal_modes ()
1898 /* This is called when exiting or suspending Emacs. Exiting will make
1899 the windows go away, and suspending requires no action. */
1902 XTreset_terminal_modes ()
1908 /***********************************************************************
1910 ***********************************************************************/
1912 /* Function prototypes of this page. */
1914 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1915 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1918 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1919 is not contained in the font. */
1921 static INLINE XCharStruct
*
1922 x_per_char_metric (font
, char2b
)
1926 /* The result metric information. */
1927 XCharStruct
*pcm
= NULL
;
1929 xassert (font
&& char2b
);
1932 if (font
->mac_style
)
1934 XCharStructRow
**row
= font
->bounds
.rows
+ char2b
->byte1
;
1938 *row
= xmalloc (sizeof (XCharStructRow
));
1940 bzero (*row
, sizeof (XCharStructRow
));
1944 pcm
= (*row
)->per_char
+ char2b
->byte2
;
1945 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row
, char2b
->byte2
))
1948 mac_query_char_extents (font
->mac_style
,
1949 (char2b
->byte1
<< 8) + char2b
->byte2
,
1950 NULL
, NULL
, pcm
, NULL
);
1952 XCHARSTRUCTROW_SET_CHAR_VALID (*row
, char2b
->byte2
);
1959 if (font
->bounds
.per_char
!= NULL
)
1961 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1963 /* min_char_or_byte2 specifies the linear character index
1964 corresponding to the first element of the per_char array,
1965 max_char_or_byte2 is the index of the last character. A
1966 character with non-zero CHAR2B->byte1 is not in the font.
1967 A character with byte2 less than min_char_or_byte2 or
1968 greater max_char_or_byte2 is not in the font. */
1969 if (char2b
->byte1
== 0
1970 && char2b
->byte2
>= font
->min_char_or_byte2
1971 && char2b
->byte2
<= font
->max_char_or_byte2
)
1972 pcm
= font
->bounds
.per_char
1973 + (char2b
->byte2
- font
->min_char_or_byte2
);
1977 /* If either min_byte1 or max_byte1 are nonzero, both
1978 min_char_or_byte2 and max_char_or_byte2 are less than
1979 256, and the 2-byte character index values corresponding
1980 to the per_char array element N (counting from 0) are:
1982 byte1 = N/D + min_byte1
1983 byte2 = N\D + min_char_or_byte2
1987 D = max_char_or_byte2 - min_char_or_byte2 + 1
1988 / = integer division
1989 \ = integer modulus */
1990 if (char2b
->byte1
>= font
->min_byte1
1991 && char2b
->byte1
<= font
->max_byte1
1992 && char2b
->byte2
>= font
->min_char_or_byte2
1993 && char2b
->byte2
<= font
->max_char_or_byte2
)
1995 pcm
= (font
->bounds
.per_char
1996 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1997 * (char2b
->byte1
- font
->min_byte1
))
1998 + (char2b
->byte2
- font
->min_char_or_byte2
));
2004 /* If the per_char pointer is null, all glyphs between the first
2005 and last character indexes inclusive have the same
2006 information, as given by both min_bounds and max_bounds. */
2007 if (char2b
->byte2
>= font
->min_char_or_byte2
2008 && char2b
->byte2
<= font
->max_char_or_byte2
)
2009 pcm
= &font
->max_bounds
;
2015 return ((pcm
== NULL
2016 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
2023 static XCharStruct
*
2024 mac_per_char_metric (font
, char2b
, font_type
)
2029 return x_per_char_metric (font
, char2b
);
2033 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
2034 the two-byte form of C. Encoding is returned in *CHAR2B. */
2037 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
2040 struct font_info
*font_info
;
2043 int charset
= CHAR_CHARSET (c
);
2044 XFontStruct
*font
= font_info
->font
;
2046 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
2047 This may be either a program in a special encoder language or a
2049 if (font_info
->font_encoder
)
2051 /* It's a program. */
2052 struct ccl_program
*ccl
= font_info
->font_encoder
;
2054 check_ccl_update (ccl
);
2055 if (CHARSET_DIMENSION (charset
) == 1)
2057 ccl
->reg
[0] = charset
;
2058 ccl
->reg
[1] = char2b
->byte2
;
2063 ccl
->reg
[0] = charset
;
2064 ccl
->reg
[1] = char2b
->byte1
;
2065 ccl
->reg
[2] = char2b
->byte2
;
2068 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2070 /* We assume that MSBs are appropriately set/reset by CCL
2072 if (font
->max_byte1
== 0) /* 1-byte font */
2073 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2075 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2077 else if (font_info
->encoding
[charset
])
2079 /* Fixed encoding scheme. See fontset.h for the meaning of the
2080 encoding numbers. */
2081 int enc
= font_info
->encoding
[charset
];
2083 if ((enc
== 1 || enc
== 2)
2084 && CHARSET_DIMENSION (charset
) == 2)
2085 char2b
->byte1
|= 0x80;
2087 if (enc
== 1 || enc
== 3)
2088 char2b
->byte2
|= 0x80;
2094 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2095 char2b
->byte1
= sjis1
;
2096 char2b
->byte2
= sjis2
;
2101 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2103 return FONT_TYPE_UNKNOWN
;
2108 /***********************************************************************
2110 ***********************************************************************/
2114 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2115 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2116 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2118 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2119 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2120 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2121 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2122 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2123 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2124 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2125 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2126 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2127 unsigned long *, double, int));*/
2128 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2129 double, int, unsigned long));
2130 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2131 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2132 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2133 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2134 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2135 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2137 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2138 int, int, int, int, int, int,
2140 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2141 int, int, int, Rect
*));
2144 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2148 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2153 struct glyph_string
*s
;
2155 if (s
->font
== FRAME_FONT (s
->f
)
2156 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2157 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2159 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2162 /* Cursor on non-default face: must merge. */
2166 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2167 xgcv
.foreground
= s
->face
->background
;
2169 /* If the glyph would be invisible, try a different foreground. */
2170 if (xgcv
.foreground
== xgcv
.background
)
2171 xgcv
.foreground
= s
->face
->foreground
;
2172 if (xgcv
.foreground
== xgcv
.background
)
2173 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2174 if (xgcv
.foreground
== xgcv
.background
)
2175 xgcv
.foreground
= s
->face
->foreground
;
2177 /* Make sure the cursor is distinct from text in this face. */
2178 if (xgcv
.background
== s
->face
->background
2179 && xgcv
.foreground
== s
->face
->foreground
)
2181 xgcv
.background
= s
->face
->foreground
;
2182 xgcv
.foreground
= s
->face
->background
;
2185 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2186 xgcv
.font
= s
->font
;
2187 mask
= GCForeground
| GCBackground
| GCFont
;
2189 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2190 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2193 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2194 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2196 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2201 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2204 x_set_mouse_face_gc (s
)
2205 struct glyph_string
*s
;
2210 /* What face has to be used last for the mouse face? */
2211 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2212 face
= FACE_FROM_ID (s
->f
, face_id
);
2214 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2216 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2217 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2219 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2220 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2221 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2223 /* If font in this face is same as S->font, use it. */
2224 if (s
->font
== s
->face
->font
)
2225 s
->gc
= s
->face
->gc
;
2228 /* Otherwise construct scratch_cursor_gc with values from FACE
2233 xgcv
.background
= s
->face
->background
;
2234 xgcv
.foreground
= s
->face
->foreground
;
2235 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2236 xgcv
.font
= s
->font
;
2237 mask
= GCForeground
| GCBackground
| GCFont
;
2239 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2240 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2243 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2244 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2246 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2249 xassert (s
->gc
!= 0);
2253 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2254 Faces to use in the mode line have already been computed when the
2255 matrix was built, so there isn't much to do, here. */
2258 x_set_mode_line_face_gc (s
)
2259 struct glyph_string
*s
;
2261 s
->gc
= s
->face
->gc
;
2265 /* Set S->gc of glyph string S for drawing that glyph string. Set
2266 S->stippled_p to a non-zero value if the face of S has a stipple
2270 x_set_glyph_string_gc (s
)
2271 struct glyph_string
*s
;
2273 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2275 if (s
->hl
== DRAW_NORMAL_TEXT
)
2277 s
->gc
= s
->face
->gc
;
2278 s
->stippled_p
= s
->face
->stipple
!= 0;
2280 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2282 x_set_mode_line_face_gc (s
);
2283 s
->stippled_p
= s
->face
->stipple
!= 0;
2285 else if (s
->hl
== DRAW_CURSOR
)
2287 x_set_cursor_gc (s
);
2290 else if (s
->hl
== DRAW_MOUSE_FACE
)
2292 x_set_mouse_face_gc (s
);
2293 s
->stippled_p
= s
->face
->stipple
!= 0;
2295 else if (s
->hl
== DRAW_IMAGE_RAISED
2296 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2298 s
->gc
= s
->face
->gc
;
2299 s
->stippled_p
= s
->face
->stipple
!= 0;
2303 s
->gc
= s
->face
->gc
;
2304 s
->stippled_p
= s
->face
->stipple
!= 0;
2307 /* GC must have been set. */
2308 xassert (s
->gc
!= 0);
2312 /* Set clipping for output of glyph string S. S may be part of a mode
2313 line or menu if we don't have X toolkit support. */
2316 x_set_glyph_string_clipping (s
)
2317 struct glyph_string
*s
;
2319 Rect rects
[MAX_CLIP_RECTS
];
2322 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2323 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2328 Compute left and right overhang of glyph string S. If S is a glyph
2329 string for a composition, assume overhangs don't exist. */
2332 mac_compute_glyph_string_overhangs (s
)
2333 struct glyph_string
*s
;
2336 && s
->first_glyph
->type
== CHAR_GLYPH
)
2339 || s
->font
->mac_style
2345 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2346 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2347 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2352 MacFontStruct
*font
= s
->font
;
2354 TextFont (font
->mac_fontnum
);
2355 TextSize (font
->mac_fontsize
);
2356 TextFace (font
->mac_fontface
);
2358 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2360 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2361 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2366 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2369 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2370 struct glyph_string
*s
;
2373 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2377 /* Draw the background of glyph_string S. If S->background_filled_p
2378 is non-zero don't draw it. FORCE_P non-zero means draw the
2379 background even if it wouldn't be drawn normally. This is used
2380 when a string preceding S draws into the background of S, or S
2381 contains the first component of a composition. */
2384 x_draw_glyph_string_background (s
, force_p
)
2385 struct glyph_string
*s
;
2388 /* Nothing to do if background has already been drawn or if it
2389 shouldn't be drawn in the first place. */
2390 if (!s
->background_filled_p
)
2392 int box_line_width
= max (s
->face
->box_line_width
, 0);
2394 #if 0 /* MAC_TODO: stipple */
2397 /* Fill background with a stipple pattern. */
2398 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2399 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2400 s
->y
+ box_line_width
,
2401 s
->background_width
,
2402 s
->height
- 2 * box_line_width
);
2403 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2404 s
->background_filled_p
= 1;
2408 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2409 || s
->font_not_found_p
2410 || s
->extends_to_end_of_line_p
2413 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2414 s
->background_width
,
2415 s
->height
- 2 * box_line_width
);
2416 s
->background_filled_p
= 1;
2422 /* Draw the foreground of glyph string S. */
2425 x_draw_glyph_string_foreground (s
)
2426 struct glyph_string
*s
;
2430 /* If first glyph of S has a left box line, start drawing the text
2431 of S to the right of that box line. */
2432 if (s
->face
->box
!= FACE_NO_BOX
2433 && s
->first_glyph
->left_box_line_p
)
2434 x
= s
->x
+ abs (s
->face
->box_line_width
);
2438 /* Draw characters of S as rectangles if S's font could not be
2440 if (s
->font_not_found_p
)
2442 for (i
= 0; i
< s
->nchars
; ++i
)
2444 struct glyph
*g
= s
->first_glyph
+ i
;
2445 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2446 g
->pixel_width
- 1, s
->height
- 1);
2447 x
+= g
->pixel_width
;
2452 char *char1b
= (char *) s
->char2b
;
2453 int boff
= s
->font_info
->baseline_offset
;
2455 if (s
->font_info
->vertical_centering
)
2456 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2458 /* If we can use 8-bit functions, condense S->char2b. */
2461 && GC_FONT (s
->gc
)->mac_style
== NULL
2464 for (i
= 0; i
< s
->nchars
; ++i
)
2465 char1b
[i
] = s
->char2b
[i
].byte2
;
2467 /* Draw text with XDrawString if background has already been
2468 filled. Otherwise, use XDrawImageString. (Note that
2469 XDrawImageString is usually faster than XDrawString.) Always
2470 use XDrawImageString when drawing the cursor so that there is
2471 no chance that characters under a box cursor are invisible. */
2473 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2474 bg_width
= 0; /* Corresponds to XDrawString. */
2476 bg_width
= s
->background_width
; /* Corresponds to XDrawImageString. */
2480 || GC_FONT (s
->gc
)->mac_style
2483 #if USE_CG_TEXT_DRAWING
2485 && mac_draw_image_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2486 s
->char2b
, s
->nchars
, bg_width
))
2490 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2491 s
->char2b
, s
->nchars
, bg_width
);
2493 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2494 char1b
, s
->nchars
, bg_width
);
2498 /* Draw the foreground of composite glyph string S. */
2501 x_draw_composite_glyph_string_foreground (s
)
2502 struct glyph_string
*s
;
2506 /* If first glyph of S has a left box line, start drawing the text
2507 of S to the right of that box line. */
2508 if (s
->face
->box
!= FACE_NO_BOX
2509 && s
->first_glyph
->left_box_line_p
)
2510 x
= s
->x
+ abs (s
->face
->box_line_width
);
2514 /* S is a glyph string for a composition. S->gidx is the index of
2515 the first character drawn for glyphs of this composition.
2516 S->gidx == 0 means we are drawing the very first character of
2517 this composition. */
2519 /* Draw a rectangle for the composition if the font for the very
2520 first character of the composition could not be loaded. */
2521 if (s
->font_not_found_p
)
2524 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2525 s
->width
- 1, s
->height
- 1);
2529 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2530 mac_draw_string_16 (s
->f
, s
->gc
,
2531 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2532 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2538 #ifdef USE_X_TOOLKIT
2540 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2543 /* Return the frame on which widget WIDGET is used.. Abort if frame
2544 cannot be determined. */
2546 static struct frame
*
2547 x_frame_of_widget (widget
)
2550 struct x_display_info
*dpyinfo
;
2554 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2556 /* Find the top-level shell of the widget. Note that this function
2557 can be called when the widget is not yet realized, so XtWindow
2558 (widget) == 0. That's the reason we can't simply use
2559 x_any_window_to_frame. */
2560 while (!XtIsTopLevelShell (widget
))
2561 widget
= XtParent (widget
);
2563 /* Look for a frame with that top-level widget. Allocate the color
2564 on that frame to get the right gamma correction value. */
2565 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2566 if (GC_FRAMEP (XCAR (tail
))
2567 && (f
= XFRAME (XCAR (tail
)),
2568 (f
->output_data
.nothing
!= 1
2569 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2570 && f
->output_data
.x
->widget
== widget
)
2577 /* Allocate the color COLOR->pixel on the screen and display of
2578 widget WIDGET in colormap CMAP. If an exact match cannot be
2579 allocated, try the nearest color available. Value is non-zero
2580 if successful. This is called from lwlib. */
2583 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2588 struct frame
*f
= x_frame_of_widget (widget
);
2589 return x_alloc_nearest_color (f
, cmap
, color
);
2593 #endif /* USE_X_TOOLKIT */
2595 #if 0 /* MAC_TODO */
2597 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2598 CMAP. If an exact match can't be allocated, try the nearest color
2599 available. Value is non-zero if successful. Set *COLOR to the
2603 x_alloc_nearest_color (f
, cmap
, color
)
2608 Display
*display
= FRAME_X_DISPLAY (f
);
2609 Screen
*screen
= FRAME_X_SCREEN (f
);
2612 gamma_correct (f
, color
);
2613 rc
= XAllocColor (display
, cmap
, color
);
2616 /* If we got to this point, the colormap is full, so we're going
2617 to try to get the next closest color. The algorithm used is
2618 a least-squares matching, which is what X uses for closest
2619 color matching with StaticColor visuals. */
2621 unsigned long nearest_delta
= ~0;
2622 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2623 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2625 for (i
= 0; i
< ncells
; ++i
)
2627 XQueryColors (display
, cmap
, cells
, ncells
);
2629 for (nearest
= i
= 0; i
< ncells
; ++i
)
2631 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2632 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2633 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2634 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2636 if (delta
< nearest_delta
)
2639 nearest_delta
= delta
;
2643 color
->red
= cells
[nearest
].red
;
2644 color
->green
= cells
[nearest
].green
;
2645 color
->blue
= cells
[nearest
].blue
;
2646 rc
= XAllocColor (display
, cmap
, color
);
2649 #ifdef DEBUG_X_COLORS
2651 register_color (color
->pixel
);
2652 #endif /* DEBUG_X_COLORS */
2658 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2659 It's necessary to do this instead of just using PIXEL directly to
2660 get color reference counts right. */
2663 x_copy_color (f
, pixel
)
2665 unsigned long pixel
;
2669 color
.pixel
= pixel
;
2671 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2672 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2674 #ifdef DEBUG_X_COLORS
2675 register_color (pixel
);
2681 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2682 It's necessary to do this instead of just using PIXEL directly to
2683 get color reference counts right. */
2686 x_copy_dpy_color (dpy
, cmap
, pixel
)
2689 unsigned long pixel
;
2693 color
.pixel
= pixel
;
2695 XQueryColor (dpy
, cmap
, &color
);
2696 XAllocColor (dpy
, cmap
, &color
);
2698 #ifdef DEBUG_X_COLORS
2699 register_color (pixel
);
2704 #endif /* MAC_TODO */
2707 /* Brightness beyond which a color won't have its highlight brightness
2710 Nominally, highlight colors for `3d' faces are calculated by
2711 brightening an object's color by a constant scale factor, but this
2712 doesn't yield good results for dark colors, so for colors who's
2713 brightness is less than this value (on a scale of 0-255) have to
2714 use an additional additive factor.
2716 The value here is set so that the default menu-bar/mode-line color
2717 (grey75) will not have its highlights changed at all. */
2718 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2721 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2722 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2723 If this produces the same color as COLOR, try a color where all RGB
2724 values have DELTA added. Return the allocated color in *COLOR.
2725 DISPLAY is the X display, CMAP is the colormap to operate on.
2726 Value is non-zero if successful. */
2729 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2731 unsigned long *color
;
2738 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2741 /* Change RGB values by specified FACTOR. Avoid overflow! */
2742 xassert (factor
>= 0);
2743 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2744 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2745 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2747 /* Calculate brightness of COLOR. */
2748 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2749 + BLUE_FROM_ULONG (*color
)) / 6;
2751 /* We only boost colors that are darker than
2752 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2753 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2754 /* Make an additive adjustment to NEW, because it's dark enough so
2755 that scaling by FACTOR alone isn't enough. */
2757 /* How far below the limit this color is (0 - 1, 1 being darker). */
2758 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2759 /* The additive adjustment. */
2760 int min_delta
= delta
* dimness
* factor
/ 2;
2763 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2764 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2765 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2767 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2768 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2769 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2773 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2774 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2775 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2777 /* MAC_TODO: Map to palette and retry with delta if same? */
2778 /* MAC_TODO: Free colors (if using palette)? */
2789 /* Set up the foreground color for drawing relief lines of glyph
2790 string S. RELIEF is a pointer to a struct relief containing the GC
2791 with which lines will be drawn. Use a color that is FACTOR or
2792 DELTA lighter or darker than the relief's background which is found
2793 in S->f->output_data.x->relief_background. If such a color cannot
2794 be allocated, use DEFAULT_PIXEL, instead. */
2797 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2799 struct relief
*relief
;
2802 unsigned long default_pixel
;
2805 struct mac_output
*di
= f
->output_data
.mac
;
2806 unsigned long mask
= GCForeground
;
2807 unsigned long pixel
;
2808 unsigned long background
= di
->relief_background
;
2809 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2811 /* MAC_TODO: Free colors (if using palette)? */
2813 /* Allocate new color. */
2814 xgcv
.foreground
= default_pixel
;
2816 if (dpyinfo
->n_planes
!= 1
2817 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2819 relief
->allocated_p
= 1;
2820 xgcv
.foreground
= relief
->pixel
= pixel
;
2823 if (relief
->gc
== 0)
2825 #if 0 /* MAC_TODO: stipple */
2826 xgcv
.stipple
= dpyinfo
->gray
;
2829 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2832 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2836 /* Set up colors for the relief lines around glyph string S. */
2839 x_setup_relief_colors (s
)
2840 struct glyph_string
*s
;
2842 struct mac_output
*di
= s
->f
->output_data
.mac
;
2843 unsigned long color
;
2845 if (s
->face
->use_box_color_for_shadows_p
)
2846 color
= s
->face
->box_color
;
2847 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2849 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2850 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2855 /* Get the background color of the face. */
2856 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2857 color
= xgcv
.background
;
2860 if (di
->white_relief
.gc
== 0
2861 || color
!= di
->relief_background
)
2863 di
->relief_background
= color
;
2864 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2865 WHITE_PIX_DEFAULT (s
->f
));
2866 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2867 BLACK_PIX_DEFAULT (s
->f
));
2872 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2873 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2874 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2875 relief. LEFT_P non-zero means draw a relief on the left side of
2876 the rectangle. RIGHT_P non-zero means draw a relief on the right
2877 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2881 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2882 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2884 int left_x
, top_y
, right_x
, bottom_y
, width
;
2885 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2888 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2893 gc
= f
->output_data
.mac
->white_relief
.gc
;
2895 gc
= f
->output_data
.mac
->black_relief
.gc
;
2896 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2900 for (i
= 0; i
< width
; ++i
)
2901 mac_draw_line (f
, gc
,
2902 left_x
+ i
* left_p
, top_y
+ i
,
2903 right_x
- i
* right_p
, top_y
+ i
);
2907 for (i
= 0; i
< width
; ++i
)
2908 mac_draw_line (f
, gc
,
2909 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2911 mac_reset_clip_rectangles (dpy
, gc
);
2913 gc
= f
->output_data
.mac
->black_relief
.gc
;
2915 gc
= f
->output_data
.mac
->white_relief
.gc
;
2916 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2920 for (i
= 0; i
< width
; ++i
)
2921 mac_draw_line (f
, gc
,
2922 left_x
+ i
* left_p
, bottom_y
- i
,
2923 right_x
- i
* right_p
, bottom_y
- i
);
2927 for (i
= 0; i
< width
; ++i
)
2928 mac_draw_line (f
, gc
,
2929 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2931 mac_reset_clip_rectangles (dpy
, gc
);
2935 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2936 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2937 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2938 left side of the rectangle. RIGHT_P non-zero means draw a line
2939 on the right side of the rectangle. CLIP_RECT is the clipping
2940 rectangle to use when drawing. */
2943 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2944 left_p
, right_p
, clip_rect
)
2945 struct glyph_string
*s
;
2946 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2951 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2952 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2953 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2956 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2957 right_x
- left_x
+ 1, width
);
2961 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2962 width
, bottom_y
- top_y
+ 1);
2965 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2966 right_x
- left_x
+ 1, width
);
2970 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2971 top_y
, width
, bottom_y
- top_y
+ 1);
2973 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2974 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2978 /* Draw a box around glyph string S. */
2981 x_draw_glyph_string_box (s
)
2982 struct glyph_string
*s
;
2984 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2985 int left_p
, right_p
;
2986 struct glyph
*last_glyph
;
2989 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2990 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2991 : window_box_right (s
->w
, s
->area
));
2993 /* The glyph that may have a right box line. */
2994 last_glyph
= (s
->cmp
|| s
->img
2996 : s
->first_glyph
+ s
->nchars
- 1);
2998 width
= abs (s
->face
->box_line_width
);
2999 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
3001 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
3003 : min (last_x
, s
->x
+ s
->background_width
) - 1);
3005 bottom_y
= top_y
+ s
->height
- 1;
3007 left_p
= (s
->first_glyph
->left_box_line_p
3008 || (s
->hl
== DRAW_MOUSE_FACE
3010 || s
->prev
->hl
!= s
->hl
)));
3011 right_p
= (last_glyph
->right_box_line_p
3012 || (s
->hl
== DRAW_MOUSE_FACE
3014 || s
->next
->hl
!= s
->hl
)));
3016 get_glyph_string_clip_rect (s
, &clip_rect
);
3018 if (s
->face
->box
== FACE_SIMPLE_BOX
)
3019 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
3020 left_p
, right_p
, &clip_rect
);
3023 x_setup_relief_colors (s
);
3024 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
3025 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
3030 /* Draw foreground of image glyph string S. */
3033 x_draw_image_foreground (s
)
3034 struct glyph_string
*s
;
3037 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3039 /* If first glyph of S has a left box line, start drawing it to the
3040 right of that line. */
3041 if (s
->face
->box
!= FACE_NO_BOX
3042 && s
->first_glyph
->left_box_line_p
3044 x
+= abs (s
->face
->box_line_width
);
3046 /* If there is a margin around the image, adjust x- and y-position
3048 if (s
->slice
.x
== 0)
3049 x
+= s
->img
->hmargin
;
3050 if (s
->slice
.y
== 0)
3051 y
+= s
->img
->vmargin
;
3055 x_set_glyph_string_clipping (s
);
3058 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3059 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3060 s
->slice
.width
, s
->slice
.height
, x
, y
);
3063 mac_copy_area (s
->img
->pixmap
,
3064 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3065 s
->slice
.width
, s
->slice
.height
, x
, y
);
3067 /* When the image has a mask, we can expect that at
3068 least part of a mouse highlight or a block cursor will
3069 be visible. If the image doesn't have a mask, make
3070 a block cursor visible by drawing a rectangle around
3071 the image. I believe it's looking better if we do
3072 nothing here for mouse-face. */
3073 if (s
->hl
== DRAW_CURSOR
)
3075 int r
= s
->img
->relief
;
3077 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3078 s
->slice
.width
+ r
*2 - 1,
3079 s
->slice
.height
+ r
*2 - 1);
3084 /* Draw a rectangle if image could not be loaded. */
3085 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3086 s
->slice
.width
- 1, s
->slice
.height
- 1);
3090 /* Draw a relief around the image glyph string S. */
3093 x_draw_image_relief (s
)
3094 struct glyph_string
*s
;
3096 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3099 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3101 /* If first glyph of S has a left box line, start drawing it to the
3102 right of that line. */
3103 if (s
->face
->box
!= FACE_NO_BOX
3104 && s
->first_glyph
->left_box_line_p
3106 x
+= abs (s
->face
->box_line_width
);
3108 /* If there is a margin around the image, adjust x- and y-position
3110 if (s
->slice
.x
== 0)
3111 x
+= s
->img
->hmargin
;
3112 if (s
->slice
.y
== 0)
3113 y
+= s
->img
->vmargin
;
3115 if (s
->hl
== DRAW_IMAGE_SUNKEN
3116 || s
->hl
== DRAW_IMAGE_RAISED
)
3118 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3119 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3123 thick
= abs (s
->img
->relief
);
3124 raised_p
= s
->img
->relief
> 0;
3129 x1
= x
+ s
->slice
.width
+ thick
- 1;
3130 y1
= y
+ s
->slice
.height
+ thick
- 1;
3132 x_setup_relief_colors (s
);
3133 get_glyph_string_clip_rect (s
, &r
);
3134 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3136 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3138 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3143 /* Draw part of the background of glyph string S. X, Y, W, and H
3144 give the rectangle to draw. */
3147 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3148 struct glyph_string
*s
;
3151 #if 0 /* MAC_TODO: stipple */
3154 /* Fill background with a stipple pattern. */
3155 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3156 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3157 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3160 #endif /* MAC_TODO */
3161 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3165 /* Draw image glyph string S.
3168 s->x +-------------------------
3171 | +-------------------------
3174 | | +-------------------
3180 x_draw_image_glyph_string (s
)
3181 struct glyph_string
*s
;
3184 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3185 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3189 height
= s
->height
- 2 * box_line_vwidth
;
3192 /* Fill background with face under the image. Do it only if row is
3193 taller than image or if image has a clip mask to reduce
3195 s
->stippled_p
= s
->face
->stipple
!= 0;
3196 if (height
> s
->slice
.height
3200 || s
->img
->pixmap
== 0
3201 || s
->width
!= s
->background_width
)
3204 if (s
->first_glyph
->left_box_line_p
3206 x
+= box_line_hwidth
;
3209 if (s
->slice
.y
== 0)
3210 y
+= box_line_vwidth
;
3212 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3214 s
->background_filled_p
= 1;
3217 /* Draw the foreground. */
3218 x_draw_image_foreground (s
);
3220 /* If we must draw a relief around the image, do it. */
3222 || s
->hl
== DRAW_IMAGE_RAISED
3223 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3224 x_draw_image_relief (s
);
3228 /* Draw stretch glyph string S. */
3231 x_draw_stretch_glyph_string (s
)
3232 struct glyph_string
*s
;
3234 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3235 s
->stippled_p
= s
->face
->stipple
!= 0;
3237 if (s
->hl
== DRAW_CURSOR
3238 && !x_stretch_cursor_p
)
3240 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3241 as wide as the stretch glyph. */
3242 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3245 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3247 /* Clear rest using the GC of the original non-cursor face. */
3248 if (width
< s
->background_width
)
3250 int x
= s
->x
+ width
, y
= s
->y
;
3251 int w
= s
->background_width
- width
, h
= s
->height
;
3255 if (s
->row
->mouse_face_p
3256 && cursor_in_mouse_face_p (s
->w
))
3258 x_set_mouse_face_gc (s
);
3264 get_glyph_string_clip_rect (s
, &r
);
3265 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3267 #if 0 /* MAC_TODO: stipple */
3268 if (s
->face
->stipple
)
3270 /* Fill background with a stipple pattern. */
3271 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3272 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3273 XSetFillStyle (s
->display
, gc
, FillSolid
);
3276 #endif /* MAC_TODO */
3277 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3280 else if (!s
->background_filled_p
)
3281 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3284 s
->background_filled_p
= 1;
3288 /* Draw glyph string S. */
3291 x_draw_glyph_string (s
)
3292 struct glyph_string
*s
;
3294 int relief_drawn_p
= 0;
3296 /* If S draws into the background of its successor that does not
3297 draw a cursor, draw the background of the successor first so that
3298 S can draw into it. This makes S->next use XDrawString instead
3299 of XDrawImageString. */
3300 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3301 && s
->next
->hl
!= DRAW_CURSOR
)
3303 xassert (s
->next
->img
== NULL
);
3304 x_set_glyph_string_gc (s
->next
);
3305 x_set_glyph_string_clipping (s
->next
);
3306 x_draw_glyph_string_background (s
->next
, 1);
3309 /* Set up S->gc, set clipping and draw S. */
3310 x_set_glyph_string_gc (s
);
3312 /* Draw relief (if any) in advance for char/composition so that the
3313 glyph string can be drawn over it. */
3314 if (!s
->for_overlaps
3315 && s
->face
->box
!= FACE_NO_BOX
3316 && (s
->first_glyph
->type
== CHAR_GLYPH
3317 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3320 x_set_glyph_string_clipping (s
);
3321 x_draw_glyph_string_background (s
, 1);
3322 x_draw_glyph_string_box (s
);
3323 x_set_glyph_string_clipping (s
);
3327 x_set_glyph_string_clipping (s
);
3329 switch (s
->first_glyph
->type
)
3332 x_draw_image_glyph_string (s
);
3336 x_draw_stretch_glyph_string (s
);
3340 if (s
->for_overlaps
)
3341 s
->background_filled_p
= 1;
3343 x_draw_glyph_string_background (s
, 0);
3344 x_draw_glyph_string_foreground (s
);
3347 case COMPOSITE_GLYPH
:
3348 if (s
->for_overlaps
|| s
->gidx
> 0)
3349 s
->background_filled_p
= 1;
3351 x_draw_glyph_string_background (s
, 1);
3352 x_draw_composite_glyph_string_foreground (s
);
3359 if (!s
->for_overlaps
)
3361 /* Draw underline. */
3362 if (s
->face
->underline_p
)
3364 unsigned long h
= 1;
3365 unsigned long dy
= s
->height
- h
;
3367 if (s
->face
->underline_defaulted_p
)
3368 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3373 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3374 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3375 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3377 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3381 /* Draw overline. */
3382 if (s
->face
->overline_p
)
3384 unsigned long dy
= 0, h
= 1;
3386 if (s
->face
->overline_color_defaulted_p
)
3387 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3392 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3393 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3394 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3396 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3400 /* Draw strike-through. */
3401 if (s
->face
->strike_through_p
)
3403 unsigned long h
= 1;
3404 unsigned long dy
= (s
->height
- h
) / 2;
3406 if (s
->face
->strike_through_color_defaulted_p
)
3407 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3412 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3413 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3414 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3416 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3420 /* Draw relief if not yet drawn. */
3421 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3422 x_draw_glyph_string_box (s
);
3425 /* Reset clipping. */
3426 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3429 /* Shift display to make room for inserted glyphs. */
3432 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3434 int x
, y
, width
, height
, shift_by
;
3436 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3437 x
, y
, width
, height
,
3441 /* Delete N glyphs at the nominal cursor position. Not implemented
3452 /* Clear entire frame. If updating_frame is non-null, clear that
3453 frame. Otherwise clear the selected frame. */
3463 f
= SELECTED_FRAME ();
3465 /* Clearing the frame will erase any cursor, so mark them all as no
3467 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3468 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3469 output_cursor
.x
= -1;
3471 /* We don't set the output cursor here because there will always
3472 follow an explicit cursor_to. */
3474 mac_clear_window (f
);
3476 /* We have to clear the scroll bars, too. If we have changed
3477 colors or something like that, then they should be notified. */
3478 x_scroll_bar_clear (f
);
3480 XFlush (FRAME_MAC_DISPLAY (f
));
3486 /* Invert the middle quarter of the frame for .15 sec. */
3488 /* We use the select system call to do the waiting, so we have to make
3489 sure it's available. If it isn't, we just won't do visual bells. */
3491 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3494 /* Subtract the `struct timeval' values X and Y, storing the result in
3495 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3498 timeval_subtract (result
, x
, y
)
3499 struct timeval
*result
, x
, y
;
3501 /* Perform the carry for the later subtraction by updating y. This
3502 is safer because on some systems the tv_sec member is unsigned. */
3503 if (x
.tv_usec
< y
.tv_usec
)
3505 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3506 y
.tv_usec
-= 1000000 * nsec
;
3510 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3512 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3513 y
.tv_usec
+= 1000000 * nsec
;
3517 /* Compute the time remaining to wait. tv_usec is certainly
3519 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3520 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3522 /* Return indication of whether the result should be considered
3524 return x
.tv_sec
< y
.tv_sec
;
3531 /* Get the height not including a menu bar widget. */
3532 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3533 /* Height of each line to flash. */
3534 int flash_height
= FRAME_LINE_HEIGHT (f
);
3535 /* These will be the left and right margins of the rectangles. */
3536 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3537 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3541 /* Don't flash the area between a scroll bar and the frame
3542 edge it is next to. */
3543 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3545 case vertical_scroll_bar_left
:
3546 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3549 case vertical_scroll_bar_right
:
3550 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3557 width
= flash_right
- flash_left
;
3561 /* If window is tall, flash top and bottom line. */
3562 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3564 mac_invert_rectangle (f
, flash_left
,
3565 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3566 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3567 width
, flash_height
);
3568 mac_invert_rectangle (f
, flash_left
,
3569 (height
- flash_height
3570 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3571 width
, flash_height
);
3574 /* If it is short, flash it all. */
3575 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3576 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3581 struct timeval wakeup
;
3583 EMACS_GET_TIME (wakeup
);
3585 /* Compute time to wait until, propagating carry from usecs. */
3586 wakeup
.tv_usec
+= 150000;
3587 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3588 wakeup
.tv_usec
%= 1000000;
3590 /* Keep waiting until past the time wakeup or any input gets
3592 while (! detect_input_pending ())
3594 struct timeval current
;
3595 struct timeval timeout
;
3597 EMACS_GET_TIME (current
);
3599 /* Break if result would be negative. */
3600 if (timeval_subtract (¤t
, wakeup
, current
))
3603 /* How long `select' should wait. */
3605 timeout
.tv_usec
= 10000;
3607 /* Try to wait that long--but we might wake up sooner. */
3608 select (0, NULL
, NULL
, NULL
, &timeout
);
3612 /* If window is tall, flash top and bottom line. */
3613 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3615 mac_invert_rectangle (f
, flash_left
,
3616 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3617 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3618 width
, flash_height
);
3619 mac_invert_rectangle (f
, flash_left
,
3620 (height
- flash_height
3621 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3622 width
, flash_height
);
3625 /* If it is short, flash it all. */
3626 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3627 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3634 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3637 /* Make audible bell. */
3642 struct frame
*f
= SELECTED_FRAME ();
3644 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3652 XFlush (FRAME_MAC_DISPLAY (f
));
3658 /* Specify how many text lines, from the top of the window,
3659 should be affected by insert-lines and delete-lines operations.
3660 This, and those operations, are used only within an update
3661 that is bounded by calls to x_update_begin and x_update_end. */
3664 XTset_terminal_window (n
)
3667 /* This function intentionally left blank. */
3672 /***********************************************************************
3674 ***********************************************************************/
3676 /* Perform an insert-lines or delete-lines operation, inserting N
3677 lines or deleting -N lines at vertical position VPOS. */
3680 x_ins_del_lines (vpos
, n
)
3687 /* Scroll part of the display as described by RUN. */
3690 x_scroll_run (w
, run
)
3694 struct frame
*f
= XFRAME (w
->frame
);
3695 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3697 /* Get frame-relative bounding box of the text display area of W,
3698 without mode lines. Include in this box the left and right
3700 window_box (w
, -1, &x
, &y
, &width
, &height
);
3702 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3703 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3704 bottom_y
= y
+ height
;
3708 /* Scrolling up. Make sure we don't copy part of the mode
3709 line at the bottom. */
3710 if (from_y
+ run
->height
> bottom_y
)
3711 height
= bottom_y
- from_y
;
3713 height
= run
->height
;
3717 /* Scolling down. Make sure we don't copy over the mode line.
3719 if (to_y
+ run
->height
> bottom_y
)
3720 height
= bottom_y
- to_y
;
3722 height
= run
->height
;
3727 /* Cursor off. Will be switched on again in x_update_window_end. */
3731 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3741 /***********************************************************************
3743 ***********************************************************************/
3751 ControlRef root_control
;
3754 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3756 ActivateControl (root_control
);
3758 x_update_cursor (f
, 1);
3762 frame_unhighlight (f
)
3766 ControlRef root_control
;
3769 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3771 DeactivateControl (root_control
);
3773 x_update_cursor (f
, 1);
3776 /* The focus has changed. Update the frames as necessary to reflect
3777 the new situation. Note that we can't change the selected frame
3778 here, because the Lisp code we are interrupting might become confused.
3779 Each event gets marked with the frame in which it occurred, so the
3780 Lisp code can tell when the switch took place by examining the events. */
3783 x_new_focus_frame (dpyinfo
, frame
)
3784 struct x_display_info
*dpyinfo
;
3785 struct frame
*frame
;
3787 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3789 if (frame
!= dpyinfo
->x_focus_frame
)
3791 /* Set this before calling other routines, so that they see
3792 the correct value of x_focus_frame. */
3793 dpyinfo
->x_focus_frame
= frame
;
3795 if (old_focus
&& old_focus
->auto_lower
)
3796 x_lower_frame (old_focus
);
3799 selected_frame
= frame
;
3800 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3802 Fselect_window (selected_frame
->selected_window
, Qnil
);
3803 choose_minibuf_frame ();
3806 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3807 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3809 pending_autoraise_frame
= 0;
3812 x_frame_rehighlight (dpyinfo
);
3815 /* Handle FocusIn and FocusOut state changes for FRAME.
3816 If FRAME has focus and there exists more than one frame, puts
3817 a FOCUS_IN_EVENT into *BUFP. */
3820 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3822 struct mac_display_info
*dpyinfo
;
3823 struct frame
*frame
;
3824 struct input_event
*bufp
;
3826 if (type
== activeFlag
)
3828 if (dpyinfo
->x_focus_event_frame
!= frame
)
3830 x_new_focus_frame (dpyinfo
, frame
);
3831 dpyinfo
->x_focus_event_frame
= frame
;
3833 /* Don't stop displaying the initial startup message
3834 for a switch-frame event we don't need. */
3835 if (GC_NILP (Vterminal_frame
)
3836 && GC_CONSP (Vframe_list
)
3837 && !GC_NILP (XCDR (Vframe_list
)))
3839 bufp
->kind
= FOCUS_IN_EVENT
;
3840 XSETFRAME (bufp
->frame_or_window
, frame
);
3846 if (dpyinfo
->x_focus_event_frame
== frame
)
3848 dpyinfo
->x_focus_event_frame
= 0;
3849 x_new_focus_frame (dpyinfo
, 0);
3854 /* The focus may have changed. Figure out if it is a real focus change,
3855 by checking both FocusIn/Out and Enter/LeaveNotify events.
3857 Returns FOCUS_IN_EVENT event in *BUFP. */
3860 x_detect_focus_change (dpyinfo
, event
, bufp
)
3861 struct mac_display_info
*dpyinfo
;
3863 struct input_event
*bufp
;
3865 struct frame
*frame
;
3867 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3871 /* On Mac, this is only called from focus events, so no switch needed. */
3872 mac_focus_changed ((event
->modifiers
& activeFlag
),
3873 dpyinfo
, frame
, bufp
);
3877 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3880 x_mouse_leave (dpyinfo
)
3881 struct x_display_info
*dpyinfo
;
3883 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3886 /* The focus has changed, or we have redirected a frame's focus to
3887 another frame (this happens when a frame uses a surrogate
3888 mini-buffer frame). Shift the highlight as appropriate.
3890 The FRAME argument doesn't necessarily have anything to do with which
3891 frame is being highlighted or un-highlighted; we only use it to find
3892 the appropriate X display info. */
3895 XTframe_rehighlight (frame
)
3896 struct frame
*frame
;
3898 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3902 x_frame_rehighlight (dpyinfo
)
3903 struct x_display_info
*dpyinfo
;
3905 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3907 if (dpyinfo
->x_focus_frame
)
3909 dpyinfo
->x_highlight_frame
3910 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3911 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3912 : dpyinfo
->x_focus_frame
);
3913 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3915 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3916 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3920 dpyinfo
->x_highlight_frame
= 0;
3922 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3925 frame_unhighlight (old_highlight
);
3926 if (dpyinfo
->x_highlight_frame
)
3927 frame_highlight (dpyinfo
->x_highlight_frame
);
3933 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3935 #if 0 /* MAC_TODO */
3936 /* Initialize mode_switch_bit and modifier_meaning. */
3938 x_find_modifier_meanings (dpyinfo
)
3939 struct x_display_info
*dpyinfo
;
3941 int min_code
, max_code
;
3944 XModifierKeymap
*mods
;
3946 dpyinfo
->meta_mod_mask
= 0;
3947 dpyinfo
->shift_lock_mask
= 0;
3948 dpyinfo
->alt_mod_mask
= 0;
3949 dpyinfo
->super_mod_mask
= 0;
3950 dpyinfo
->hyper_mod_mask
= 0;
3953 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3955 min_code
= dpyinfo
->display
->min_keycode
;
3956 max_code
= dpyinfo
->display
->max_keycode
;
3959 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3960 min_code
, max_code
- min_code
+ 1,
3962 mods
= XGetModifierMapping (dpyinfo
->display
);
3964 /* Scan the modifier table to see which modifier bits the Meta and
3965 Alt keysyms are on. */
3967 int row
, col
; /* The row and column in the modifier table. */
3969 for (row
= 3; row
< 8; row
++)
3970 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3973 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3975 /* Zeroes are used for filler. Skip them. */
3979 /* Are any of this keycode's keysyms a meta key? */
3983 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3985 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3991 dpyinfo
->meta_mod_mask
|= (1 << row
);
3996 dpyinfo
->alt_mod_mask
|= (1 << row
);
4001 dpyinfo
->hyper_mod_mask
|= (1 << row
);
4006 dpyinfo
->super_mod_mask
|= (1 << row
);
4010 /* Ignore this if it's not on the lock modifier. */
4011 if ((1 << row
) == LockMask
)
4012 dpyinfo
->shift_lock_mask
= LockMask
;
4020 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
4021 if (! dpyinfo
->meta_mod_mask
)
4023 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
4024 dpyinfo
->alt_mod_mask
= 0;
4027 /* If some keys are both alt and meta,
4028 make them just meta, not alt. */
4029 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
4031 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4034 XFree ((char *) syms
);
4035 XFreeModifiermap (mods
);
4038 #endif /* MAC_TODO */
4040 /* Convert between the modifier bits X uses and the modifier bits
4044 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4045 struct x_display_info
*dpyinfo
;
4046 unsigned short state
;
4048 return (((state
& shiftKey
) ? shift_modifier
: 0)
4049 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4050 | ((state
& cmdKey
) ? meta_modifier
: 0)
4051 | ((state
& optionKey
) ? alt_modifier
: 0));
4054 #if 0 /* MAC_TODO */
4055 static unsigned short
4056 x_emacs_to_x_modifiers (dpyinfo
, state
)
4057 struct x_display_info
*dpyinfo
;
4060 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4061 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4062 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4063 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4064 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4065 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4067 #endif /* MAC_TODO */
4069 /* Convert a keysym to its name. */
4072 x_get_keysym_name (keysym
)
4079 value
= XKeysymToString (keysym
);
4090 /* Function to report a mouse movement to the mainstream Emacs code.
4091 The input handler calls this.
4093 We have received a mouse movement event, which is given in *event.
4094 If the mouse is over a different glyph than it was last time, tell
4095 the mainstream emacs code by setting mouse_moved. If not, ask for
4096 another motion event, so we can check again the next time it moves. */
4098 static Point last_mouse_motion_position
;
4099 static Lisp_Object last_mouse_motion_frame
;
4102 note_mouse_movement (frame
, pos
)
4106 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4107 #if TARGET_API_MAC_CARBON
4111 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4112 last_mouse_motion_position
= *pos
;
4113 XSETFRAME (last_mouse_motion_frame
, frame
);
4115 #if TARGET_API_MAC_CARBON
4116 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4118 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4121 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4122 /* This case corresponds to LeaveNotify in X11. */
4124 /* If we move outside the frame, then we're certainly no
4125 longer on any text in the frame. */
4126 clear_mouse_face (dpyinfo
);
4127 dpyinfo
->mouse_face_mouse_frame
= 0;
4128 if (!dpyinfo
->grabbed
)
4129 rif
->define_frame_cursor (frame
,
4130 frame
->output_data
.mac
->nontext_cursor
);
4134 /* Has the mouse moved off the glyph it was on at the last sighting? */
4135 if (frame
!= last_mouse_glyph_frame
4136 || !PtInRect (*pos
, &last_mouse_glyph
))
4138 frame
->mouse_moved
= 1;
4139 last_mouse_scroll_bar
= Qnil
;
4140 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4141 /* Remember which glyph we're now on. */
4142 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4143 last_mouse_glyph_frame
= frame
;
4151 /************************************************************************
4153 ************************************************************************/
4155 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4158 redo_mouse_highlight ()
4160 if (!NILP (last_mouse_motion_frame
)
4161 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4162 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4163 last_mouse_motion_position
.h
,
4164 last_mouse_motion_position
.v
);
4168 static struct frame
*
4169 mac_focus_frame (dpyinfo
)
4170 struct mac_display_info
*dpyinfo
;
4172 if (dpyinfo
->x_focus_frame
)
4173 return dpyinfo
->x_focus_frame
;
4175 /* Mac version may get events, such as a menu bar click, even when
4176 all the frames are invisible. In this case, we regard the
4177 event came to the selected frame. */
4178 return SELECTED_FRAME ();
4182 /* Return the current position of the mouse.
4183 *FP should be a frame which indicates which display to ask about.
4185 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4186 and *PART to the frame, window, and scroll bar part that the mouse
4187 is over. Set *X and *Y to the portion and whole of the mouse's
4188 position on the scroll bar.
4190 If the mouse movement started elsewhere, set *FP to the frame the
4191 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4194 Set *TIME to the server time-stamp for the time at which the mouse
4195 was at this position.
4197 Don't store anything if we don't have a valid set of values to report.
4199 This clears the mouse_moved flag, so we can wait for the next mouse
4203 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4206 Lisp_Object
*bar_window
;
4207 enum scroll_bar_part
*part
;
4209 unsigned long *time
;
4215 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4216 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4219 Lisp_Object frame
, tail
;
4221 /* Clear the mouse-moved flag for every frame on this display. */
4222 FOR_EACH_FRAME (tail
, frame
)
4223 XFRAME (frame
)->mouse_moved
= 0;
4225 last_mouse_scroll_bar
= Qnil
;
4227 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4228 && FRAME_LIVE_P (last_mouse_frame
))
4229 f1
= last_mouse_frame
;
4231 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4235 /* Ok, we found a frame. Store all the values.
4236 last_mouse_glyph is a rectangle used to reduce the
4237 generation of mouse events. To not miss any motion
4238 events, we must divide the frame into rectangles of the
4239 size of the smallest character that could be displayed
4240 on it, i.e. into the same rectangles that matrices on
4241 the frame are divided into. */
4244 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4245 GetMouse (&mouse_pos
);
4246 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4248 last_mouse_glyph_frame
= f1
;
4253 XSETINT (*x
, mouse_pos
.h
);
4254 XSETINT (*y
, mouse_pos
.v
);
4255 *time
= last_mouse_movement_time
;
4263 /************************************************************************
4265 ************************************************************************/
4267 #ifdef USE_TOOLKIT_SCROLL_BARS
4269 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4270 static OSStatus install_scroll_bar_timer
P_ ((void));
4271 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4272 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4273 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4274 struct input_event
*));
4275 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4277 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4279 struct input_event
*));
4280 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4281 struct input_event
*));
4282 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4283 Point
, struct input_event
*));
4284 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4287 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4289 static int last_scroll_bar_part
;
4291 static EventLoopTimerRef scroll_bar_timer
;
4293 static int scroll_bar_timer_event_posted_p
;
4295 #define SCROLL_BAR_FIRST_DELAY 0.5
4296 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4299 scroll_bar_timer_callback (timer
, data
)
4300 EventLoopTimerRef timer
;
4303 EventRef event
= NULL
;
4306 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4307 kEventAttributeNone
, &event
);
4312 GetMouse (&mouse_pos
);
4313 LocalToGlobal (&mouse_pos
);
4314 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4315 sizeof (Point
), &mouse_pos
);
4319 UInt32 modifiers
= GetCurrentKeyModifiers ();
4321 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4322 sizeof (UInt32
), &modifiers
);
4325 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4326 kEventPriorityStandard
);
4328 scroll_bar_timer_event_posted_p
= 1;
4331 ReleaseEvent (event
);
4335 install_scroll_bar_timer ()
4337 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4339 if (scroll_bar_timer_callbackUPP
== NULL
)
4340 scroll_bar_timer_callbackUPP
=
4341 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4343 if (scroll_bar_timer
== NULL
)
4344 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4345 kEventDurationForever as delays. */
4347 InstallEventLoopTimer (GetCurrentEventLoop (),
4348 kEventDurationForever
, kEventDurationForever
,
4349 scroll_bar_timer_callbackUPP
, NULL
,
4354 set_scroll_bar_timer (delay
)
4355 EventTimerInterval delay
;
4357 if (scroll_bar_timer
== NULL
)
4358 install_scroll_bar_timer ();
4360 scroll_bar_timer_event_posted_p
= 0;
4362 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4366 control_part_code_to_scroll_bar_part (part_code
)
4367 ControlPartCode part_code
;
4371 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4372 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4373 case kControlPageUpPart
: return scroll_bar_above_handle
;
4374 case kControlPageDownPart
: return scroll_bar_below_handle
;
4375 case kControlIndicatorPart
: return scroll_bar_handle
;
4382 construct_scroll_bar_click (bar
, part
, bufp
)
4383 struct scroll_bar
*bar
;
4385 struct input_event
*bufp
;
4387 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4388 bufp
->frame_or_window
= bar
->window
;
4392 XSETINT (bufp
->x
, 0);
4393 XSETINT (bufp
->y
, 0);
4394 bufp
->modifiers
= 0;
4398 get_control_part_bounds (ch
, part_code
, rect
)
4400 ControlPartCode part_code
;
4403 RgnHandle region
= NewRgn ();
4406 err
= GetControlRegion (ch
, part_code
, region
);
4408 GetRegionBounds (region
, rect
);
4409 DisposeRgn (region
);
4415 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4416 struct scroll_bar
*bar
;
4417 ControlPartCode part_code
;
4418 struct input_event
*bufp
;
4420 int part
= control_part_code_to_scroll_bar_part (part_code
);
4425 if (part
!= scroll_bar_handle
)
4427 construct_scroll_bar_click (bar
, part
, bufp
);
4428 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4429 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4432 last_scroll_bar_part
= part
;
4433 bar
->dragging
= Qnil
;
4434 tracked_scroll_bar
= bar
;
4438 x_scroll_bar_handle_release (bar
, bufp
)
4439 struct scroll_bar
*bar
;
4440 struct input_event
*bufp
;
4442 if (last_scroll_bar_part
!= scroll_bar_handle
4443 || !GC_NILP (bar
->dragging
))
4444 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4446 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4447 set_scroll_bar_timer (kEventDurationForever
);
4449 last_scroll_bar_part
= -1;
4450 bar
->dragging
= Qnil
;
4451 tracked_scroll_bar
= NULL
;
4455 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4457 struct scroll_bar
*bar
;
4459 struct input_event
*bufp
;
4461 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4463 if (last_scroll_bar_part
== scroll_bar_handle
)
4468 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4469 kControlIndicatorPart
, &r
);
4471 if (GC_NILP (bar
->dragging
))
4472 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4474 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4475 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4476 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4481 if (top
> top_range
)
4484 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4485 XSETINT (bufp
->x
, top
);
4486 XSETINT (bufp
->y
, top_range
);
4490 ControlPartCode part_code
;
4491 int unhilite_p
= 0, part
;
4493 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4497 part
= control_part_code_to_scroll_bar_part (part_code
);
4499 switch (last_scroll_bar_part
)
4501 case scroll_bar_above_handle
:
4502 case scroll_bar_below_handle
:
4503 if (part
!= scroll_bar_above_handle
4504 && part
!= scroll_bar_below_handle
)
4508 case scroll_bar_up_arrow
:
4509 case scroll_bar_down_arrow
:
4510 if (part
!= scroll_bar_up_arrow
4511 && part
!= scroll_bar_down_arrow
)
4518 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4519 else if (part
!= last_scroll_bar_part
4520 || scroll_bar_timer_event_posted_p
)
4522 construct_scroll_bar_click (bar
, part
, bufp
);
4523 last_scroll_bar_part
= part
;
4524 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4525 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4530 /* Set the thumb size and position of scroll bar BAR. We are currently
4531 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4534 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4535 struct scroll_bar
*bar
;
4536 int portion
, position
, whole
;
4538 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4540 int value
, viewsize
, maximum
;
4542 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4543 value
= 0, viewsize
= 1, maximum
= 0;
4548 maximum
= max (0, whole
- portion
);
4553 SetControl32BitMinimum (ch
, 0);
4554 SetControl32BitMaximum (ch
, maximum
);
4555 SetControl32BitValue (ch
, value
);
4556 SetControlViewSize (ch
, viewsize
);
4561 #endif /* USE_TOOLKIT_SCROLL_BARS */
4565 /************************************************************************
4566 Scroll bars, general
4567 ************************************************************************/
4569 /* Create a scroll bar and return the scroll bar vector for it. W is
4570 the Emacs window on which to create the scroll bar. TOP, LEFT,
4571 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4574 static struct scroll_bar
*
4575 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4577 int top
, left
, width
, height
, disp_top
, disp_height
;
4579 struct frame
*f
= XFRAME (w
->frame
);
4580 struct scroll_bar
*bar
4581 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4589 r
.right
= left
+ width
;
4590 r
.bottom
= disp_top
+ disp_height
;
4592 #if TARGET_API_MAC_CARBON
4593 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4594 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4596 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4597 0, 0, 0, scrollBarProc
, (long) bar
);
4599 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4601 XSETWINDOW (bar
->window
, w
);
4602 XSETINT (bar
->top
, top
);
4603 XSETINT (bar
->left
, left
);
4604 XSETINT (bar
->width
, width
);
4605 XSETINT (bar
->height
, height
);
4606 XSETINT (bar
->start
, 0);
4607 XSETINT (bar
->end
, 0);
4608 bar
->dragging
= Qnil
;
4609 #ifdef USE_TOOLKIT_SCROLL_BARS
4610 bar
->track_top
= Qnil
;
4611 bar
->track_height
= Qnil
;
4614 /* Add bar to its frame's list of scroll bars. */
4615 bar
->next
= FRAME_SCROLL_BARS (f
);
4617 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4618 if (!NILP (bar
->next
))
4619 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4626 /* Draw BAR's handle in the proper position.
4628 If the handle is already drawn from START to END, don't bother
4629 redrawing it, unless REBUILD is non-zero; in that case, always
4630 redraw it. (REBUILD is handy for drawing the handle after expose
4633 Normally, we want to constrain the start and end of the handle to
4634 fit inside its rectangle, but if the user is dragging the scroll
4635 bar handle, we want to let them drag it down all the way, so that
4636 the bar's top is as far down as it goes; otherwise, there's no way
4637 to move to the very end of the buffer. */
4639 #ifndef USE_TOOLKIT_SCROLL_BARS
4642 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4643 struct scroll_bar
*bar
;
4647 int dragging
= ! NILP (bar
->dragging
);
4648 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4649 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4650 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4651 int length
= end
- start
;
4653 /* If the display is already accurate, do nothing. */
4655 && start
== XINT (bar
->start
)
4656 && end
== XINT (bar
->end
))
4661 /* Make sure the values are reasonable, and try to preserve the
4662 distance between start and end. */
4665 else if (start
> top_range
)
4667 end
= start
+ length
;
4671 else if (end
> top_range
&& ! dragging
)
4674 /* Store the adjusted setting in the scroll bar. */
4675 XSETINT (bar
->start
, start
);
4676 XSETINT (bar
->end
, end
);
4678 /* Clip the end position, just for display. */
4679 if (end
> top_range
)
4682 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4683 top positions, to make sure the handle is always at least that
4684 many pixels tall. */
4685 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4687 SetControlMinimum (ch
, 0);
4688 /* Don't inadvertently activate deactivated scroll bars */
4689 if (GetControlMaximum (ch
) != -1)
4690 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4692 SetControlValue (ch
, start
);
4693 #if TARGET_API_MAC_CARBON
4694 SetControlViewSize (ch
, end
- start
);
4700 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4702 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4706 x_scroll_bar_remove (bar
)
4707 struct scroll_bar
*bar
;
4709 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4713 /* Destroy the Mac scroll bar control */
4714 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4716 /* Disassociate this scroll bar from its window. */
4717 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4723 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4724 that we are displaying PORTION characters out of a total of WHOLE
4725 characters, starting at POSITION. If WINDOW has no scroll bar,
4729 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4731 int portion
, whole
, position
;
4733 struct frame
*f
= XFRAME (w
->frame
);
4734 struct scroll_bar
*bar
;
4735 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4736 int window_y
, window_height
;
4738 /* Get window dimensions. */
4739 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4741 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4742 height
= window_height
;
4744 /* Compute the left edge of the scroll bar area. */
4745 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4747 /* Compute the width of the scroll bar which might be less than
4748 the width of the area reserved for the scroll bar. */
4749 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4750 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4754 /* Compute the left edge of the scroll bar. */
4755 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4758 sb_left
= left
+ width
- sb_width
;
4760 /* Adjustments according to Inside Macintosh to make it look nice */
4762 disp_height
= height
;
4768 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4774 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4777 /* Does the scroll bar exist yet? */
4778 if (NILP (w
->vertical_scroll_bar
))
4781 mac_clear_area (f
, left
, top
, width
, height
);
4783 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4785 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4789 /* It may just need to be moved and resized. */
4792 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4793 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4797 /* If already correctly positioned, do nothing. */
4798 if (!(XINT (bar
->left
) == sb_left
4799 && XINT (bar
->top
) == top
4800 && XINT (bar
->width
) == sb_width
4801 && XINT (bar
->height
) == height
))
4803 /* Since toolkit scroll bars are smaller than the space reserved
4804 for them on the frame, we have to clear "under" them. */
4805 mac_clear_area (f
, left
, top
, width
, height
);
4808 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4809 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4811 if (sb_width
< disp_height
)
4814 /* Remember new settings. */
4815 XSETINT (bar
->left
, sb_left
);
4816 XSETINT (bar
->top
, top
);
4817 XSETINT (bar
->width
, sb_width
);
4818 XSETINT (bar
->height
, height
);
4819 #ifdef USE_TOOLKIT_SCROLL_BARS
4820 bar
->track_top
= Qnil
;
4821 bar
->track_height
= Qnil
;
4828 #ifdef USE_TOOLKIT_SCROLL_BARS
4829 if (NILP (bar
->track_top
))
4831 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4836 SetControl32BitMinimum (ch
, 0);
4837 SetControl32BitMaximum (ch
, 1);
4838 SetControlViewSize (ch
, 1);
4840 /* Move the scroll bar thumb to the top. */
4841 SetControl32BitValue (ch
, 0);
4842 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4844 /* Move the scroll bar thumb to the bottom. */
4845 SetControl32BitValue (ch
, 1);
4846 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4848 UnionRect (&r0
, &r1
, &r0
);
4849 XSETINT (bar
->track_top
, r0
.top
);
4850 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4855 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4856 #else /* not USE_TOOLKIT_SCROLL_BARS */
4857 /* Set the scroll bar's current state, unless we're currently being
4859 if (NILP (bar
->dragging
))
4861 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4864 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4867 int start
= ((double) position
* top_range
) / whole
;
4868 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4869 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4872 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4876 /* The following three hooks are used when we're doing a thorough
4877 redisplay of the frame. We don't explicitly know which scroll bars
4878 are going to be deleted, because keeping track of when windows go
4879 away is a real pain - "Can you say set-window-configuration, boys
4880 and girls?" Instead, we just assert at the beginning of redisplay
4881 that *all* scroll bars are to be removed, and then save a scroll bar
4882 from the fiery pit when we actually redisplay its window. */
4884 /* Arrange for all scroll bars on FRAME to be removed at the next call
4885 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4886 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4889 XTcondemn_scroll_bars (frame
)
4892 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4893 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4896 bar
= FRAME_SCROLL_BARS (frame
);
4897 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4898 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4899 XSCROLL_BAR (bar
)->prev
= Qnil
;
4900 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4901 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4902 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4907 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4908 Note that WINDOW isn't necessarily condemned at all. */
4911 XTredeem_scroll_bar (window
)
4912 struct window
*window
;
4914 struct scroll_bar
*bar
;
4917 /* We can't redeem this window's scroll bar if it doesn't have one. */
4918 if (NILP (window
->vertical_scroll_bar
))
4921 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4923 /* Unlink it from the condemned list. */
4924 f
= XFRAME (WINDOW_FRAME (window
));
4925 if (NILP (bar
->prev
))
4927 /* If the prev pointer is nil, it must be the first in one of
4929 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4930 /* It's not condemned. Everything's fine. */
4932 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4933 window
->vertical_scroll_bar
))
4934 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4936 /* If its prev pointer is nil, it must be at the front of
4937 one or the other! */
4941 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4943 if (! NILP (bar
->next
))
4944 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4946 bar
->next
= FRAME_SCROLL_BARS (f
);
4948 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4949 if (! NILP (bar
->next
))
4950 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4953 /* Remove all scroll bars on FRAME that haven't been saved since the
4954 last call to `*condemn_scroll_bars_hook'. */
4957 XTjudge_scroll_bars (f
)
4960 Lisp_Object bar
, next
;
4962 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4964 /* Clear out the condemned list now so we won't try to process any
4965 more events on the hapless scroll bars. */
4966 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4968 for (; ! NILP (bar
); bar
= next
)
4970 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4972 x_scroll_bar_remove (b
);
4975 b
->next
= b
->prev
= Qnil
;
4978 /* Now there should be no references to the condemned scroll bars,
4979 and they should get garbage-collected. */
4983 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4984 is set to something other than NO_EVENT, it is enqueued.
4986 This may be called from a signal handler, so we have to ignore GC
4990 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4991 struct scroll_bar
*bar
;
4992 ControlPartCode part_code
;
4994 struct input_event
*bufp
;
4996 int win_y
, top_range
;
4998 if (! GC_WINDOWP (bar
->window
))
5001 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
5002 bufp
->frame_or_window
= bar
->window
;
5005 bar
->dragging
= Qnil
;
5009 case kControlUpButtonPart
:
5010 bufp
->part
= scroll_bar_up_arrow
;
5012 case kControlDownButtonPart
:
5013 bufp
->part
= scroll_bar_down_arrow
;
5015 case kControlPageUpPart
:
5016 bufp
->part
= scroll_bar_above_handle
;
5018 case kControlPageDownPart
:
5019 bufp
->part
= scroll_bar_below_handle
;
5021 #if TARGET_API_MAC_CARBON
5024 case kControlIndicatorPart
:
5026 if (er
->what
== mouseDown
)
5027 bar
->dragging
= make_number (0);
5028 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5029 bufp
->part
= scroll_bar_handle
;
5033 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5034 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5036 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5040 if (! NILP (bar
->dragging
))
5041 win_y
-= XINT (bar
->dragging
);
5045 if (win_y
> top_range
)
5048 XSETINT (bufp
->x
, win_y
);
5049 XSETINT (bufp
->y
, top_range
);
5052 #ifndef USE_TOOLKIT_SCROLL_BARS
5054 /* Handle some mouse motion while someone is dragging the scroll bar.
5056 This may be called from a signal handler, so we have to ignore GC
5060 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5061 struct scroll_bar
*bar
;
5065 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5067 last_mouse_movement_time
= t
;
5070 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5072 /* If we're dragging the bar, display it. */
5073 if (! GC_NILP (bar
->dragging
))
5075 /* Where should the handle be now? */
5076 int new_start
= y_pos
- 24;
5078 if (new_start
!= XINT (bar
->start
))
5080 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5082 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5087 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5089 /* Return information to the user about the current position of the mouse
5090 on the scroll bar. */
5093 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5095 Lisp_Object
*bar_window
;
5096 enum scroll_bar_part
*part
;
5098 unsigned long *time
;
5100 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5101 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5102 #if TARGET_API_MAC_CARBON
5103 WindowPtr wp
= GetControlOwner (ch
);
5105 WindowPtr wp
= (*ch
)->contrlOwner
;
5108 struct frame
*f
= mac_window_to_frame (wp
);
5109 int win_y
, top_range
;
5111 SetPortWindowPort (wp
);
5113 GetMouse (&mouse_pos
);
5115 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5116 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5118 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5122 if (! NILP (bar
->dragging
))
5123 win_y
-= XINT (bar
->dragging
);
5127 if (win_y
> top_range
)
5131 *bar_window
= bar
->window
;
5133 if (! NILP (bar
->dragging
))
5134 *part
= scroll_bar_handle
;
5135 else if (win_y
< XINT (bar
->start
))
5136 *part
= scroll_bar_above_handle
;
5137 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5138 *part
= scroll_bar_handle
;
5140 *part
= scroll_bar_below_handle
;
5142 XSETINT (*x
, win_y
);
5143 XSETINT (*y
, top_range
);
5146 last_mouse_scroll_bar
= Qnil
;
5148 *time
= last_mouse_movement_time
;
5152 /* The screen has been cleared so we may have changed foreground or
5153 background colors, and the scroll bars may need to be redrawn.
5154 Clear out the scroll bars, and ask for expose events, so we can
5158 x_scroll_bar_clear (f
)
5161 XTcondemn_scroll_bars (f
);
5162 XTjudge_scroll_bars (f
);
5166 /***********************************************************************
5168 ***********************************************************************/
5170 /* Set clipping for output in glyph row ROW. W is the window in which
5171 we operate. GC is the graphics context to set clipping in.
5173 ROW may be a text row or, e.g., a mode line. Text rows must be
5174 clipped to the interior of the window dedicated to text display,
5175 mode lines must be clipped to the whole window. */
5178 x_clip_to_row (w
, row
, area
, gc
)
5180 struct glyph_row
*row
;
5184 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5186 int window_x
, window_y
, window_width
;
5188 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5190 clip_rect
.left
= window_x
;
5191 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5192 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5193 clip_rect
.right
= clip_rect
.left
+ window_width
;
5194 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5196 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5200 /* Draw a hollow box cursor on window W in glyph row ROW. */
5203 x_draw_hollow_cursor (w
, row
)
5205 struct glyph_row
*row
;
5207 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5208 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5209 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5212 struct glyph
*cursor_glyph
;
5215 /* Get the glyph the cursor is on. If we can't tell because
5216 the current matrix is invalid or such, give up. */
5217 cursor_glyph
= get_phys_cursor_glyph (w
);
5218 if (cursor_glyph
== NULL
)
5221 /* Compute frame-relative coordinates for phys cursor. */
5222 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5223 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5224 wd
= w
->phys_cursor_width
;
5226 /* The foreground of cursor_gc is typically the same as the normal
5227 background color, which can cause the cursor box to be invisible. */
5228 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5229 if (dpyinfo
->scratch_cursor_gc
)
5230 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5232 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5233 GCForeground
, &xgcv
);
5234 gc
= dpyinfo
->scratch_cursor_gc
;
5236 /* Set clipping, draw the rectangle, and reset clipping again. */
5237 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5238 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5239 mac_reset_clip_rectangles (dpy
, gc
);
5243 /* Draw a bar cursor on window W in glyph row ROW.
5245 Implementation note: One would like to draw a bar cursor with an
5246 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5247 Unfortunately, I didn't find a font yet that has this property set.
5251 x_draw_bar_cursor (w
, row
, width
, kind
)
5253 struct glyph_row
*row
;
5255 enum text_cursor_kinds kind
;
5257 struct frame
*f
= XFRAME (w
->frame
);
5258 struct glyph
*cursor_glyph
;
5260 /* If cursor is out of bounds, don't draw garbage. This can happen
5261 in mini-buffer windows when switching between echo area glyphs
5263 cursor_glyph
= get_phys_cursor_glyph (w
);
5264 if (cursor_glyph
== NULL
)
5267 /* If on an image, draw like a normal cursor. That's usually better
5268 visible than drawing a bar, esp. if the image is large so that
5269 the bar might not be in the window. */
5270 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5272 struct glyph_row
*row
;
5273 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5274 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5278 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5279 Window window
= FRAME_MAC_WINDOW (f
);
5280 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5281 unsigned long mask
= GCForeground
| GCBackground
;
5282 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5285 /* If the glyph's background equals the color we normally draw
5286 the bar cursor in, the bar cursor in its normal color is
5287 invisible. Use the glyph's foreground color instead in this
5288 case, on the assumption that the glyph's colors are chosen so
5289 that the glyph is legible. */
5290 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5291 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5293 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5296 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5299 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5300 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5304 width
= FRAME_CURSOR_WIDTH (f
);
5305 width
= min (cursor_glyph
->pixel_width
, width
);
5307 w
->phys_cursor_width
= width
;
5308 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5310 if (kind
== BAR_CURSOR
)
5311 mac_fill_rectangle (f
, gc
,
5312 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5313 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5314 width
, row
->height
);
5316 mac_fill_rectangle (f
, gc
,
5317 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5318 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5319 row
->height
- width
),
5320 cursor_glyph
->pixel_width
,
5323 mac_reset_clip_rectangles (dpy
, gc
);
5328 /* RIF: Define cursor CURSOR on frame F. */
5331 mac_define_frame_cursor (f
, cursor
)
5335 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5337 if (dpyinfo
->x_focus_frame
== f
)
5338 SetThemeCursor (cursor
);
5342 /* RIF: Clear area on frame F. */
5345 mac_clear_frame_area (f
, x
, y
, width
, height
)
5347 int x
, y
, width
, height
;
5349 mac_clear_area (f
, x
, y
, width
, height
);
5353 /* RIF: Draw cursor on window W. */
5356 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5358 struct glyph_row
*glyph_row
;
5360 int cursor_type
, cursor_width
;
5365 w
->phys_cursor_type
= cursor_type
;
5366 w
->phys_cursor_on_p
= 1;
5368 if (glyph_row
->exact_window_width_line_p
5369 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5371 glyph_row
->cursor_in_fringe_p
= 1;
5372 draw_fringe_bitmap (w
, glyph_row
, 0);
5375 switch (cursor_type
)
5377 case HOLLOW_BOX_CURSOR
:
5378 x_draw_hollow_cursor (w
, glyph_row
);
5381 case FILLED_BOX_CURSOR
:
5382 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5386 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5390 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5394 w
->phys_cursor_width
= 0;
5406 #if 0 /* MAC_TODO: no icon support yet. */
5408 x_bitmap_icon (f
, icon
)
5414 if (FRAME_W32_WINDOW (f
) == 0)
5418 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5419 else if (STRINGP (icon
))
5420 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5421 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5422 else if (SYMBOLP (icon
))
5426 if (EQ (icon
, intern ("application")))
5427 name
= (LPCTSTR
) IDI_APPLICATION
;
5428 else if (EQ (icon
, intern ("hand")))
5429 name
= (LPCTSTR
) IDI_HAND
;
5430 else if (EQ (icon
, intern ("question")))
5431 name
= (LPCTSTR
) IDI_QUESTION
;
5432 else if (EQ (icon
, intern ("exclamation")))
5433 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5434 else if (EQ (icon
, intern ("asterisk")))
5435 name
= (LPCTSTR
) IDI_ASTERISK
;
5436 else if (EQ (icon
, intern ("winlogo")))
5437 name
= (LPCTSTR
) IDI_WINLOGO
;
5441 hicon
= LoadIcon (NULL
, name
);
5449 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5454 #endif /* MAC_TODO */
5456 /************************************************************************
5458 ************************************************************************/
5460 /* Display Error Handling functions not used on W32. Listing them here
5461 helps diff stay in step when comparing w32term.c with xterm.c.
5463 x_error_catcher (display, error)
5464 x_catch_errors (dpy)
5465 x_catch_errors_unwind (old_val)
5466 x_check_errors (dpy, format)
5467 x_had_errors_p (dpy)
5468 x_clear_errors (dpy)
5469 x_uncatch_errors (dpy, count)
5471 x_connection_signal (signalnum)
5472 x_connection_closed (dpy, error_message)
5473 x_error_quitter (display, error)
5474 x_error_handler (display, error)
5475 x_io_error_quitter (display)
5480 /* Changing the font of the frame. */
5482 /* Give frame F the font named FONTNAME as its default font, and
5483 return the full name of that font. FONTNAME may be a wildcard
5484 pattern; in that case, we choose some font that fits the pattern.
5485 The return value shows which font we chose. */
5488 x_new_font (f
, fontname
)
5490 register char *fontname
;
5492 struct font_info
*fontp
5493 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5498 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5499 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5500 FRAME_FONTSET (f
) = -1;
5502 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5503 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5504 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5506 compute_fringe_widths (f
, 1);
5508 /* Compute the scroll bar width in character columns. */
5509 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5511 int wid
= FRAME_COLUMN_WIDTH (f
);
5512 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5513 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5517 int wid
= FRAME_COLUMN_WIDTH (f
);
5518 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5521 /* Now make the frame display the given font. */
5522 if (FRAME_MAC_WINDOW (f
) != 0)
5524 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5526 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5528 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5531 /* Don't change the size of a tip frame; there's no point in
5532 doing it because it's done in Fx_show_tip, and it leads to
5533 problems because the tip frame has no widget. */
5534 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5535 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5538 return build_string (fontp
->full_name
);
5541 /* Give frame F the fontset named FONTSETNAME as its default font, and
5542 return the full name of that fontset. FONTSETNAME may be a wildcard
5543 pattern; in that case, we choose some fontset that fits the pattern.
5544 The return value shows which fontset we chose. */
5547 x_new_fontset (f
, fontsetname
)
5551 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5557 if (FRAME_FONTSET (f
) == fontset
)
5558 /* This fontset is already set in frame F. There's nothing more
5560 return fontset_name (fontset
);
5562 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5564 if (!STRINGP (result
))
5565 /* Can't load ASCII font. */
5568 /* Since x_new_font doesn't update any fontset information, do it now. */
5569 FRAME_FONTSET (f
) = fontset
;
5571 return build_string (fontsetname
);
5575 /***********************************************************************
5576 TODO: W32 Input Methods
5577 ***********************************************************************/
5578 /* Listing missing functions from xterm.c helps diff stay in step.
5580 xim_destroy_callback (xim, client_data, call_data)
5581 xim_open_dpy (dpyinfo, resource_name)
5583 xim_instantiate_callback (display, client_data, call_data)
5584 xim_initialize (dpyinfo, resource_name)
5585 xim_close_dpy (dpyinfo)
5591 mac_get_window_bounds (f
, inner
, outer
)
5593 Rect
*inner
, *outer
;
5595 #if TARGET_API_MAC_CARBON
5596 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5597 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5598 #else /* not TARGET_API_MAC_CARBON */
5599 RgnHandle region
= NewRgn ();
5601 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5602 *inner
= (*region
)->rgnBBox
;
5603 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5604 *outer
= (*region
)->rgnBBox
;
5605 DisposeRgn (region
);
5606 #endif /* not TARGET_API_MAC_CARBON */
5611 /* Calculate the absolute position in frame F
5612 from its current recorded position values and gravity. */
5615 x_calc_absolute_position (f
)
5618 int width_diff
= 0, height_diff
= 0;
5619 int flags
= f
->size_hint_flags
;
5622 /* We have nothing to do if the current position
5623 is already for the top-left corner. */
5624 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5627 /* Find the offsets of the outside upper-left corner of
5628 the inner window, with respect to the outer window. */
5629 mac_get_window_bounds (f
, &inner
, &outer
);
5631 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5632 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5634 /* Treat negative positions as relative to the leftmost bottommost
5635 position that fits on the screen. */
5636 if (flags
& XNegative
)
5637 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5639 - FRAME_PIXEL_WIDTH (f
)
5642 if (flags
& YNegative
)
5643 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5645 - FRAME_PIXEL_HEIGHT (f
)
5648 /* The left_pos and top_pos
5649 are now relative to the top and left screen edges,
5650 so the flags should correspond. */
5651 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5654 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5655 to really change the position, and 0 when calling from
5656 x_make_frame_visible (in that case, XOFF and YOFF are the current
5657 position values). It is -1 when calling from x_set_frame_parameters,
5658 which means, do adjust for borders but don't change the gravity. */
5661 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5663 register int xoff
, yoff
;
5666 if (change_gravity
> 0)
5670 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5672 f
->size_hint_flags
|= XNegative
;
5674 f
->size_hint_flags
|= YNegative
;
5675 f
->win_gravity
= NorthWestGravity
;
5677 x_calc_absolute_position (f
);
5680 x_wm_set_size_hint (f
, (long) 0, 0);
5682 #if TARGET_API_MAC_CARBON
5683 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5684 /* If the title bar is completely outside the screen, adjust the
5686 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5687 kWindowConstrainMoveRegardlessOfFit
5688 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5689 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5692 Rect inner
, outer
, screen_rect
, dummy
;
5693 RgnHandle region
= NewRgn ();
5695 mac_get_window_bounds (f
, &inner
, &outer
);
5696 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5697 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5698 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5699 f
->top_pos
+ f
->y_pixels_diff
, false);
5701 /* If the title bar is completely outside the screen, adjust the
5702 position. The variable `outer' holds the title bar rectangle.
5703 The variable `inner' holds slightly smaller one than `outer',
5704 so that the calculation of overlapping may not become too
5706 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5707 outer
= (*region
)->rgnBBox
;
5708 DisposeRgn (region
);
5710 InsetRect (&inner
, 8, 8);
5711 screen_rect
= qd
.screenBits
.bounds
;
5712 screen_rect
.top
+= GetMBarHeight ();
5714 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5716 if (inner
.right
<= screen_rect
.left
)
5717 f
->left_pos
= screen_rect
.left
;
5718 else if (inner
.left
>= screen_rect
.right
)
5719 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5721 if (inner
.bottom
<= screen_rect
.top
)
5722 f
->top_pos
= screen_rect
.top
;
5723 else if (inner
.top
>= screen_rect
.bottom
)
5724 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5726 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5727 f
->top_pos
+ f
->y_pixels_diff
, false);
5735 /* Call this to change the size of frame F's x-window.
5736 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5737 for this size change and subsequent size changes.
5738 Otherwise we leave the window gravity unchanged. */
5741 x_set_window_size (f
, change_gravity
, cols
, rows
)
5746 int pixelwidth
, pixelheight
;
5750 check_frame_size (f
, &rows
, &cols
);
5751 f
->scroll_bar_actual_width
5752 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5754 compute_fringe_widths (f
, 0);
5756 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5757 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5759 f
->win_gravity
= NorthWestGravity
;
5760 x_wm_set_size_hint (f
, (long) 0, 0);
5762 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5763 #if TARGET_API_MAC_CARBON
5764 if (f
->output_data
.mac
->hourglass_control
)
5765 MoveControl (f
->output_data
.mac
->hourglass_control
,
5766 pixelwidth
- HOURGLASS_WIDTH
, 0);
5769 /* Now, strictly speaking, we can't be sure that this is accurate,
5770 but the window manager will get around to dealing with the size
5771 change request eventually, and we'll hear how it went when the
5772 ConfigureNotify event gets here.
5774 We could just not bother storing any of this information here,
5775 and let the ConfigureNotify event set everything up, but that
5776 might be kind of confusing to the Lisp code, since size changes
5777 wouldn't be reported in the frame parameters until some random
5778 point in the future when the ConfigureNotify event arrives.
5780 We pass 1 for DELAY since we can't run Lisp code inside of
5782 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5783 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5784 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5786 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5787 receive in the ConfigureNotify event; if we get what we asked
5788 for, then the event won't cause the screen to become garbaged, so
5789 we have to make sure to do it here. */
5790 SET_FRAME_GARBAGED (f
);
5792 XFlush (FRAME_X_DISPLAY (f
));
5794 /* If cursor was outside the new size, mark it as off. */
5795 mark_window_cursors_off (XWINDOW (f
->root_window
));
5797 /* Clear out any recollection of where the mouse highlighting was,
5798 since it might be in a place that's outside the new frame size.
5799 Actually checking whether it is outside is a pain in the neck,
5800 so don't try--just let the highlighting be done afresh with new size. */
5801 cancel_mouse_face (f
);
5806 /* Mouse warping. */
5808 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5811 x_set_mouse_position (f
, x
, y
)
5817 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5818 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5820 if (pix_x
< 0) pix_x
= 0;
5821 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5823 if (pix_y
< 0) pix_y
= 0;
5824 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5826 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5830 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5834 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5837 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5838 0, 0, 0, 0, pix_x
, pix_y
);
5843 /* focus shifting, raising and lowering. */
5846 x_focus_on_frame (f
)
5849 #if 0 /* This proves to be unpleasant. */
5853 /* I don't think that the ICCCM allows programs to do things like this
5854 without the interaction of the window manager. Whatever you end up
5855 doing with this code, do it to x_unfocus_frame too. */
5856 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5857 RevertToPointerRoot
, CurrentTime
);
5867 /* Raise frame F. */
5873 if (f
->async_visible
)
5876 BringToFront (FRAME_MAC_WINDOW (f
));
5881 /* Lower frame F. */
5887 if (f
->async_visible
)
5890 SendBehind (FRAME_MAC_WINDOW (f
), NULL
);
5896 XTframe_raise_lower (f
, raise_flag
)
5906 /* Change of visibility. */
5909 mac_handle_visibility_change (f
)
5912 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5913 int visible
= 0, iconified
= 0;
5914 struct input_event buf
;
5916 if (IsWindowVisible (wp
))
5917 if (IsWindowCollapsed (wp
))
5922 if (!f
->async_visible
&& visible
)
5926 /* wait_reading_process_output will notice this and update
5927 the frame's display structures. If we were made
5928 invisible, we should not set garbaged, because that stops
5929 redrawing on Update events. */
5930 SET_FRAME_GARBAGED (f
);
5933 buf
.kind
= DEICONIFY_EVENT
;
5934 XSETFRAME (buf
.frame_or_window
, f
);
5935 kbd_buffer_store_event (&buf
);
5937 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5938 /* Force a redisplay sooner or later to update the
5939 frame titles in case this is the second frame. */
5940 record_asynch_buffer_change ();
5942 else if (f
->async_visible
&& !visible
)
5946 buf
.kind
= ICONIFY_EVENT
;
5947 XSETFRAME (buf
.frame_or_window
, f
);
5948 kbd_buffer_store_event (&buf
);
5951 f
->async_visible
= visible
;
5952 f
->async_iconified
= iconified
;
5955 /* This tries to wait until the frame is really visible.
5956 However, if the window manager asks the user where to position
5957 the frame, this will return before the user finishes doing that.
5958 The frame will not actually be visible at that time,
5959 but it will become visible later when the window manager
5960 finishes with it. */
5963 x_make_frame_visible (f
)
5967 int original_top
, original_left
;
5971 if (! FRAME_VISIBLE_P (f
))
5973 /* We test FRAME_GARBAGED_P here to make sure we don't
5974 call x_set_offset a second time
5975 if we get to x_make_frame_visible a second time
5976 before the window gets really visible. */
5977 if (! FRAME_ICONIFIED_P (f
)
5978 && ! f
->output_data
.mac
->asked_for_visible
)
5979 #if TARGET_API_MAC_CARBON
5980 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5982 struct frame
*sf
= SELECTED_FRAME ();
5983 if (!FRAME_MAC_P (sf
))
5984 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5985 kWindowCenterOnMainScreen
);
5987 RepositionWindow (FRAME_MAC_WINDOW (f
),
5988 FRAME_MAC_WINDOW (sf
),
5989 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5990 kWindowCascadeStartAtParentWindowScreen
5992 kWindowCascadeOnParentWindowScreen
5995 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5999 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
6001 f
->output_data
.mac
->asked_for_visible
= 1;
6003 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
6004 ShowWindow (FRAME_MAC_WINDOW (f
));
6007 XFlush (FRAME_MAC_DISPLAY (f
));
6009 /* Synchronize to ensure Emacs knows the frame is visible
6010 before we do anything else. We do this loop with input not blocked
6011 so that incoming events are handled. */
6016 /* This must come after we set COUNT. */
6019 XSETFRAME (frame
, f
);
6021 /* Wait until the frame is visible. Process X events until a
6022 MapNotify event has been seen, or until we think we won't get a
6023 MapNotify at all.. */
6024 for (count
= input_signal_count
+ 10;
6025 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
6027 /* Force processing of queued events. */
6030 /* Machines that do polling rather than SIGIO have been
6031 observed to go into a busy-wait here. So we'll fake an
6032 alarm signal to let the handler know that there's something
6033 to be read. We used to raise a real alarm, but it seems
6034 that the handler isn't always enabled here. This is
6036 if (input_polling_used ())
6038 /* It could be confusing if a real alarm arrives while
6039 processing the fake one. Turn it off and let the
6040 handler reset it. */
6041 extern void poll_for_input_1
P_ ((void));
6042 int old_poll_suppress_count
= poll_suppress_count
;
6043 poll_suppress_count
= 1;
6044 poll_for_input_1 ();
6045 poll_suppress_count
= old_poll_suppress_count
;
6048 /* See if a MapNotify event has been processed. */
6049 FRAME_SAMPLE_VISIBILITY (f
);
6054 /* Change from mapped state to withdrawn state. */
6056 /* Make the frame visible (mapped and not iconified). */
6059 x_make_frame_invisible (f
)
6062 /* A deactivate event does not occur when the last visible frame is
6063 made invisible. So if we clear the highlight here, it will not
6064 be rehighlighted when it is made visible. */
6066 /* Don't keep the highlight on an invisible frame. */
6067 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6068 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6073 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6074 that the current position of the window is user-specified, rather than
6075 program-specified, so that when the window is mapped again, it will be
6076 placed at the same location, without forcing the user to position it
6077 by hand again (they have already done that once for this window.) */
6078 x_wm_set_size_hint (f
, (long) 0, 1);
6080 HideWindow (FRAME_MAC_WINDOW (f
));
6084 #if !USE_CARBON_EVENTS
6085 mac_handle_visibility_change (f
);
6089 /* Change window state from mapped to iconified. */
6097 /* A deactivate event does not occur when the last visible frame is
6098 iconified. So if we clear the highlight here, it will not be
6099 rehighlighted when it is deiconified. */
6101 /* Don't keep the highlight on an invisible frame. */
6102 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6103 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6106 if (f
->async_iconified
)
6111 FRAME_SAMPLE_VISIBILITY (f
);
6113 if (! FRAME_VISIBLE_P (f
))
6114 ShowWindow (FRAME_MAC_WINDOW (f
));
6116 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6121 error ("Can't notify window manager of iconification");
6123 #if !USE_CARBON_EVENTS
6124 mac_handle_visibility_change (f
);
6129 /* Free X resources of frame F. */
6132 x_free_frame_resources (f
)
6135 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6136 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6140 if (wp
!= tip_window
)
6141 remove_window_handler (wp
);
6144 if (wp
== tip_window
)
6145 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6146 closed' event. So we reset tip_window here. */
6149 free_frame_menubar (f
);
6151 if (FRAME_FACE_CACHE (f
))
6152 free_frame_faces (f
);
6156 if (FRAME_SIZE_HINTS (f
))
6157 xfree (FRAME_SIZE_HINTS (f
));
6159 xfree (f
->output_data
.mac
);
6160 f
->output_data
.mac
= NULL
;
6162 if (f
== dpyinfo
->x_focus_frame
)
6163 dpyinfo
->x_focus_frame
= 0;
6164 if (f
== dpyinfo
->x_focus_event_frame
)
6165 dpyinfo
->x_focus_event_frame
= 0;
6166 if (f
== dpyinfo
->x_highlight_frame
)
6167 dpyinfo
->x_highlight_frame
= 0;
6169 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6171 dpyinfo
->mouse_face_beg_row
6172 = dpyinfo
->mouse_face_beg_col
= -1;
6173 dpyinfo
->mouse_face_end_row
6174 = dpyinfo
->mouse_face_end_col
= -1;
6175 dpyinfo
->mouse_face_window
= Qnil
;
6176 dpyinfo
->mouse_face_deferred_gc
= 0;
6177 dpyinfo
->mouse_face_mouse_frame
= 0;
6184 /* Destroy the X window of frame F. */
6187 x_destroy_window (f
)
6190 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6192 x_free_frame_resources (f
);
6194 dpyinfo
->reference_count
--;
6198 /* Setting window manager hints. */
6200 /* Set the normal size hints for the window manager, for frame F.
6201 FLAGS is the flags word to use--or 0 meaning preserve the flags
6202 that the window now has.
6203 If USER_POSITION is nonzero, we set the USPosition
6204 flag (this is useful when FLAGS is 0). */
6206 x_wm_set_size_hint (f
, flags
, user_position
)
6211 int base_width
, base_height
, width_inc
, height_inc
;
6212 int min_rows
= 0, min_cols
= 0;
6213 XSizeHints
*size_hints
;
6215 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6216 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6217 width_inc
= FRAME_COLUMN_WIDTH (f
);
6218 height_inc
= FRAME_LINE_HEIGHT (f
);
6220 check_frame_size (f
, &min_rows
, &min_cols
);
6222 size_hints
= FRAME_SIZE_HINTS (f
);
6223 if (size_hints
== NULL
)
6225 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6226 bzero (size_hints
, sizeof (XSizeHints
));
6229 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6230 size_hints
->width_inc
= width_inc
;
6231 size_hints
->height_inc
= height_inc
;
6232 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6233 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6234 size_hints
->base_width
= base_width
;
6235 size_hints
->base_height
= base_height
;
6238 size_hints
->flags
= flags
;
6239 else if (user_position
)
6241 size_hints
->flags
&= ~ PPosition
;
6242 size_hints
->flags
|= USPosition
;
6246 #if 0 /* MAC_TODO: hide application instead of iconify? */
6247 /* Used for IconicState or NormalState */
6250 x_wm_set_window_state (f
, state
)
6254 #ifdef USE_X_TOOLKIT
6257 XtSetArg (al
[0], XtNinitialState
, state
);
6258 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6259 #else /* not USE_X_TOOLKIT */
6260 Window window
= FRAME_X_WINDOW (f
);
6262 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6263 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6265 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6266 #endif /* not USE_X_TOOLKIT */
6270 x_wm_set_icon_pixmap (f
, pixmap_id
)
6276 #ifndef USE_X_TOOLKIT
6277 Window window
= FRAME_X_WINDOW (f
);
6282 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6283 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6287 /* It seems there is no way to turn off use of an icon pixmap.
6288 The following line does it, only if no icon has yet been created,
6289 for some window managers. But with mwm it crashes.
6290 Some people say it should clear the IconPixmapHint bit in this case,
6291 but that doesn't work, and the X consortium said it isn't the
6292 right thing at all. Since there is no way to win,
6293 best to explicitly give up. */
6295 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6301 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6305 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6306 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6309 #else /* not USE_X_TOOLKIT */
6311 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6312 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6314 #endif /* not USE_X_TOOLKIT */
6317 #endif /* MAC_TODO */
6320 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6324 #if 0 /* MAC_TODO: no icons on Mac */
6325 #ifdef USE_X_TOOLKIT
6326 Window window
= XtWindow (f
->output_data
.x
->widget
);
6328 Window window
= FRAME_X_WINDOW (f
);
6331 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6332 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6333 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6335 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6336 #endif /* MAC_TODO */
6340 /***********************************************************************
6342 ***********************************************************************/
6344 /* An XLFD pattern is divided into blocks delimited by '*'. This
6345 structure holds information for each block. */
6346 struct xlfdpat_block
6348 /* Length of the pattern string in this block. Non-zero except for
6349 the first and the last blocks. */
6352 /* Pattern string except the last character in this block. The last
6353 character is replaced with NUL in order to use it as a
6355 unsigned char *pattern
;
6357 /* Last character of the pattern string. Must not be '?'. */
6358 unsigned char last_char
;
6360 /* One of the tables for the Boyer-Moore string search. It
6361 specifies the number of positions to proceed for each character
6362 with which the match fails. */
6365 /* The skip value for the last character in the above `skip' is
6366 assigned to `infinity' in order to simplify a loop condition.
6367 The original value is saved here. */
6373 /* Normalized pattern string. "Normalized" means that capital
6374 letters are lowered, blocks are not empty except the first and
6375 the last ones, and trailing '?'s in a block that is not the last
6376 one are moved to the next one. The last character in each block
6377 is replaced with NUL. */
6380 /* Number of characters except '*'s and trailing '?'s in the
6381 normalized pattern string. */
6384 /* Number of trailing '?'s in the normalized pattern string. */
6385 int trailing_anychars
;
6387 /* Number of blocks and information for each block. The latter is
6388 NULL if the pattern is exact (no '*' or '?' in it). */
6390 struct xlfdpat_block
*blocks
;
6394 xlfdpat_destroy (pat
)
6395 struct xlfdpat
*pat
;
6402 xfree (pat
->blocks
);
6409 static struct xlfdpat
*
6410 xlfdpat_create (pattern
)
6413 struct xlfdpat
*pat
;
6414 int nblocks
, i
, skip
;
6415 unsigned char last_char
, *p
, *q
, *anychar_head
;
6416 struct xlfdpat_block
*blk
;
6418 pat
= xmalloc (sizeof (struct xlfdpat
));
6422 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6423 if (pat
->buf
== NULL
)
6426 /* Normalize the pattern string and store it to `pat->buf'. */
6428 anychar_head
= NULL
;
6431 for (p
= pattern
; *p
; p
++)
6433 unsigned char c
= *p
;
6436 if (last_char
== '*')
6437 /* ...a** -> ...a* */
6441 if (last_char
== '?')
6442 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6443 /* ...*??* -> ...*?? */
6446 /* ...a??* -> ...a*?? */
6448 *anychar_head
++ = '*';
6455 if (last_char
!= '?')
6459 /* On Mac OS X 10.3, tolower also converts non-ASCII
6460 characters for some locales. */
6464 *q
++ = last_char
= c
;
6468 pat
->nblocks
= nblocks
;
6469 if (last_char
!= '?')
6470 pat
->trailing_anychars
= 0;
6473 pat
->trailing_anychars
= q
- anychar_head
;
6476 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6478 if (anychar_head
== NULL
&& nblocks
== 1)
6480 /* The pattern is exact. */
6485 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6486 if (pat
->blocks
== NULL
)
6489 /* Divide the normalized pattern into blocks. */
6491 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6496 blk
->len
= p
- blk
->pattern
;
6500 blk
->len
= q
- blk
->pattern
;
6502 /* Setup a table for the Boyer-Moore string search. */
6503 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6506 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6507 blk
->pattern
[blk
->len
- 1] = '\0';
6509 for (skip
= 1; skip
< blk
->len
; skip
++)
6510 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6513 for (i
= 0; i
< 256; i
++)
6514 blk
->skip
[i
] = skip
;
6516 p
= blk
->pattern
+ (blk
->len
- skip
);
6518 blk
->skip
[*p
++] = skip
;
6520 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6526 xlfdpat_destroy (pat
);
6531 xlfdpat_exact_p (pat
)
6532 struct xlfdpat
*pat
;
6534 return pat
->blocks
== NULL
;
6537 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6538 that the pattern in *BLK matches with its prefix. Return NULL
6539 there is no such strings. STRING must be lowered in advance. */
6542 xlfdpat_block_match_1 (blk
, string
, start_max
)
6543 struct xlfdpat_block
*blk
;
6544 unsigned char *string
;
6547 int start
, infinity
;
6548 unsigned char *p
, *s
;
6550 xassert (blk
->len
> 0);
6551 xassert (start_max
+ blk
->len
<= strlen (string
));
6552 xassert (blk
->last_char
!= '?');
6554 /* See the comments in the function `boyer_moore' (search.c) for the
6555 use of `infinity'. */
6556 infinity
= start_max
+ blk
->len
+ 1;
6557 blk
->skip
[blk
->last_char
] = infinity
;
6562 /* Check the last character of the pattern. */
6563 s
= string
+ blk
->len
- 1;
6566 start
+= blk
->skip
[*(s
+ start
)];
6568 while (start
<= start_max
);
6570 if (start
< infinity
)
6571 /* Couldn't find the last character. */
6574 /* No less than `infinity' means we could find the last
6575 character at `s[start - infinity]'. */
6578 /* Check the remaining characters. We prefer making no-'?'
6579 cases faster because the use of '?' is really rare. */
6584 while (*p
++ == *s
++)
6587 while (*(p
- 1) == '?');
6589 if (*(p
- 1) == '\0')
6591 return string
+ start
;
6594 start
+= blk
->last_char_skip
;
6596 while (start
<= start_max
);
6601 #define xlfdpat_block_match(b, s, m) \
6602 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6603 : xlfdpat_block_match_1 (b, s, m))
6605 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6606 matches with STRING. STRING must be lowered in advance. */
6609 xlfdpat_match (pat
, string
)
6610 struct xlfdpat
*pat
;
6611 unsigned char *string
;
6613 int str_len
, nblocks
, i
, start_max
;
6614 struct xlfdpat_block
*blk
;
6617 xassert (pat
->nblocks
> 0);
6619 if (xlfdpat_exact_p (pat
))
6620 return strcmp (pat
->buf
, string
) == 0;
6622 /* The number of the characters in the string must not be smaller
6623 than that in the pattern. */
6624 str_len
= strlen (string
);
6625 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6628 /* Chop off the trailing '?'s. */
6629 str_len
-= pat
->trailing_anychars
;
6631 /* The last block. When it is non-empty, it must match at the end
6633 nblocks
= pat
->nblocks
;
6634 blk
= pat
->blocks
+ (nblocks
- 1);
6636 /* The last block is also the first one. */
6637 return (str_len
== blk
->len
6638 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6639 else if (blk
->len
!= 0)
6640 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6643 /* The first block. When it is non-empty, it must match at the
6644 beginning of the string. */
6648 s
= xlfdpat_block_match (blk
, string
, 0);
6651 string
= s
+ blk
->len
;
6654 /* The rest of the blocks. */
6655 start_max
= str_len
- pat
->nchars
;
6656 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6658 s
= xlfdpat_block_match (blk
, string
, start_max
);
6661 start_max
-= s
- string
;
6662 string
= s
+ blk
->len
;
6669 /***********************************************************************
6671 ***********************************************************************/
6673 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6676 x_get_font_info (f
, font_idx
)
6680 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6683 /* the global font name table */
6684 static char **font_name_table
= NULL
;
6685 static int font_name_table_size
= 0;
6686 static int font_name_count
= 0;
6688 /* Alist linking font family names to Font Manager font family
6689 references (which can also be used as QuickDraw font IDs). We use
6690 an alist because hash tables are not ready when the terminal frame
6691 for Mac OS Classic is created. */
6692 static Lisp_Object fm_font_family_alist
;
6694 /* Hash table linking font family names to ATSU font IDs. */
6695 static Lisp_Object atsu_font_id_hash
;
6698 /* Alist linking character set strings to Mac text encoding and Emacs
6700 static Lisp_Object Vmac_charset_info_alist
;
6703 create_text_encoding_info_alist ()
6705 Lisp_Object result
= Qnil
, rest
;
6707 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6709 Lisp_Object charset_info
= XCAR (rest
);
6710 Lisp_Object charset
, coding_system
, text_encoding
;
6711 Lisp_Object existing_info
;
6713 if (!(CONSP (charset_info
)
6714 && STRINGP (charset
= XCAR (charset_info
))
6715 && CONSP (XCDR (charset_info
))
6716 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6717 && CONSP (XCDR (XCDR (charset_info
)))
6718 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6721 existing_info
= assq_no_quit (text_encoding
, result
);
6722 if (NILP (existing_info
))
6723 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6726 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6727 XSETCDR (XCDR (existing_info
),
6728 Fcons (charset
, XCDR (XCDR (existing_info
))));
6736 decode_mac_font_name (name
, size
, coding_system
)
6739 Lisp_Object coding_system
;
6741 struct coding_system coding
;
6744 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6746 for (p
= name
; *p
; p
++)
6747 if (!isascii (*p
) || iscntrl (*p
))
6752 setup_coding_system (coding_system
, &coding
);
6753 coding
.src_multibyte
= 0;
6754 coding
.dst_multibyte
= 1;
6755 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6756 coding
.composing
= COMPOSITION_DISABLED
;
6757 buf
= (char *) alloca (size
);
6759 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6760 bcopy (buf
, name
, coding
.produced
);
6761 name
[coding
.produced
] = '\0';
6765 /* If there's just one occurrence of '-' in the family name, it is
6766 replaced with '_'. (More than one occurrence of '-' means a
6767 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6768 p
= strchr (name
, '-');
6769 if (p
&& strchr (p
+ 1, '-') == NULL
)
6772 for (p
= name
; *p
; p
++)
6773 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6774 for some locales. */
6781 mac_to_x_fontname (name
, size
, style
, charset
)
6789 char xf
[256], *result
;
6792 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6796 strcpy(foundry
, "Apple");
6797 strcpy(family
, name
);
6800 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6801 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6802 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6804 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6805 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6806 for (p
= result
; *p
; p
++)
6807 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6808 for some locales. */
6815 /* Parse fully-specified and instantiated X11 font spec XF, and store
6816 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6817 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6818 caller must allocate at least 256 and 32 bytes respectively. For
6819 ordinary Mac fonts, the value stored to FAMILY should just be their
6820 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6821 intlfonts collection contain their charset designation in their
6822 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6823 types of font names are handled accordingly. */
6825 const int kDefaultFontSize
= 12;
6828 parse_x_font_name (xf
, family
, size
, style
, charset
)
6834 Str31 foundry
, weight
;
6835 int point_size
, avgwidth
;
6838 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6839 foundry
, family
, weight
, slant
, size
,
6840 &point_size
, &avgwidth
, charset
) != 8
6841 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6842 foundry
, family
, weight
, slant
, size
,
6843 &point_size
, &avgwidth
, charset
) != 8)
6849 *size
= point_size
/ 10;
6850 else if (avgwidth
> 0)
6851 *size
= avgwidth
/ 10;
6854 *size
= kDefaultFontSize
;
6857 if (strcmp (weight
, "bold") == 0)
6862 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6864 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6866 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6868 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6869 but take overlap into account. */
6870 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6871 memcpy (family
, foundry
, foundry_len
);
6872 family
[foundry_len
] = '-';
6873 family
[foundry_len
+ 1 + family_len
] = '-';
6874 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6880 for (p
= family
; *p
; p
++)
6881 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6882 for some locales. */
6891 add_font_name_table_entry (char *font_name
)
6893 if (font_name_table_size
== 0)
6895 font_name_table_size
= 256;
6896 font_name_table
= (char **)
6897 xmalloc (font_name_table_size
* sizeof (char *));
6899 else if (font_name_count
+ 1 >= font_name_table_size
)
6901 font_name_table_size
*= 2;
6902 font_name_table
= (char **)
6903 xrealloc (font_name_table
,
6904 font_name_table_size
* sizeof (char *));
6907 font_name_table
[font_name_count
++] = font_name
;
6910 /* Sets up the table font_name_table to contain the list of all fonts
6911 in the system the first time the table is used so that the Resource
6912 Manager need not be accessed every time this information is
6916 init_font_name_table ()
6918 #if TARGET_API_MAC_CARBON
6919 FMFontFamilyIterator ffi
;
6920 FMFontFamilyInstanceIterator ffii
;
6922 Lisp_Object text_encoding_info_alist
;
6923 struct gcpro gcpro1
;
6925 text_encoding_info_alist
= create_text_encoding_info_alist ();
6928 #if USE_CG_TEXT_DRAWING
6929 init_cg_text_anti_aliasing_threshold ();
6931 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6932 text_encoding_info_alist
)))
6935 ItemCount nfonts
, i
;
6936 ATSUFontID
*font_ids
= NULL
;
6937 Ptr name
, prev_name
= NULL
;
6941 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6942 make_float (DEFAULT_REHASH_SIZE
),
6943 make_float (DEFAULT_REHASH_THRESHOLD
),
6945 err
= ATSUFontCount (&nfonts
);
6947 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6949 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6951 for (i
= 0; i
< nfonts
; i
++)
6953 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6954 kFontMacintoshPlatform
, kFontNoScript
,
6955 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6958 name
= xmalloc (name_len
+ 1);
6961 name
[name_len
] = '\0';
6962 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6963 kFontMacintoshPlatform
, kFontNoScript
,
6964 kFontNoLanguage
, name_len
, name
,
6967 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6970 && (prev_name
== NULL
6971 || strcmp (name
, prev_name
) != 0))
6973 static char *cs
= "iso10646-1";
6975 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
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,
6982 italic
| bold
, cs
));
6983 Fputhash (make_unibyte_string (name
, name_len
),
6984 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
6998 /* Create a dummy instance iterator here to avoid creating and
6999 destroying it in the loop. */
7000 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
7002 /* Create an iterator to enumerate the font families. */
7003 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
7006 FMDisposeFontFamilyInstanceIterator (&ffii
);
7010 GCPRO1 (text_encoding_info_alist
);
7012 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
7018 TextEncoding encoding
;
7019 TextEncodingBase sc
;
7020 Lisp_Object text_encoding_info
;
7022 if (FMGetFontFamilyName (ff
, name
) != noErr
)
7028 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
7030 sc
= GetTextEncodingBase (encoding
);
7031 text_encoding_info
= assq_no_quit (make_number (sc
),
7032 text_encoding_info_alist
);
7033 if (NILP (text_encoding_info
))
7034 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
7035 text_encoding_info_alist
);
7036 decode_mac_font_name (name
, sizeof (name
),
7037 XCAR (XCDR (text_encoding_info
)));
7038 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7040 fm_font_family_alist
);
7042 /* Point the instance iterator at the current font family. */
7043 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7046 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7049 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7051 if (size
> 0 || style
== normal
)
7052 for (; !NILP (rest
); rest
= XCDR (rest
))
7054 char *cs
= SDATA (XCAR (rest
));
7058 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
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
,
7070 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7079 /* Dispose of the iterators. */
7080 FMDisposeFontFamilyIterator (&ffi
);
7081 FMDisposeFontFamilyInstanceIterator (&ffii
);
7082 #else /* !TARGET_API_MAC_CARBON */
7084 SInt16 fontnum
, old_fontnum
;
7085 int num_mac_fonts
= CountResources('FOND');
7087 Handle font_handle
, font_handle_2
;
7088 short id
, scriptcode
;
7091 struct FontAssoc
*fat
;
7092 struct AsscEntry
*assc_entry
;
7093 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7094 struct gcpro gcpro1
;
7096 GetPort (&port
); /* save the current font number used */
7097 old_fontnum
= port
->txFont
;
7099 text_encoding_info_alist
= create_text_encoding_info_alist ();
7101 GCPRO1 (text_encoding_info_alist
);
7103 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7105 font_handle
= GetIndResource ('FOND', i
);
7109 GetResInfo (font_handle
, &id
, &type
, name
);
7110 GetFNum (name
, &fontnum
);
7116 scriptcode
= FontToScript (fontnum
);
7117 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7118 text_encoding_info_alist
);
7119 if (NILP (text_encoding_info
))
7120 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7121 text_encoding_info_alist
);
7122 decode_mac_font_name (name
, sizeof (name
),
7123 XCAR (XCDR (text_encoding_info
)));
7124 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7125 make_number (fontnum
)),
7126 fm_font_family_alist
);
7129 HLock (font_handle
);
7131 if (GetResourceSizeOnDisk (font_handle
)
7132 >= sizeof (struct FamRec
))
7134 fat
= (struct FontAssoc
*) (*font_handle
7135 + sizeof (struct FamRec
));
7137 = (struct AsscEntry
*) (*font_handle
7138 + sizeof (struct FamRec
)
7139 + sizeof (struct FontAssoc
));
7141 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7143 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7145 for (; !NILP (rest
); rest
= XCDR (rest
))
7147 char *cs
= SDATA (XCAR (rest
));
7149 add_font_name_table_entry (mac_to_x_fontname (name
,
7150 assc_entry
->fontSize
,
7151 assc_entry
->fontStyle
,
7157 HUnlock (font_handle
);
7158 font_handle_2
= GetNextFOND (font_handle
);
7159 ReleaseResource (font_handle
);
7160 font_handle
= font_handle_2
;
7162 while (ResError () == noErr
&& font_handle
);
7167 TextFont (old_fontnum
);
7168 #endif /* !TARGET_API_MAC_CARBON */
7173 mac_clear_font_name_table ()
7177 for (i
= 0; i
< font_name_count
; i
++)
7178 xfree (font_name_table
[i
]);
7179 xfree (font_name_table
);
7180 font_name_table
= NULL
;
7181 font_name_table_size
= font_name_count
= 0;
7182 fm_font_family_alist
= Qnil
;
7186 enum xlfd_scalable_field_index
7188 XLFD_SCL_PIXEL_SIZE
,
7189 XLFD_SCL_POINT_SIZE
,
7194 static int xlfd_scalable_fields
[] =
7203 mac_do_list_fonts (pattern
, maxnames
)
7208 Lisp_Object font_list
= Qnil
;
7209 struct xlfdpat
*pat
;
7211 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7214 if (font_name_table
== NULL
) /* Initialize when first used. */
7215 init_font_name_table ();
7217 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7220 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7221 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7222 fonts are scaled according to the specified size. */
7225 field
= xlfd_scalable_fields
;
7233 if ('0' <= *ptr
&& *ptr
<= '9')
7235 *val
= *ptr
++ - '0';
7236 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7237 *val
= *val
* 10 + *ptr
++ - '0';
7244 ptr
= strchr (ptr
, '-');
7247 while (ptr
&& i
< 14);
7249 if (i
== 14 && ptr
== NULL
)
7251 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7252 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7253 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7254 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7256 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7257 scl_val
[XLFD_SCL_POINT_SIZE
] =
7258 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7259 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7261 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7262 scl_val
[XLFD_SCL_AVGWIDTH
] =
7263 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7264 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7268 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7270 pat
= xlfdpat_create (pattern
);
7274 exact
= xlfdpat_exact_p (pat
);
7276 for (i
= 0; i
< font_name_count
; i
++)
7278 if (xlfdpat_match (pat
, font_name_table
[i
]))
7280 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7281 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7284 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7285 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7287 int former_len
= ptr
- font_name_table
[i
];
7289 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7292 memcpy (scaled
, font_name_table
[i
], former_len
);
7293 sprintf (scaled
+ former_len
,
7294 "-%d-%d-72-72-m-%d-%s",
7295 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7296 scl_val
[XLFD_SCL_POINT_SIZE
],
7297 scl_val
[XLFD_SCL_AVGWIDTH
],
7298 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7300 if (xlfdpat_match (pat
, scaled
))
7302 font_list
= Fcons (build_string (scaled
), font_list
);
7304 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7312 xlfdpat_destroy (pat
);
7317 /* Return a list of names of available fonts matching PATTERN on frame F.
7319 Frame F null means we have not yet created any frame on Mac, and
7320 consult the first display in x_display_list. MAXNAMES sets a limit
7321 on how many fonts to match. */
7324 x_list_fonts (f
, pattern
, size
, maxnames
)
7326 Lisp_Object pattern
;
7329 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7330 struct mac_display_info
*dpyinfo
7331 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7333 xassert (size
<= 0);
7335 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7336 if (NILP (patterns
))
7337 patterns
= Fcons (pattern
, Qnil
);
7339 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7341 pattern
= XCAR (patterns
);
7343 if (!STRINGP (pattern
))
7346 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7347 key
= Fcons (pattern
, make_number (maxnames
));
7349 list
= Fassoc (key
, tem
);
7352 list
= Fcdr_safe (list
);
7353 /* We have a cashed list. Don't have to get the list again. */
7358 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7361 /* MAC_TODO: add code for matching outline fonts here */
7363 /* Now store the result in the cache. */
7364 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7365 Fcons (Fcons (key
, list
),
7366 XCAR (XCDR (dpyinfo
->name_list_element
))));
7369 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7378 /* Check that FONT is valid on frame F. It is if it can be found in F's
7382 x_check_font (f
, font
)
7387 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7389 xassert (font
!= NULL
);
7391 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7392 if (dpyinfo
->font_table
[i
].name
7393 && font
== dpyinfo
->font_table
[i
].font
)
7396 xassert (i
< dpyinfo
->n_fonts
);
7399 #endif /* GLYPH_DEBUG != 0 */
7401 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7402 Note: There are (broken) X fonts out there with invalid XFontStruct
7403 min_bounds contents. For example, handa@etl.go.jp reports that
7404 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7405 have font->min_bounds.width == 0. */
7408 x_font_min_bounds (font
, w
, h
)
7409 MacFontStruct
*font
;
7412 *h
= FONT_HEIGHT (font
);
7413 *w
= font
->min_bounds
.width
;
7417 /* Compute the smallest character width and smallest font height over
7418 all fonts available on frame F. Set the members smallest_char_width
7419 and smallest_font_height in F's x_display_info structure to
7420 the values computed. Value is non-zero if smallest_font_height or
7421 smallest_char_width become smaller than they were before. */
7424 x_compute_min_glyph_bounds (f
)
7428 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7429 MacFontStruct
*font
;
7430 int old_width
= dpyinfo
->smallest_char_width
;
7431 int old_height
= dpyinfo
->smallest_font_height
;
7433 dpyinfo
->smallest_font_height
= 100000;
7434 dpyinfo
->smallest_char_width
= 100000;
7436 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7437 if (dpyinfo
->font_table
[i
].name
)
7439 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7442 font
= (MacFontStruct
*) fontp
->font
;
7443 xassert (font
!= (MacFontStruct
*) ~0);
7444 x_font_min_bounds (font
, &w
, &h
);
7446 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7447 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7450 xassert (dpyinfo
->smallest_char_width
> 0
7451 && dpyinfo
->smallest_font_height
> 0);
7453 return (dpyinfo
->n_fonts
== 1
7454 || dpyinfo
->smallest_char_width
< old_width
7455 || dpyinfo
->smallest_font_height
< old_height
);
7459 /* Determine whether given string is a fully-specified XLFD: all 14
7460 fields are present, none is '*'. */
7463 is_fully_specified_xlfd (char *p
)
7471 for (i
= 0; i
< 13; i
++)
7473 q
= strchr (p
+ 1, '-');
7476 if (q
- p
== 2 && *(p
+ 1) == '*')
7481 if (strchr (p
+ 1, '-') != NULL
)
7484 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7491 /* XLoadQueryFont creates and returns an internal representation for a
7492 font in a MacFontStruct struct. There is really no concept
7493 corresponding to "loading" a font on the Mac. But we check its
7494 existence and find the font number and all other information for it
7495 and store them in the returned MacFontStruct. */
7497 static MacFontStruct
*
7498 XLoadQueryFont (Display
*dpy
, char *fontname
)
7506 static ATSUFontID font_id
;
7507 ATSUStyle mac_style
= NULL
;
7510 #if TARGET_API_MAC_CARBON
7511 TextEncoding encoding
;
7516 MacFontStruct
*font
;
7517 XCharStruct
*space_bounds
= NULL
, *pcm
;
7519 if (is_fully_specified_xlfd (fontname
))
7523 Lisp_Object matched_fonts
;
7525 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7526 if (NILP (matched_fonts
))
7528 name
= SDATA (XCAR (matched_fonts
));
7531 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7535 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7538 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7539 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7540 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7541 sizeof (Boolean
), sizeof (Boolean
)};
7542 static Fixed size_fixed
;
7543 static Boolean bold_p
, italic_p
;
7544 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7545 &bold_p
, &italic_p
};
7546 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
,
7548 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
,
7549 kDecomposeDiacriticsSelector
};
7550 Lisp_Object font_id_cons
;
7552 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7553 atsu_font_id_hash
, Qnil
);
7554 if (NILP (font_id_cons
))
7556 font_id
= cons_to_long (font_id_cons
);
7557 size_fixed
= Long2Fix (size
);
7558 bold_p
= (fontface
& bold
) != 0;
7559 italic_p
= (fontface
& italic
) != 0;
7560 err
= ATSUCreateStyle (&mac_style
);
7563 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7567 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7568 tags
, sizes
, values
);
7570 scriptcode
= kTextEncodingMacUnicode
;
7575 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7579 fontnum
= XINT (XCDR (tmp
));
7580 #if TARGET_API_MAC_CARBON
7581 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7583 scriptcode
= GetTextEncodingBase (encoding
);
7585 scriptcode
= FontToScript (fontnum
);
7589 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7591 font
->mac_fontnum
= fontnum
;
7592 font
->mac_fontsize
= size
;
7593 font
->mac_fontface
= fontface
;
7594 font
->mac_scriptcode
= scriptcode
;
7596 font
->mac_style
= mac_style
;
7597 #if USE_CG_TEXT_DRAWING
7598 font
->cg_font
= NULL
;
7599 font
->cg_glyphs
= NULL
;
7603 /* Apple Japanese (SJIS) font is listed as both
7604 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7605 (Roman script) in init_font_name_table (). The latter should be
7606 treated as a one-byte font. */
7607 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7608 font
->mac_scriptcode
= smRoman
;
7610 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7613 if (font
->mac_style
)
7618 font
->min_byte1
= 0;
7619 font
->max_byte1
= 0xff;
7620 font
->min_char_or_byte2
= 0;
7621 font
->max_char_or_byte2
= 0xff;
7623 font
->bounds
.rows
= xmalloc (sizeof (XCharStructRow
*) * 0x100);
7624 if (font
->bounds
.rows
== NULL
)
7626 mac_unload_font (&one_mac_display_info
, font
);
7629 bzero (font
->bounds
.rows
, sizeof (XCharStructRow
*) * 0x100);
7630 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStructRow
));
7631 if (font
->bounds
.rows
[0] == NULL
)
7633 mac_unload_font (&one_mac_display_info
, font
);
7636 bzero (font
->bounds
.rows
[0], sizeof (XCharStructRow
));
7638 #if USE_CG_TEXT_DRAWING
7640 FMFontFamily font_family
;
7642 ATSFontRef ats_font
;
7644 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7646 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7648 /* Use CG text drawing if italic/bold is not synthesized. */
7649 if (err
== noErr
&& style
== fontface
)
7651 ats_font
= FMGetATSFontRefFromFont (font_id
);
7652 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7657 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7658 if (font
->cg_glyphs
)
7659 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7661 space_bounds
= font
->bounds
.rows
[0]->per_char
+ 0x20;
7662 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7663 &font
->ascent
, &font
->descent
,
7665 #if USE_CG_TEXT_DRAWING
7666 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7674 mac_unload_font (&one_mac_display_info
, font
);
7677 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], 0x20);
7679 pcm
= font
->bounds
.rows
[0]->per_char
;
7680 for (c
= 0x21; c
<= 0xff; c
++)
7683 /* Soft hyphen is not supported in ATSUI. */
7691 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7692 #if USE_CG_TEXT_DRAWING
7693 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7699 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], c
);
7701 #if USE_CG_TEXT_DRAWING
7702 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7704 /* Don't use CG text drawing if font substitution occurs in
7705 ASCII or Latin-1 characters. */
7706 CGFontRelease (font
->cg_font
);
7707 font
->cg_font
= NULL
;
7708 xfree (font
->cg_glyphs
);
7709 font
->cg_glyphs
= NULL
;
7718 SInt16 old_fontnum
, old_fontsize
;
7720 FontInfo the_fontinfo
;
7721 int is_two_byte_font
;
7723 /* Save the current font number used. */
7725 #if TARGET_API_MAC_CARBON
7726 old_fontnum
= GetPortTextFont (port
);
7727 old_fontsize
= GetPortTextSize (port
);
7728 old_fontface
= GetPortTextFace (port
);
7730 old_fontnum
= port
->txFont
;
7731 old_fontsize
= port
->txSize
;
7732 old_fontface
= port
->txFace
;
7737 TextFace (fontface
);
7739 GetFontInfo (&the_fontinfo
);
7741 font
->ascent
= the_fontinfo
.ascent
;
7742 font
->descent
= the_fontinfo
.descent
;
7744 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7745 || font
->mac_scriptcode
== smTradChinese
7746 || font
->mac_scriptcode
== smSimpChinese
7747 || font
->mac_scriptcode
== smKorean
);
7749 if (is_two_byte_font
)
7753 font
->min_byte1
= 0xa1;
7754 font
->max_byte1
= 0xfe;
7755 font
->min_char_or_byte2
= 0xa1;
7756 font
->max_char_or_byte2
= 0xfe;
7758 /* Use the width of an "ideographic space" of that font
7759 because the_fontinfo.widMax returns the wrong width for
7761 switch (font
->mac_scriptcode
)
7764 font
->min_byte1
= 0x81;
7765 font
->max_byte1
= 0xfc;
7766 font
->min_char_or_byte2
= 0x40;
7767 font
->max_char_or_byte2
= 0xfc;
7768 char_width
= StringWidth("\p\x81\x40");
7771 font
->min_char_or_byte2
= 0x40;
7772 char_width
= StringWidth("\p\xa1\x40");
7775 char_width
= StringWidth("\p\xa1\xa1");
7778 char_width
= StringWidth("\p\xa1\xa1");
7782 font
->bounds
.per_char
= NULL
;
7784 if (fontface
& italic
)
7785 font
->max_bounds
.rbearing
= char_width
+ 1;
7787 font
->max_bounds
.rbearing
= char_width
;
7788 font
->max_bounds
.lbearing
= 0;
7789 font
->max_bounds
.width
= char_width
;
7790 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7791 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7793 font
->min_bounds
= font
->max_bounds
;
7799 font
->min_byte1
= font
->max_byte1
= 0;
7800 font
->min_char_or_byte2
= 0x20;
7801 font
->max_char_or_byte2
= 0xff;
7803 font
->bounds
.per_char
=
7804 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7805 if (font
->bounds
.per_char
== NULL
)
7807 mac_unload_font (&one_mac_display_info
, font
);
7810 bzero (font
->bounds
.per_char
,
7811 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7813 space_bounds
= font
->bounds
.per_char
;
7814 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
7815 space_bounds
, NULL
);
7817 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
7818 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
7821 /* Restore previous font number, size and face. */
7822 TextFont (old_fontnum
);
7823 TextSize (old_fontsize
);
7824 TextFace (old_fontface
);
7831 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
7832 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
7835 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
7837 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
7839 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
7841 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
7844 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
7846 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
7848 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
7850 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
7855 font
->mac_style
== NULL
&&
7857 font
->max_bounds
.width
== font
->min_bounds
.width
7858 && font
->min_bounds
.lbearing
>= 0
7859 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
7861 /* Fixed width and no overhangs. */
7862 xfree (font
->bounds
.per_char
);
7863 font
->bounds
.per_char
= NULL
;
7867 #if !defined (MAC_OS8) || USE_ATSUI
7868 /* AppKit and WebKit do some adjustment to the heights of Courier,
7869 Helvetica, and Times. This only works on the environments where
7870 srcCopy text transfer mode is never used. */
7872 #ifdef MAC_OS8 /* implies USE_ATSUI */
7875 (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7876 || strcmp (family
, "times") == 0))
7877 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7885 mac_unload_font (dpyinfo
, font
)
7886 struct mac_display_info
*dpyinfo
;
7889 xfree (font
->full_name
);
7891 if (font
->mac_style
)
7895 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
7896 if (font
->bounds
.rows
[i
])
7897 xfree (font
->bounds
.rows
[i
]);
7898 xfree (font
->bounds
.rows
);
7899 ATSUDisposeStyle (font
->mac_style
);
7903 if (font
->bounds
.per_char
)
7904 xfree (font
->bounds
.per_char
);
7905 #if USE_CG_TEXT_DRAWING
7907 CGFontRelease (font
->cg_font
);
7908 if (font
->cg_glyphs
)
7909 xfree (font
->cg_glyphs
);
7915 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7916 pointer to the structure font_info while allocating it dynamically.
7917 If SIZE is 0, load any size of font.
7918 If loading is failed, return NULL. */
7921 x_load_font (f
, fontname
, size
)
7923 register char *fontname
;
7926 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7927 Lisp_Object font_names
;
7929 /* Get a list of all the fonts that match this name. Once we
7930 have a list of matching fonts, we compare them against the fonts
7931 we already have by comparing names. */
7932 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7934 if (!NILP (font_names
))
7939 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7940 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7941 if (dpyinfo
->font_table
[i
].name
7942 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7943 SDATA (XCAR (tail
)))
7944 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7945 SDATA (XCAR (tail
)))))
7946 return (dpyinfo
->font_table
+ i
);
7951 /* Load the font and add it to the table. */
7954 struct MacFontStruct
*font
;
7955 struct font_info
*fontp
;
7956 unsigned long value
;
7959 fontname
= (char *) SDATA (XCAR (font_names
));
7962 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7967 /* Find a free slot in the font table. */
7968 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7969 if (dpyinfo
->font_table
[i
].name
== NULL
)
7972 /* If no free slot found, maybe enlarge the font table. */
7973 if (i
== dpyinfo
->n_fonts
7974 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7977 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7978 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7980 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7983 fontp
= dpyinfo
->font_table
+ i
;
7984 if (i
== dpyinfo
->n_fonts
)
7987 /* Now fill in the slots of *FONTP. */
7989 bzero (fontp
, sizeof (*fontp
));
7991 fontp
->font_idx
= i
;
7992 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7993 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7995 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7997 /* Fixed width font. */
7998 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
8005 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
8006 pcm
= mac_per_char_metric (font
, &char2b
, 0);
8008 fontp
->space_width
= pcm
->width
;
8010 fontp
->space_width
= FONT_WIDTH (font
);
8014 int width
= pcm
->width
;
8015 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
8016 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
8017 width
+= pcm
->width
;
8018 fontp
->average_width
= width
/ 95;
8021 fontp
->average_width
= FONT_WIDTH (font
);
8024 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
8025 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
8027 fontp
->size
= font
->max_bounds
.width
;
8028 fontp
->height
= FONT_HEIGHT (font
);
8030 /* For some font, ascent and descent in max_bounds field is
8031 larger than the above value. */
8032 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
8033 if (max_height
> fontp
->height
)
8034 fontp
->height
= max_height
;
8037 /* The slot `encoding' specifies how to map a character
8038 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
8039 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
8040 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8041 2:0xA020..0xFF7F). For the moment, we don't know which charset
8042 uses this font. So, we set information in fontp->encoding[1]
8043 which is never used by any charset. If mapping can't be
8044 decided, set FONT_ENCODING_NOT_DECIDED. */
8045 if (font
->mac_scriptcode
== smJapanese
)
8046 fontp
->encoding
[1] = 4;
8050 = (font
->max_byte1
== 0
8052 ? (font
->min_char_or_byte2
< 0x80
8053 ? (font
->max_char_or_byte2
< 0x80
8054 ? 0 /* 0x20..0x7F */
8055 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8056 : 1) /* 0xA0..0xFF */
8058 : (font
->min_byte1
< 0x80
8059 ? (font
->max_byte1
< 0x80
8060 ? (font
->min_char_or_byte2
< 0x80
8061 ? (font
->max_char_or_byte2
< 0x80
8062 ? 0 /* 0x2020..0x7F7F */
8063 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8064 : 3) /* 0x20A0..0x7FFF */
8065 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8066 : (font
->min_char_or_byte2
< 0x80
8067 ? (font
->max_char_or_byte2
< 0x80
8068 ? 2 /* 0xA020..0xFF7F */
8069 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8070 : 1))); /* 0xA0A0..0xFFFF */
8073 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8074 fontp
->baseline_offset
8075 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8076 ? (long) value
: 0);
8077 fontp
->relative_compose
8078 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8079 ? (long) value
: 0);
8080 fontp
->default_ascent
8081 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8082 ? (long) value
: 0);
8084 fontp
->baseline_offset
= 0;
8085 fontp
->relative_compose
= 0;
8086 fontp
->default_ascent
= 0;
8089 /* Set global flag fonts_changed_p to non-zero if the font loaded
8090 has a character with a smaller width than any other character
8091 before, or if the font loaded has a smaller height than any
8092 other font loaded before. If this happens, it will make a
8093 glyph matrix reallocation necessary. */
8094 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8101 /* Return a pointer to struct font_info of a font named FONTNAME for
8102 frame F. If no such font is loaded, return NULL. */
8105 x_query_font (f
, fontname
)
8107 register char *fontname
;
8109 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8112 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8113 if (dpyinfo
->font_table
[i
].name
8114 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8115 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8116 return (dpyinfo
->font_table
+ i
);
8121 /* Find a CCL program for a font specified by FONTP, and set the member
8122 `encoder' of the structure. */
8125 x_find_ccl_program (fontp
)
8126 struct font_info
*fontp
;
8128 Lisp_Object list
, elt
;
8130 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8134 && STRINGP (XCAR (elt
))
8135 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8141 struct ccl_program
*ccl
8142 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8144 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8147 fontp
->font_encoder
= ccl
;
8153 /* The Mac Event loop code */
8155 #if !TARGET_API_MAC_CARBON
8157 #include <Quickdraw.h>
8158 #include <Balloons.h>
8159 #include <Devices.h>
8161 #include <Gestalt.h>
8163 #include <Processes.h>
8165 #include <ToolUtils.h>
8166 #include <TextUtils.h>
8167 #include <Dialogs.h>
8170 #include <Resources.h>
8175 #endif /* ! TARGET_API_MAC_CARBON */
8180 #define WINDOW_RESOURCE 128
8181 #define TERM_WINDOW_RESOURCE 129
8183 #define DEFAULT_NUM_COLS 80
8185 #define MIN_DOC_SIZE 64
8186 #define MAX_DOC_SIZE 32767
8188 #define EXTRA_STACK_ALLOC (256 * 1024)
8190 #define ARGV_STRING_LIST_ID 129
8191 #define ABOUT_ALERT_ID 128
8192 #define RAM_TOO_LARGE_ALERT_ID 129
8194 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8195 Lisp_Object Qreverse
;
8198 /* Modifier associated with the control key, or nil to ignore. */
8199 Lisp_Object Vmac_control_modifier
;
8201 /* Modifier associated with the option key, or nil to ignore. */
8202 Lisp_Object Vmac_option_modifier
;
8204 /* Modifier associated with the command key, or nil to ignore. */
8205 Lisp_Object Vmac_command_modifier
;
8207 /* Modifier associated with the function key, or nil to ignore. */
8208 Lisp_Object Vmac_function_modifier
;
8210 /* True if the option and command modifiers should be used to emulate
8211 a three button mouse */
8212 Lisp_Object Vmac_emulate_three_button_mouse
;
8214 #if USE_CARBON_EVENTS
8215 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8216 mouse-2, instead of mouse-3. */
8217 int mac_wheel_button_is_mouse_2
;
8219 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8220 for processing before Emacs sees it. */
8221 int mac_pass_command_to_system
;
8223 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8224 for processing before Emacs sees it. */
8225 int mac_pass_control_to_system
;
8228 /* Points to the variable `inev' in the function XTread_socket. It is
8229 used for passing an input event to the function back from
8230 Carbon/Apple event handlers. */
8231 static struct input_event
*read_socket_inev
= NULL
;
8233 Point saved_menu_event_location
;
8236 #if USE_CARBON_EVENTS
8237 static Lisp_Object Qhicommand
;
8239 extern int mac_ready_for_apple_events
;
8240 extern Lisp_Object Qundefined
;
8241 extern void init_apple_event_handler
P_ ((void));
8242 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8243 Lisp_Object
*, Lisp_Object
*,
8245 extern OSErr init_coercion_handler
P_ ((void));
8247 #if TARGET_API_MAC_CARBON
8249 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8250 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8251 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8252 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8255 #if USE_CARBON_EVENTS
8257 extern void init_service_handler ();
8258 static Lisp_Object Qservices
, Qpaste
, Qperform
;
8260 /* Window Event Handler */
8261 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8264 OSErr
install_window_handler (WindowPtr
);
8266 extern void init_emacs_passwd_dir ();
8267 extern int emacs_main (int, char **, char **);
8269 extern void initialize_applescript();
8270 extern void terminate_applescript();
8273 #if USE_CARBON_EVENTS
8274 mac_to_emacs_modifiers (UInt32 mods
)
8276 mac_to_emacs_modifiers (EventModifiers mods
)
8279 unsigned int result
= 0;
8280 if (mods
& shiftKey
)
8281 result
|= shift_modifier
;
8283 /* Deactivated to simplify configuration:
8284 if Vmac_option_modifier is non-NIL, we fully process the Option
8285 key. Otherwise, we only process it if an additional Ctrl or Command
8286 is pressed. That way the system may convert the character to a
8288 if ((mods & optionKey) &&
8289 (( !NILP(Vmac_option_modifier) ||
8290 ((mods & cmdKey) || (mods & controlKey))))) */
8292 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8293 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8295 result
|= XUINT(val
);
8297 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8298 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8300 result
|= XUINT(val
);
8302 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8303 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8305 result
|= XUINT(val
);
8309 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8310 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8312 result
|= XUINT(val
);
8320 mac_get_emulated_btn ( UInt32 modifiers
)
8323 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8324 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8325 if (modifiers
& cmdKey
)
8326 result
= cmdIs3
? 2 : 1;
8327 else if (modifiers
& optionKey
)
8328 result
= cmdIs3
? 1 : 2;
8333 #if USE_CARBON_EVENTS
8334 /* Obtains the event modifiers from the event ref and then calls
8335 mac_to_emacs_modifiers. */
8337 mac_event_to_emacs_modifiers (EventRef eventRef
)
8340 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8341 sizeof (UInt32
), NULL
, &mods
);
8342 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8343 GetEventClass(eventRef
) == kEventClassMouse
)
8345 mods
&= ~(optionKey
| cmdKey
);
8347 return mac_to_emacs_modifiers (mods
);
8350 /* Given an event ref, return the code to use for the mouse button
8351 code in the emacs input_event. */
8353 mac_get_mouse_btn (EventRef ref
)
8355 EventMouseButton result
= kEventMouseButtonPrimary
;
8356 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8357 sizeof (EventMouseButton
), NULL
, &result
);
8360 case kEventMouseButtonPrimary
:
8361 if (NILP (Vmac_emulate_three_button_mouse
))
8365 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8366 sizeof (UInt32
), NULL
, &mods
);
8367 return mac_get_emulated_btn(mods
);
8369 case kEventMouseButtonSecondary
:
8370 return mac_wheel_button_is_mouse_2
? 2 : 1;
8371 case kEventMouseButtonTertiary
:
8372 case 4: /* 4 is the number for the mouse wheel button */
8373 return mac_wheel_button_is_mouse_2
? 1 : 2;
8379 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8380 events. However the click of the mouse wheel is not converted to a
8381 mouseDown or mouseUp event. Likewise for dead key down events.
8382 This calls ConvertEventRef, but then checks to see if it is a mouse
8383 up/down, or a dead key down carbon event that has not been
8384 converted, and if so, converts it by hand (to be picked up in the
8385 XTread_socket loop). */
8386 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8388 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8393 switch (GetEventClass (eventRef
))
8395 case kEventClassMouse
:
8396 switch (GetEventKind (eventRef
))
8398 case kEventMouseDown
:
8399 eventRec
->what
= mouseDown
;
8404 eventRec
->what
= mouseUp
;
8413 case kEventClassKeyboard
:
8414 switch (GetEventKind (eventRef
))
8416 case kEventRawKeyDown
:
8418 unsigned char char_codes
;
8421 eventRec
->what
= keyDown
;
8422 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8423 NULL
, sizeof (char), NULL
, &char_codes
);
8424 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8425 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8426 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8442 /* Need where and when. */
8445 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8446 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8447 /* Use two step process because new event modifiers are 32-bit
8448 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8449 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8450 NULL
, sizeof (UInt32
), NULL
, &mods
);
8451 eventRec
->modifiers
= mods
;
8453 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8464 Handle menubar_handle
;
8465 MenuHandle menu_handle
;
8467 menubar_handle
= GetNewMBar (128);
8468 if(menubar_handle
== NULL
)
8470 SetMenuBar (menubar_handle
);
8473 #if !TARGET_API_MAC_CARBON
8474 menu_handle
= GetMenuHandle (M_APPLE
);
8475 if(menu_handle
!= NULL
)
8476 AppendResMenu (menu_handle
,'DRVR');
8484 do_init_managers (void)
8486 #if !TARGET_API_MAC_CARBON
8487 InitGraf (&qd
.thePort
);
8489 FlushEvents (everyEvent
, 0);
8494 #endif /* !TARGET_API_MAC_CARBON */
8497 #if !TARGET_API_MAC_CARBON
8498 /* set up some extra stack space for use by emacs */
8499 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8501 /* MaxApplZone must be called for AppleScript to execute more
8502 complicated scripts */
8505 #endif /* !TARGET_API_MAC_CARBON */
8509 do_check_ram_size (void)
8511 SInt32 physical_ram_size
, logical_ram_size
;
8513 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8514 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8515 || physical_ram_size
> (1 << VALBITS
)
8516 || logical_ram_size
> (1 << VALBITS
))
8518 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8524 do_window_update (WindowPtr win
)
8526 struct frame
*f
= mac_window_to_frame (win
);
8530 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8532 if (win
!= tip_window
)
8534 if (f
->async_visible
== 0)
8536 /* Update events may occur when a frame gets iconified. */
8538 f
->async_visible
= 1;
8539 f
->async_iconified
= 0;
8540 SET_FRAME_GARBAGED (f
);
8546 #if TARGET_API_MAC_CARBON
8547 RgnHandle region
= NewRgn ();
8549 GetPortVisibleRegion (GetWindowPort (win
), region
);
8550 GetRegionBounds (region
, &r
);
8551 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8552 UpdateControls (win
, region
);
8553 DisposeRgn (region
);
8555 r
= (*win
->visRgn
)->rgnBBox
;
8556 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8557 UpdateControls (win
, win
->visRgn
);
8566 is_emacs_window (WindowPtr win
)
8568 Lisp_Object tail
, frame
;
8573 FOR_EACH_FRAME (tail
, frame
)
8574 if (FRAME_MAC_P (XFRAME (frame
)))
8575 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8584 /* Window-activate events will do the job. */
8590 /* Window-deactivate events will do the job. */
8595 do_apple_menu (SInt16 menu_item
)
8597 #if !TARGET_API_MAC_CARBON
8599 SInt16 da_driver_refnum
;
8601 if (menu_item
== I_ABOUT
)
8602 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8605 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8606 da_driver_refnum
= OpenDeskAcc (item_name
);
8608 #endif /* !TARGET_API_MAC_CARBON */
8612 do_menu_choice (SInt32 menu_choice
)
8614 SInt16 menu_id
, menu_item
;
8616 menu_id
= HiWord (menu_choice
);
8617 menu_item
= LoWord (menu_choice
);
8625 do_apple_menu (menu_item
);
8630 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8631 MenuHandle menu
= GetMenuHandle (menu_id
);
8636 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8637 menubar_selection_callback (f
, refcon
);
8646 /* Handle drags in size box. Based on code contributed by Ben
8647 Mesander and IM - Window Manager A. */
8650 do_grow_window (WindowPtr w
, EventRecord
*e
)
8653 int rows
, columns
, width
, height
;
8654 struct frame
*f
= mac_window_to_frame (w
);
8655 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8656 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8657 #if TARGET_API_MAC_CARBON
8663 if (size_hints
->flags
& PMinSize
)
8665 min_width
= size_hints
->min_width
;
8666 min_height
= size_hints
->min_height
;
8668 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8670 #if TARGET_API_MAC_CARBON
8671 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8673 height
= new_rect
.bottom
- new_rect
.top
;
8674 width
= new_rect
.right
- new_rect
.left
;
8676 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8677 /* see if it really changed size */
8680 height
= HiWord (grow_size
);
8681 width
= LoWord (grow_size
);
8684 if (width
!= FRAME_PIXEL_WIDTH (f
)
8685 || height
!= FRAME_PIXEL_HEIGHT (f
))
8687 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8688 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8690 x_set_window_size (f
, 0, columns
, rows
);
8695 /* Handle clicks in zoom box. Calculation of "standard state" based
8696 on code in IM - Window Manager A and code contributed by Ben
8697 Mesander. The standard state of an Emacs window is 80-characters
8698 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8701 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8704 Rect zoom_rect
, port_rect
;
8706 int w_title_height
, columns
, rows
, width
, height
;
8707 struct frame
*f
= mac_window_to_frame (w
);
8708 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8710 #if TARGET_API_MAC_CARBON
8712 Point standard_size
;
8714 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8715 standard_size
.v
= dpyinfo
->height
;
8717 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8718 zoom_in_or_out
= inZoomIn
;
8721 /* Adjust the standard size according to character boundaries. */
8723 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8724 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8725 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8726 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8727 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8728 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8729 && port_rect
.left
== zoom_rect
.left
8730 && port_rect
.top
== zoom_rect
.top
)
8731 zoom_in_or_out
= inZoomIn
;
8733 zoom_in_or_out
= inZoomOut
;
8736 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8738 #else /* not TARGET_API_MAC_CARBON */
8739 GetPort (&save_port
);
8741 SetPortWindowPort (w
);
8743 /* Clear window to avoid flicker. */
8744 EraseRect (&(w
->portRect
));
8745 if (zoom_in_or_out
== inZoomOut
)
8747 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8748 LocalToGlobal (&top_left
);
8750 /* calculate height of window's title bar */
8751 w_title_height
= top_left
.v
- 1
8752 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8754 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8755 zoom_rect
= qd
.screenBits
.bounds
;
8756 zoom_rect
.top
+= w_title_height
;
8757 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8759 zoom_rect
.right
= zoom_rect
.left
8760 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8762 /* Adjust the standard size according to character boundaries. */
8763 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8765 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8767 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8771 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8773 SetPort (save_port
);
8774 #endif /* not TARGET_API_MAC_CARBON */
8776 /* retrieve window size and update application values */
8777 #if TARGET_API_MAC_CARBON
8778 GetWindowPortBounds (w
, &port_rect
);
8780 port_rect
= w
->portRect
;
8782 height
= port_rect
.bottom
- port_rect
.top
;
8783 width
= port_rect
.right
- port_rect
.left
;
8785 if (width
!= FRAME_PIXEL_WIDTH (f
)
8786 || height
!= FRAME_PIXEL_HEIGHT (f
))
8788 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8789 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8791 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8792 SET_FRAME_GARBAGED (f
);
8793 cancel_mouse_face (f
);
8795 FRAME_PIXEL_WIDTH (f
) = width
;
8796 FRAME_PIXEL_HEIGHT (f
) = height
;
8798 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8802 mac_store_apple_event (class, id
, desc
)
8803 Lisp_Object
class, id
;
8807 struct input_event buf
;
8810 desc_copy
= xmalloc (sizeof (AEDesc
));
8811 if (desc_copy
== NULL
)
8814 err
= AEDuplicateDesc (desc
, desc_copy
);
8819 buf
.kind
= MAC_APPLE_EVENT
;
8822 buf
.code
= (int)desc_copy
;
8823 XSETFRAME (buf
.frame_or_window
,
8824 mac_focus_frame (&one_mac_display_info
));
8826 kbd_buffer_store_event (&buf
);
8833 mac_make_lispy_event_code (code
)
8836 AEDesc
*desc
= (AEDesc
*)code
;
8839 obj
= mac_aedesc_to_lisp (desc
);
8840 AEDisposeDesc (desc
);
8846 #if USE_CARBON_EVENTS
8847 static pascal OSStatus
8848 mac_handle_command_event (next_handler
, event
, data
)
8849 EventHandlerCallRef next_handler
;
8856 Lisp_Object class_key
, id_key
, binding
;
8858 result
= CallNextEventHandler (next_handler
, event
);
8859 if (result
!= eventNotHandledErr
)
8862 GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8863 sizeof (HICommand
), NULL
, &command
);
8865 if (command
.commandID
== 0)
8866 return eventNotHandledErr
;
8868 /* A HICommand event is mapped to an Apple event whose event class
8869 symbol is `hicommand' and event ID is its command ID. */
8870 class_key
= Qhicommand
;
8871 mac_find_apple_event_spec (0, command
.commandID
,
8872 &class_key
, &id_key
, &binding
);
8873 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
8874 if (INTEGERP (binding
))
8875 return XINT (binding
);
8878 AppleEvent apple_event
;
8880 static EventParamName names
[] = {kEventParamDirectObject
,
8881 kEventParamKeyModifiers
};
8882 static EventParamType types
[] = {typeHICommand
,
8884 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
8888 err
= mac_store_apple_event (class_key
, id_key
, &apple_event
);
8889 AEDisposeDesc (&apple_event
);
8895 return eventNotHandledErr
;
8899 init_command_handler ()
8902 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8903 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8905 if (handle_command_eventUPP
== NULL
)
8906 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8907 return InstallApplicationEventHandler (handle_command_eventUPP
,
8908 GetEventTypeCount (specs
), specs
,
8912 static pascal OSStatus
8913 mac_handle_window_event (next_handler
, event
, data
)
8914 EventHandlerCallRef next_handler
;
8921 XSizeHints
*size_hints
;
8923 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8924 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8926 switch (GetEventKind (event
))
8928 case kEventWindowUpdate
:
8929 result
= CallNextEventHandler (next_handler
, event
);
8930 if (result
!= eventNotHandledErr
)
8933 do_window_update (wp
);
8936 case kEventWindowBoundsChanging
:
8937 result
= CallNextEventHandler (next_handler
, event
);
8938 if (result
!= eventNotHandledErr
)
8941 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8942 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8943 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8944 if ((attributes
& kWindowBoundsChangeUserResize
)
8945 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8946 == (PResizeInc
| PBaseSize
| PMinSize
)))
8951 GetEventParameter (event
, kEventParamCurrentBounds
,
8953 NULL
, sizeof (Rect
), NULL
, &bounds
);
8954 width
= bounds
.right
- bounds
.left
;
8955 height
= bounds
.bottom
- bounds
.top
;
8957 if (width
< size_hints
->min_width
)
8958 width
= size_hints
->min_width
;
8960 width
= size_hints
->base_width
8961 + (int) ((width
- size_hints
->base_width
)
8962 / (float) size_hints
->width_inc
+ .5)
8963 * size_hints
->width_inc
;
8965 if (height
< size_hints
->min_height
)
8966 height
= size_hints
->min_height
;
8968 height
= size_hints
->base_height
8969 + (int) ((height
- size_hints
->base_height
)
8970 / (float) size_hints
->height_inc
+ .5)
8971 * size_hints
->height_inc
;
8973 bounds
.right
= bounds
.left
+ width
;
8974 bounds
.bottom
= bounds
.top
+ height
;
8975 SetEventParameter (event
, kEventParamCurrentBounds
,
8976 typeQDRectangle
, sizeof (Rect
), &bounds
);
8981 case kEventWindowShown
:
8982 case kEventWindowHidden
:
8983 case kEventWindowExpanded
:
8984 case kEventWindowCollapsed
:
8985 result
= CallNextEventHandler (next_handler
, event
);
8987 mac_handle_visibility_change (mac_window_to_frame (wp
));
8993 return eventNotHandledErr
;
8996 static pascal OSStatus
8997 mac_handle_mouse_event (next_handler
, event
, data
)
8998 EventHandlerCallRef next_handler
;
9004 switch (GetEventKind (event
))
9006 case kEventMouseWheelMoved
:
9010 EventMouseWheelAxis axis
;
9014 result
= CallNextEventHandler (next_handler
, event
);
9015 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
9018 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
9019 NULL
, sizeof (WindowRef
), NULL
, &wp
);
9020 f
= mac_window_to_frame (wp
);
9021 if (f
!= mac_focus_frame (&one_mac_display_info
))
9024 GetEventParameter (event
, kEventParamMouseWheelAxis
,
9025 typeMouseWheelAxis
, NULL
,
9026 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
9027 if (axis
!= kEventMouseWheelAxisY
)
9030 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
9031 NULL
, sizeof (SInt32
), NULL
, &delta
);
9032 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
9033 NULL
, sizeof (Point
), NULL
, &point
);
9034 read_socket_inev
->kind
= WHEEL_EVENT
;
9035 read_socket_inev
->code
= 0;
9036 read_socket_inev
->modifiers
=
9037 (mac_event_to_emacs_modifiers (event
)
9038 | ((delta
< 0) ? down_modifier
: up_modifier
));
9039 SetPortWindowPort (wp
);
9040 GlobalToLocal (&point
);
9041 XSETINT (read_socket_inev
->x
, point
.h
);
9042 XSETINT (read_socket_inev
->y
, point
.v
);
9043 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9053 return eventNotHandledErr
;
9058 mac_store_services_event (event
)
9062 AppleEvent apple_event
;
9065 switch (GetEventKind (event
))
9067 case kEventServicePaste
:
9069 err
= create_apple_event_from_event_ref (event
, 0, NULL
, NULL
,
9073 case kEventServicePerform
:
9075 static EventParamName names
[] = {kEventParamServiceMessageName
,
9076 kEventParamServiceUserData
};
9077 static EventParamType types
[] = {typeCFStringRef
,
9081 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9092 err
= mac_store_apple_event (Qservices
, id_key
, &apple_event
);
9093 AEDisposeDesc (&apple_event
);
9098 #endif /* MAC_OSX */
9099 #endif /* USE_CARBON_EVENTS */
9103 install_window_handler (window
)
9107 #if USE_CARBON_EVENTS
9108 EventTypeSpec specs_window
[] =
9109 {{kEventClassWindow
, kEventWindowUpdate
},
9110 {kEventClassWindow
, kEventWindowBoundsChanging
},
9111 {kEventClassWindow
, kEventWindowShown
},
9112 {kEventClassWindow
, kEventWindowHidden
},
9113 {kEventClassWindow
, kEventWindowExpanded
},
9114 {kEventClassWindow
, kEventWindowCollapsed
}};
9115 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9116 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9117 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9119 if (handle_window_eventUPP
== NULL
)
9120 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9121 if (handle_mouse_eventUPP
== NULL
)
9122 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9123 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9124 GetEventTypeCount (specs_window
),
9125 specs_window
, NULL
, NULL
);
9127 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9128 GetEventTypeCount (specs_mouse
),
9129 specs_mouse
, NULL
, NULL
);
9131 #if TARGET_API_MAC_CARBON
9132 if (mac_do_track_dragUPP
== NULL
)
9133 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9134 if (mac_do_receive_dragUPP
== NULL
)
9135 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9138 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9140 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9146 remove_window_handler (window
)
9149 #if TARGET_API_MAC_CARBON
9150 if (mac_do_track_dragUPP
)
9151 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9152 if (mac_do_receive_dragUPP
)
9153 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9157 #if TARGET_API_MAC_CARBON
9159 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9160 void *handlerRefCon
, DragReference theDrag
)
9162 static int can_accept
;
9165 ItemReference theItem
;
9166 FlavorFlags theFlags
;
9169 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9170 return dragNotAcceptedErr
;
9174 case kDragTrackingEnterHandler
:
9175 CountDragItems (theDrag
, &items
);
9177 for (index
= 1; index
<= items
; index
++)
9179 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9180 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9181 if (result
== noErr
)
9189 case kDragTrackingEnterWindow
:
9192 RgnHandle hilite_rgn
= NewRgn ();
9194 struct frame
*f
= mac_window_to_frame (window
);
9196 GetWindowPortBounds (window
, &r
);
9197 OffsetRect (&r
, -r
.left
, -r
.top
);
9198 RectRgn (hilite_rgn
, &r
);
9199 ShowDragHilite (theDrag
, hilite_rgn
, true);
9200 DisposeRgn (hilite_rgn
);
9201 SetThemeCursor (kThemeCopyArrowCursor
);
9205 case kDragTrackingInWindow
:
9208 case kDragTrackingLeaveWindow
:
9211 struct frame
*f
= mac_window_to_frame (window
);
9213 HideDragHilite (theDrag
);
9214 SetThemeCursor (kThemeArrowCursor
);
9218 case kDragTrackingLeaveHandler
:
9226 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9227 DragReference theDrag
)
9231 FlavorFlags theFlags
;
9234 ItemReference theItem
;
9236 Size size
= sizeof (HFSFlavor
);
9237 Lisp_Object file_list
;
9239 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9240 return dragNotAcceptedErr
;
9243 GetDragMouse (theDrag
, &mouse
, 0L);
9244 CountDragItems (theDrag
, &items
);
9245 for (index
= 1; index
<= items
; index
++)
9247 /* Only handle file references. */
9248 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9249 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9250 if (result
== noErr
)
9255 err
= GetFlavorData (theDrag
, theItem
, flavorTypeHFS
,
9258 err
= AECoercePtr (typeFSS
, &data
.fileSpec
, sizeof (FSSpec
),
9259 TYPE_FILE_NAME
, &desc
);
9264 /* x-dnd functions expect undecoded filenames. */
9265 file
= make_uninit_string (AEGetDescDataSize (&desc
));
9266 err
= AEGetDescData (&desc
, SDATA (file
), SBYTES (file
));
9268 file_list
= Fcons (file
, file_list
);
9269 AEDisposeDesc (&desc
);
9273 /* If there are items in the list, construct an event and post it to
9274 the queue like an interrupt using kbd_buffer_store_event. */
9275 if (!NILP (file_list
))
9277 struct input_event event
;
9279 struct frame
*f
= mac_window_to_frame (window
);
9282 GlobalToLocal (&mouse
);
9283 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9285 event
.kind
= DRAG_N_DROP_EVENT
;
9287 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9288 event
.timestamp
= TickCount () * (1000 / 60);
9289 XSETINT (event
.x
, mouse
.h
);
9290 XSETINT (event
.y
, mouse
.v
);
9291 XSETFRAME (frame
, f
);
9292 event
.frame_or_window
= frame
;
9293 event
.arg
= file_list
;
9294 /* Post to the interrupt queue */
9295 kbd_buffer_store_event (&event
);
9296 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9298 ProcessSerialNumber psn
;
9299 GetCurrentProcess (&psn
);
9300 SetFrontProcess (&psn
);
9306 return dragNotAcceptedErr
;
9313 profiler_exit_proc ()
9315 ProfilerDump ("\pEmacs.prof");
9320 /* These few functions implement Emacs as a normal Mac application
9321 (almost): set up the heap and the Toolbox, handle necessary system
9322 events plus a few simple menu events. They also set up Emacs's
9323 access to functions defined in the rest of this file. Emacs uses
9324 function hooks to perform all its terminal I/O. A complete list of
9325 these functions appear in termhooks.h. For what they do, read the
9326 comments there and see also w32term.c and xterm.c. What's
9327 noticeably missing here is the event loop, which is normally
9328 present in most Mac application. After performing the necessary
9329 Mac initializations, main passes off control to emacs_main
9330 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9331 (defined further below) to read input. This is where
9332 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9339 #if __profile__ /* is the profiler on? */
9340 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9345 /* set creator and type for files created by MSL */
9350 do_init_managers ();
9355 do_check_ram_size ();
9358 init_emacs_passwd_dir ();
9362 init_coercion_handler ();
9364 initialize_applescript ();
9366 init_apple_event_handler ();
9372 /* set up argv array from STR# resource */
9373 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9377 /* free up AppleScript resources on exit */
9378 atexit (terminate_applescript
);
9380 #if __profile__ /* is the profiler on? */
9381 atexit (profiler_exit_proc
);
9384 /* 3rd param "envp" never used in emacs_main */
9385 (void) emacs_main (argc
, argv
, 0);
9388 /* Never reached - real exit in Fkill_emacs */
9393 /* Table for translating Mac keycode to X keysym values. Contributed
9395 Mapping for special keys is now identical to that in Apple X11
9396 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9397 on the right of the Cmd key on laptops, and fn + `enter' (->
9399 static unsigned char keycode_to_xkeysym_table
[] = {
9400 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9401 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9402 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9404 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9405 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9406 /*0x38*/ 0, 0, 0, 0,
9407 /*0x3C*/ 0, 0, 0, 0,
9409 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9410 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9411 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9412 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9414 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9415 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9416 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9417 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9419 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9420 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9421 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9422 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9424 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9425 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9426 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9427 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9432 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9434 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9435 return *xKeySym
!= 0;
9438 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9439 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9440 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9441 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9443 /*0x30*/ 0, 0, 0, 0,
9444 /*0x34*/ 0, 0, 0, 0,
9445 /*0x38*/ 0, 0, 0, 0,
9446 /*0x3C*/ 0, 0, 0, 0,
9448 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9449 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9450 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9451 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9453 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9454 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9455 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9456 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9458 /*0x60*/ 0, 0, 0, 0,
9459 /*0x64*/ 0, 0, 0, 0,
9460 /*0x68*/ 0, 0, 0, 0,
9461 /*0x6C*/ 0, 0, 0, 0,
9463 /*0x70*/ 0, 0, 0, 0,
9464 /*0x74*/ 0, 0, 0, 0,
9465 /*0x78*/ 0, 0, 0, 0,
9469 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9472 /* Use the special map to translate keys when function modifier is
9473 to be caught. KeyTranslate can't be used in that case.
9474 We can't detect the function key using the input_event.modifiers,
9475 because this uses the high word of an UInt32. Therefore,
9476 we'll just read it out of the original eventRef.
9480 /* TODO / known issues
9482 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9483 The above table always translates to lower characters. We need to use
9484 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9486 - The table is meant for English language keyboards, and it will work
9487 for many others with the exception of key combinations like Fn-ö on
9488 a German keyboard, which is currently mapped to Fn-;.
9489 How to solve this without keeping separate tables for all keyboards
9490 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9491 value for keycode with the modifiers in he high byte, i.e. no room for the
9492 Fn modifier. That's why we need the table.
9497 if (!NILP(Vmac_function_modifier
))
9499 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9500 sizeof (UInt32
), NULL
, &mods
);
9501 if (mods
& kEventKeyModifierFnMask
)
9502 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9504 return (*newCode
!= 0);
9512 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9514 EventModifiers mapped_modifiers
=
9515 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9516 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9517 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9519 if (mods
& mapped_modifiers
)
9521 /* This code comes from Keyboard Resource,
9522 Appendix C of IM - Text. This is necessary
9523 since shift is ignored in KCHR table
9524 translation when option or command is pressed.
9525 It also does not translate correctly
9526 control-shift chars like C-% so mask off shift
9529 Not done for combinations with the option key (alt)
9530 unless it is to be caught by Emacs: this is
9531 to preserve key combinations translated by the OS
9534 /* Mask off modifier keys that are mapped to some Emacs
9536 int new_modifiers
= mods
& ~mapped_modifiers
;
9537 /* set high byte of keycode to modifier high byte*/
9538 int new_keycode
= keycode
| new_modifiers
;
9539 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9540 unsigned long some_state
= 0;
9541 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9542 &some_state
) & 0xff;
9543 /* TO DO: Recognize two separate resulting characters, "for
9544 example, when the user presses Option-E followed by N, you
9545 can map this through the KeyTranslate function using the
9546 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9547 returns as two characters in the bytes labeled Character code
9548 1 and Character code 2." (from Carbon API doc) */
9556 #if !USE_CARBON_EVENTS
9557 static RgnHandle mouse_region
= NULL
;
9560 mac_wait_next_event (er
, sleep_time
, dequeue
)
9565 static EventRecord er_buf
= {nullEvent
};
9566 UInt32 target_tick
, current_tick
;
9567 EventMask event_mask
;
9569 if (mouse_region
== NULL
)
9570 mouse_region
= NewRgn ();
9572 event_mask
= everyEvent
;
9573 if (!mac_ready_for_apple_events
)
9574 event_mask
-= highLevelEventMask
;
9576 current_tick
= TickCount ();
9577 target_tick
= current_tick
+ sleep_time
;
9579 if (er_buf
.what
== nullEvent
)
9580 while (!WaitNextEvent (event_mask
, &er_buf
,
9581 target_tick
- current_tick
, mouse_region
))
9583 current_tick
= TickCount ();
9584 if (target_tick
<= current_tick
)
9590 er_buf
.what
= nullEvent
;
9593 #endif /* not USE_CARBON_EVENTS */
9595 /* Emacs calls this whenever it wants to read an input event from the
9598 XTread_socket (sd
, expected
, hold_quit
)
9600 struct input_event
*hold_quit
;
9602 struct input_event inev
;
9604 #if USE_CARBON_EVENTS
9606 EventTargetRef toolbox_dispatcher
;
9609 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9611 if (interrupt_input_blocked
)
9613 interrupt_input_pending
= 1;
9617 interrupt_input_pending
= 0;
9620 /* So people can tell when we have read the available input. */
9621 input_signal_count
++;
9625 #if USE_CARBON_EVENTS
9626 toolbox_dispatcher
= GetEventDispatcherTarget ();
9628 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9629 kEventRemoveFromQueue
, &eventRef
))
9630 #else /* !USE_CARBON_EVENTS */
9631 while (mac_wait_next_event (&er
, 0, true))
9632 #endif /* !USE_CARBON_EVENTS */
9636 unsigned long timestamp
;
9638 /* It is necessary to set this (additional) argument slot of an
9639 event to nil because keyboard.c protects incompletely
9640 processed event from being garbage collected by placing them
9641 in the kbd_buffer_gcpro vector. */
9643 inev
.kind
= NO_EVENT
;
9646 #if USE_CARBON_EVENTS
9647 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9649 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9652 #if USE_CARBON_EVENTS
9653 /* Handle new events */
9654 if (!mac_convert_event_ref (eventRef
, &er
))
9656 /* There used to be a handler for the kEventMouseWheelMoved
9657 event here. But as of Mac OS X 10.4, this kind of event
9658 is not directly posted to the main event queue by
9659 two-finger scrolling on the trackpad. Instead, some
9660 private event is posted and it is converted to a wheel
9661 event by the default handler for the application target.
9662 The converted one can be received by a Carbon event
9663 handler installed on a window target. */
9664 read_socket_inev
= &inev
;
9665 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9666 read_socket_inev
= NULL
;
9669 #endif /* USE_CARBON_EVENTS */
9675 WindowPtr window_ptr
;
9676 ControlPartCode part_code
;
9679 #if USE_CARBON_EVENTS
9680 /* This is needed to send mouse events like aqua window
9681 buttons to the correct handler. */
9682 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9683 != eventNotHandledErr
)
9686 last_mouse_glyph_frame
= 0;
9688 if (dpyinfo
->grabbed
&& last_mouse_frame
9689 && FRAME_LIVE_P (last_mouse_frame
))
9691 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9692 part_code
= inContent
;
9696 part_code
= FindWindow (er
.where
, &window_ptr
);
9697 if (tip_window
&& window_ptr
== tip_window
)
9699 HideWindow (tip_window
);
9700 part_code
= FindWindow (er
.where
, &window_ptr
);
9704 if (er
.what
!= mouseDown
&&
9705 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9711 f
= mac_focus_frame (dpyinfo
);
9712 saved_menu_event_location
= er
.where
;
9713 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9714 XSETFRAME (inev
.frame_or_window
, f
);
9718 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9719 SelectWindow (window_ptr
);
9722 ControlPartCode control_part_code
;
9724 Point mouse_loc
= er
.where
;
9726 ControlKind control_kind
;
9729 f
= mac_window_to_frame (window_ptr
);
9730 /* convert to local coordinates of new window */
9731 SetPortWindowPort (window_ptr
);
9733 GlobalToLocal (&mouse_loc
);
9734 #if TARGET_API_MAC_CARBON
9735 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9736 &control_part_code
);
9739 GetControlKind (ch
, &control_kind
);
9742 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9746 #if USE_CARBON_EVENTS
9747 inev
.code
= mac_get_mouse_btn (eventRef
);
9748 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9750 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9751 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9753 XSETINT (inev
.x
, mouse_loc
.h
);
9754 XSETINT (inev
.y
, mouse_loc
.v
);
9756 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9758 #ifndef USE_TOOLKIT_SCROLL_BARS
9759 /* control_part_code becomes kControlNoPart if
9760 a progress indicator is clicked. */
9761 && control_part_code
!= kControlNoPart
9762 #else /* USE_TOOLKIT_SCROLL_BARS */
9764 && control_kind
.kind
== kControlKindScrollBar
9765 #endif /* MAC_OSX */
9766 #endif /* USE_TOOLKIT_SCROLL_BARS */
9769 struct scroll_bar
*bar
;
9771 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9773 bar
= tracked_scroll_bar
;
9774 #ifndef USE_TOOLKIT_SCROLL_BARS
9775 control_part_code
= kControlIndicatorPart
;
9779 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9780 #ifdef USE_TOOLKIT_SCROLL_BARS
9781 /* Make the "Ctrl-Mouse-2 splits window" work
9782 for toolkit scroll bars. */
9783 if (er
.modifiers
& controlKey
)
9784 x_scroll_bar_handle_click (bar
, control_part_code
,
9786 else if (er
.what
== mouseDown
)
9787 x_scroll_bar_handle_press (bar
, control_part_code
,
9790 x_scroll_bar_handle_release (bar
, &inev
);
9791 #else /* not USE_TOOLKIT_SCROLL_BARS */
9792 x_scroll_bar_handle_click (bar
, control_part_code
,
9794 if (er
.what
== mouseDown
9795 && control_part_code
== kControlIndicatorPart
)
9796 tracked_scroll_bar
= bar
;
9798 tracked_scroll_bar
= NULL
;
9799 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9804 int x
= mouse_loc
.h
;
9805 int y
= mouse_loc
.v
;
9807 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9808 if (EQ (window
, f
->tool_bar_window
))
9810 if (er
.what
== mouseDown
)
9811 handle_tool_bar_click (f
, x
, y
, 1, 0);
9813 handle_tool_bar_click (f
, x
, y
, 0,
9819 XSETFRAME (inev
.frame_or_window
, f
);
9820 inev
.kind
= MOUSE_CLICK_EVENT
;
9824 if (er
.what
== mouseDown
)
9826 dpyinfo
->grabbed
|= (1 << inev
.code
);
9827 last_mouse_frame
= f
;
9830 last_tool_bar_item
= -1;
9834 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9835 /* If a button is released though it was not
9836 previously pressed, that would be because
9837 of multi-button emulation. */
9838 dpyinfo
->grabbed
= 0;
9840 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9843 /* Ignore any mouse motion that happened before
9844 this event; any subsequent mouse-movement Emacs
9845 events should reflect only motion after the
9850 #ifdef USE_TOOLKIT_SCROLL_BARS
9851 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9856 inev
.modifiers
|= down_modifier
;
9859 inev
.modifiers
|= up_modifier
;
9866 #if TARGET_API_MAC_CARBON
9867 DragWindow (window_ptr
, er
.where
, NULL
);
9868 #else /* not TARGET_API_MAC_CARBON */
9869 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9870 #endif /* not TARGET_API_MAC_CARBON */
9871 /* Update the frame parameters. */
9873 struct frame
*f
= mac_window_to_frame (window_ptr
);
9875 if (f
&& !f
->async_iconified
)
9876 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9881 if (TrackGoAway (window_ptr
, er
.where
))
9883 inev
.kind
= DELETE_WINDOW_EVENT
;
9884 XSETFRAME (inev
.frame_or_window
,
9885 mac_window_to_frame (window_ptr
));
9889 /* window resize handling added --ben */
9891 do_grow_window (window_ptr
, &er
);
9894 /* window zoom handling added --ben */
9897 if (TrackBox (window_ptr
, er
.where
, part_code
))
9898 do_zoom_window (window_ptr
, part_code
);
9908 #if USE_CARBON_EVENTS
9909 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9910 != eventNotHandledErr
)
9913 do_window_update ((WindowPtr
) er
.message
);
9918 #if USE_CARBON_EVENTS
9919 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9920 != eventNotHandledErr
)
9923 switch ((er
.message
>> 24) & 0x000000FF)
9925 case suspendResumeMessage
:
9926 if ((er
.message
& resumeFlag
) == 1)
9932 case mouseMovedMessage
:
9933 #if !USE_CARBON_EVENTS
9934 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9935 er
.where
.h
+ 1, er
.where
.v
+ 1);
9937 previous_help_echo_string
= help_echo_string
;
9938 help_echo_string
= Qnil
;
9940 if (dpyinfo
->grabbed
&& last_mouse_frame
9941 && FRAME_LIVE_P (last_mouse_frame
))
9942 f
= last_mouse_frame
;
9944 f
= dpyinfo
->x_focus_frame
;
9946 if (dpyinfo
->mouse_face_hidden
)
9948 dpyinfo
->mouse_face_hidden
= 0;
9949 clear_mouse_face (dpyinfo
);
9954 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9955 Point mouse_pos
= er
.where
;
9957 SetPortWindowPort (wp
);
9959 GlobalToLocal (&mouse_pos
);
9961 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9962 #ifdef USE_TOOLKIT_SCROLL_BARS
9963 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9965 #else /* not USE_TOOLKIT_SCROLL_BARS */
9966 x_scroll_bar_note_movement (tracked_scroll_bar
,
9968 - XINT (tracked_scroll_bar
->top
),
9969 er
.when
* (1000 / 60));
9970 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9973 /* Generate SELECT_WINDOW_EVENTs when needed. */
9974 if (mouse_autoselect_window
)
9978 window
= window_from_coordinates (f
,
9983 /* Window will be selected only when it is
9984 not selected now and last mouse movement
9985 event was not in it. Minibuffer window
9986 will be selected iff it is active. */
9987 if (WINDOWP (window
)
9988 && !EQ (window
, last_window
)
9989 && !EQ (window
, selected_window
))
9991 inev
.kind
= SELECT_WINDOW_EVENT
;
9992 inev
.frame_or_window
= window
;
9997 if (!note_mouse_movement (f
, &mouse_pos
))
9998 help_echo_string
= previous_help_echo_string
;
10002 /* If the contents of the global variable
10003 help_echo_string has changed, generate a
10005 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
10013 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
10015 #if USE_CARBON_EVENTS
10016 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10017 != eventNotHandledErr
)
10020 if (window_ptr
== tip_window
)
10022 HideWindow (tip_window
);
10026 if (!is_emacs_window (window_ptr
))
10029 if ((er
.modifiers
& activeFlag
) != 0)
10031 /* A window has been activated */
10032 Point mouse_loc
= er
.where
;
10034 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10036 SetPortWindowPort (window_ptr
);
10037 GlobalToLocal (&mouse_loc
);
10038 /* Window-activated event counts as mouse movement,
10039 so update things that depend on mouse position. */
10040 note_mouse_movement (mac_window_to_frame (window_ptr
),
10045 /* A window has been deactivated */
10046 #if USE_TOOLKIT_SCROLL_BARS
10047 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10049 struct input_event event
;
10051 EVENT_INIT (event
);
10052 event
.kind
= NO_EVENT
;
10053 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10054 if (event
.kind
!= NO_EVENT
)
10056 event
.timestamp
= timestamp
;
10057 kbd_buffer_store_event_hold (&event
, hold_quit
);
10062 dpyinfo
->grabbed
= 0;
10064 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10066 f
= mac_window_to_frame (window_ptr
);
10067 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10069 /* If we move outside the frame, then we're
10070 certainly no longer on any text in the
10072 clear_mouse_face (dpyinfo
);
10073 dpyinfo
->mouse_face_mouse_frame
= 0;
10076 /* Generate a nil HELP_EVENT to cancel a help-echo.
10077 Do it only if there's something to cancel.
10078 Otherwise, the startup message is cleared when the
10079 mouse leaves the frame. */
10080 if (any_help_event_p
)
10089 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10092 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10093 /* When using Carbon Events, we need to pass raw keyboard
10094 events to the TSM ourselves. If TSM handles it, it
10095 will pass back noErr, otherwise it will pass back
10096 "eventNotHandledErr" and we can process it
10098 if ((mac_pass_command_to_system
10099 || !(er
.modifiers
& cmdKey
))
10100 && (mac_pass_control_to_system
10101 || !(er
.modifiers
& controlKey
))
10102 && (NILP (Vmac_option_modifier
)
10103 || !(er
.modifiers
& optionKey
)))
10104 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10105 != eventNotHandledErr
)
10110 if (dpyinfo
->x_focus_frame
== NULL
)
10112 /* Beep if keyboard input occurs when all the frames
10120 static SInt16 last_key_script
= -1;
10121 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10123 if (last_key_script
!= current_key_script
)
10125 struct input_event event
;
10127 EVENT_INIT (event
);
10128 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10130 event
.code
= current_key_script
;
10131 event
.timestamp
= timestamp
;
10132 kbd_buffer_store_event (&event
);
10135 last_key_script
= current_key_script
;
10140 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10142 clear_mouse_face (dpyinfo
);
10143 dpyinfo
->mouse_face_hidden
= 1;
10146 /* translate the keycode back to determine the original key */
10147 /* Convert key code if function key is pressed.
10148 Otherwise, if non-ASCII-event, take care of that
10149 without re-translating the key code. */
10150 #if USE_CARBON_EVENTS
10151 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10153 inev
.code
= xkeysym
;
10154 /* this doesn't work - tried to add shift modifiers */
10156 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10157 xkeysym
| 0x80, xkeysym
);
10158 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10162 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10164 inev
.code
= 0xff00 | xkeysym
;
10165 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10170 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10171 er
.message
& charCodeMask
);
10172 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10176 #if USE_CARBON_EVENTS
10177 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10179 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10181 inev
.modifiers
|= (extra_keyboard_modifiers
10182 & (meta_modifier
| alt_modifier
10183 | hyper_modifier
| super_modifier
));
10184 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10187 case kHighLevelEvent
:
10188 read_socket_inev
= &inev
;
10189 AEProcessAppleEvent (&er
);
10190 read_socket_inev
= NULL
;
10196 #if USE_CARBON_EVENTS
10197 ReleaseEvent (eventRef
);
10200 if (inev
.kind
!= NO_EVENT
)
10202 inev
.timestamp
= timestamp
;
10203 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10208 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10213 XSETFRAME (frame
, f
);
10219 any_help_event_p
= 1;
10220 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10221 help_echo_object
, help_echo_pos
);
10225 help_echo_string
= Qnil
;
10226 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10233 /* If the focus was just given to an autoraising frame,
10235 /* ??? This ought to be able to handle more than one such frame. */
10236 if (pending_autoraise_frame
)
10238 x_raise_frame (pending_autoraise_frame
);
10239 pending_autoraise_frame
= 0;
10242 #if !USE_CARBON_EVENTS
10243 /* Check which frames are still visible. We do this here because
10244 there doesn't seem to be any direct notification from the Window
10245 Manager that the visibility of a window has changed (at least,
10246 not in all cases). */
10248 Lisp_Object tail
, frame
;
10250 FOR_EACH_FRAME (tail
, frame
)
10252 struct frame
*f
= XFRAME (frame
);
10254 /* The tooltip has been drawn already. Avoid the
10255 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10256 if (EQ (frame
, tip_frame
))
10259 if (FRAME_MAC_P (f
))
10260 mac_handle_visibility_change (f
);
10271 /* Need to override CodeWarrior's input function so no conversion is
10272 done on newlines Otherwise compiled functions in .elc files will be
10273 read incorrectly. Defined in ...:MSL C:MSL
10274 Common:Source:buffer_io.c. */
10277 __convert_to_newlines (unsigned char * p
, size_t * n
)
10279 #pragma unused(p,n)
10283 __convert_from_newlines (unsigned char * p
, size_t * n
)
10285 #pragma unused(p,n)
10291 make_mac_terminal_frame (struct frame
*f
)
10296 XSETFRAME (frame
, f
);
10298 f
->output_method
= output_mac
;
10299 f
->output_data
.mac
= (struct mac_output
*)
10300 xmalloc (sizeof (struct mac_output
));
10301 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10303 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10305 FRAME_COLS (f
) = 96;
10306 FRAME_LINES (f
) = 4;
10308 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10309 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10311 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10313 f
->output_data
.mac
->cursor_pixel
= 0;
10314 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10315 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10316 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10318 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10319 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10320 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10321 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10322 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10323 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10325 FRAME_FONTSET (f
) = -1;
10326 f
->output_data
.mac
->explicit_parent
= 0;
10329 f
->border_width
= 0;
10331 f
->internal_border_width
= 0;
10336 f
->new_text_cols
= 0;
10337 f
->new_text_lines
= 0;
10339 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10340 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10341 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10345 if (!(FRAME_MAC_WINDOW (f
) =
10346 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10347 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10349 /* so that update events can find this mac_output struct */
10350 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10356 /* Need to be initialized for unshow_buffer in window.c. */
10357 selected_window
= f
->selected_window
;
10359 Fmodify_frame_parameters (frame
,
10360 Fcons (Fcons (Qfont
,
10361 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10362 Fmodify_frame_parameters (frame
,
10363 Fcons (Fcons (Qforeground_color
,
10364 build_string ("black")), Qnil
));
10365 Fmodify_frame_parameters (frame
,
10366 Fcons (Fcons (Qbackground_color
,
10367 build_string ("white")), Qnil
));
10372 /***********************************************************************
10374 ***********************************************************************/
10376 int mac_initialized
= 0;
10379 mac_initialize_display_info ()
10381 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10382 GDHandle main_device_handle
;
10384 bzero (dpyinfo
, sizeof (*dpyinfo
));
10387 dpyinfo
->mac_id_name
10388 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10389 + SCHARS (Vsystem_name
)
10391 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10392 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10394 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10395 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10398 main_device_handle
= LMGetMainDevice();
10400 dpyinfo
->reference_count
= 0;
10401 dpyinfo
->resx
= 72.0;
10402 dpyinfo
->resy
= 72.0;
10403 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10405 /* HasDepth returns true if it is possible to have a 32 bit display,
10406 but this may not be what is actually used. Mac OSX can do better.
10407 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10408 header for CGGetActiveDisplayList says that the first display returned
10409 is the active one, so we use that. */
10411 CGDirectDisplayID disp_id
[1];
10412 CGDisplayCount disp_count
;
10413 CGDisplayErr error_code
;
10415 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10416 if (error_code
!= 0)
10417 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10419 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10422 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10423 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10424 gdDevType
, dpyinfo
->color_p
))
10427 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10428 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10429 dpyinfo
->grabbed
= 0;
10430 dpyinfo
->root_window
= NULL
;
10431 dpyinfo
->image_cache
= make_image_cache ();
10433 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10434 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10435 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10436 dpyinfo
->mouse_face_window
= Qnil
;
10437 dpyinfo
->mouse_face_overlay
= Qnil
;
10438 dpyinfo
->mouse_face_hidden
= 0;
10443 mac_make_rdb (xrm_option
)
10446 XrmDatabase database
;
10448 database
= xrm_get_preference_database (NULL
);
10450 xrm_merge_string_database (database
, xrm_option
);
10455 struct mac_display_info
*
10456 mac_term_init (display_name
, xrm_option
, resource_name
)
10457 Lisp_Object display_name
;
10459 char *resource_name
;
10461 struct mac_display_info
*dpyinfo
;
10465 if (!mac_initialized
)
10468 mac_initialized
= 1;
10471 if (x_display_list
)
10472 error ("Sorry, this version can only handle one display");
10474 mac_initialize_display_info ();
10476 dpyinfo
= &one_mac_display_info
;
10478 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10480 /* Put this display on the chain. */
10481 dpyinfo
->next
= x_display_list
;
10482 x_display_list
= dpyinfo
;
10484 /* Put it on x_display_name_list. */
10485 x_display_name_list
= Fcons (Fcons (display_name
,
10486 Fcons (Qnil
, dpyinfo
->xrdb
)),
10487 x_display_name_list
);
10488 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10494 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10497 x_delete_display (dpyinfo
)
10498 struct mac_display_info
*dpyinfo
;
10502 /* Discard this display from x_display_name_list and x_display_list.
10503 We can't use Fdelq because that can quit. */
10504 if (! NILP (x_display_name_list
)
10505 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10506 x_display_name_list
= XCDR (x_display_name_list
);
10511 tail
= x_display_name_list
;
10512 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10514 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10516 XSETCDR (tail
, XCDR (XCDR (tail
)));
10519 tail
= XCDR (tail
);
10523 if (x_display_list
== dpyinfo
)
10524 x_display_list
= dpyinfo
->next
;
10527 struct x_display_info
*tail
;
10529 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10530 if (tail
->next
== dpyinfo
)
10531 tail
->next
= tail
->next
->next
;
10534 /* Free the font names in the font table. */
10535 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10536 if (dpyinfo
->font_table
[i
].name
)
10538 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10539 xfree (dpyinfo
->font_table
[i
].full_name
);
10540 xfree (dpyinfo
->font_table
[i
].name
);
10543 if (dpyinfo
->font_table
->font_encoder
)
10544 xfree (dpyinfo
->font_table
->font_encoder
);
10546 xfree (dpyinfo
->font_table
);
10547 xfree (dpyinfo
->mac_id_name
);
10549 if (x_display_list
== 0)
10551 mac_clear_font_name_table ();
10552 bzero (dpyinfo
, sizeof (*dpyinfo
));
10561 extern int inhibit_window_system
;
10562 extern int noninteractive
;
10563 CFBundleRef appsBundle
;
10566 /* No need to test if already -nw*/
10567 if (inhibit_window_system
|| noninteractive
)
10570 appsBundle
= CFBundleGetMainBundle();
10571 if (appsBundle
!= NULL
)
10573 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10574 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10575 /* We found the bundle identifier, now we know we are valid. */
10582 /* MAC_TODO: Have this start the bundled executable */
10584 /* For now, prevent the fatal error by bringing it up in the terminal */
10585 inhibit_window_system
= 1;
10589 MakeMeTheFrontProcess ()
10591 ProcessSerialNumber psn
;
10594 err
= GetCurrentProcess (&psn
);
10596 (void) SetFrontProcess (&psn
);
10599 /***** Code to handle C-g testing *****/
10601 /* Contains the Mac modifier formed from quit_char */
10602 int mac_quit_char_modifiers
= 0;
10603 int mac_quit_char_keycode
;
10604 extern int quit_char
;
10607 mac_determine_quit_char_modifiers()
10609 /* Todo: Determine modifiers from quit_char. */
10610 UInt32 qc_modifiers
= ctrl_modifier
;
10612 /* Map modifiers */
10613 mac_quit_char_modifiers
= 0;
10614 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10615 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10616 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10620 init_quit_char_handler ()
10622 /* TODO: Let this support keys other the 'g' */
10623 mac_quit_char_keycode
= 5;
10624 /* Look at <architecture/adb_kb_map.h> for details */
10625 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10627 mac_determine_quit_char_modifiers();
10629 #endif /* MAC_OSX */
10637 MenuItemIndex menu_index
;
10639 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10640 &menu
, &menu_index
);
10642 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10643 #if USE_CARBON_EVENTS
10644 EnableMenuCommand (NULL
, kHICommandPreferences
);
10645 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10646 &menu
, &menu_index
);
10649 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10650 InsertMenuItemTextWithCFString (menu
, NULL
,
10651 0, kMenuItemAttrSeparator
, 0);
10652 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10653 0, 0, kHICommandAbout
);
10655 #endif /* USE_CARBON_EVENTS */
10656 #else /* !MAC_OSX */
10657 #if USE_CARBON_EVENTS
10658 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10664 /* Set up use of X before we make the first connection. */
10666 extern frame_parm_handler mac_frame_parm_handlers
[];
10668 static struct redisplay_interface x_redisplay_interface
=
10670 mac_frame_parm_handlers
,
10674 x_clear_end_of_line
,
10676 x_after_update_window_line
,
10677 x_update_window_begin
,
10678 x_update_window_end
,
10681 0, /* flush_display_optional */
10682 x_clear_window_mouse_face
,
10683 x_get_glyph_overhangs
,
10684 x_fix_overlapping_area
,
10685 x_draw_fringe_bitmap
,
10686 0, /* define_fringe_bitmap */
10687 0, /* destroy_fringe_bitmap */
10688 mac_per_char_metric
,
10690 mac_compute_glyph_string_overhangs
,
10691 x_draw_glyph_string
,
10692 mac_define_frame_cursor
,
10693 mac_clear_frame_area
,
10694 mac_draw_window_cursor
,
10695 mac_draw_vertical_window_border
,
10696 mac_shift_glyphs_for_insert
10702 rif
= &x_redisplay_interface
;
10704 clear_frame_hook
= x_clear_frame
;
10705 ins_del_lines_hook
= x_ins_del_lines
;
10706 delete_glyphs_hook
= x_delete_glyphs
;
10707 ring_bell_hook
= XTring_bell
;
10708 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10709 set_terminal_modes_hook
= XTset_terminal_modes
;
10710 update_begin_hook
= x_update_begin
;
10711 update_end_hook
= x_update_end
;
10712 set_terminal_window_hook
= XTset_terminal_window
;
10713 read_socket_hook
= XTread_socket
;
10714 frame_up_to_date_hook
= XTframe_up_to_date
;
10715 mouse_position_hook
= XTmouse_position
;
10716 frame_rehighlight_hook
= XTframe_rehighlight
;
10717 frame_raise_lower_hook
= XTframe_raise_lower
;
10719 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10720 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10721 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10722 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10724 TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
10725 TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
10726 TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
10727 TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
10728 TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
10733 last_tool_bar_item
= -1;
10734 any_help_event_p
= 0;
10736 /* Try to use interrupt input; if we can't, then start polling. */
10737 Fset_input_interrupt_mode (Qt
);
10741 #if TARGET_API_MAC_CARBON
10743 #if USE_CARBON_EVENTS
10745 init_service_handler ();
10747 init_quit_char_handler ();
10748 #endif /* MAC_OSX */
10750 init_command_handler ();
10753 #endif /* USE_CARBON_EVENTS */
10756 init_coercion_handler ();
10758 init_apple_event_handler ();
10760 if (!inhibit_window_system
)
10761 MakeMeTheFrontProcess ();
10772 staticpro (&x_error_message_string
);
10773 x_error_message_string
= Qnil
;
10776 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10777 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10778 Qalt
= intern ("alt"); staticpro (&Qalt
);
10779 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10780 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10781 Qmodifier_value
= intern ("modifier-value");
10782 staticpro (&Qmodifier_value
);
10784 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10785 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10786 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10787 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10788 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10790 #if USE_CARBON_EVENTS
10791 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
10793 Qservices
= intern ("services"); staticpro (&Qservices
);
10794 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10795 Qperform
= intern ("perform"); staticpro (&Qperform
);
10800 Fprovide (intern ("mac-carbon"), Qnil
);
10803 staticpro (&Qreverse
);
10804 Qreverse
= intern ("reverse");
10806 staticpro (&x_display_name_list
);
10807 x_display_name_list
= Qnil
;
10809 staticpro (&last_mouse_scroll_bar
);
10810 last_mouse_scroll_bar
= Qnil
;
10812 staticpro (&fm_font_family_alist
);
10813 fm_font_family_alist
= Qnil
;
10816 staticpro (&atsu_font_id_hash
);
10817 atsu_font_id_hash
= Qnil
;
10820 /* We don't yet support this, but defining this here avoids whining
10821 from cus-start.el and other places, like "M-x set-variable". */
10822 DEFVAR_BOOL ("x-use-underline-position-properties",
10823 &x_use_underline_position_properties
,
10824 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10825 nil means ignore them. If you encounter fonts with bogus
10826 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10827 to 4.1, set this to nil.
10829 NOTE: Not supported on Mac yet. */);
10830 x_use_underline_position_properties
= 0;
10832 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10833 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10834 #ifdef USE_TOOLKIT_SCROLL_BARS
10835 Vx_toolkit_scroll_bars
= Qt
;
10837 Vx_toolkit_scroll_bars
= Qnil
;
10840 staticpro (&last_mouse_motion_frame
);
10841 last_mouse_motion_frame
= Qnil
;
10843 /* Variables to configure modifier key assignment. */
10845 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
10846 doc
: /* *Modifier key assumed when the Mac control key is pressed.
10847 The value can be `control', `meta', `alt', `hyper', or `super' for the
10848 respective modifier. The default is `control'. */);
10849 Vmac_control_modifier
= Qcontrol
;
10851 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10852 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
10853 The value can be `control', `meta', `alt', `hyper', or `super' for the
10854 respective modifier. If the value is nil then the key will act as the
10855 normal Mac control modifier, and the option key can be used to compose
10856 characters depending on the chosen Mac keyboard setting. */);
10857 Vmac_option_modifier
= Qnil
;
10859 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
10860 doc
: /* *Modifier key assumed when the Mac command key is pressed.
10861 The value can be `control', `meta', `alt', `hyper', or `super' for the
10862 respective modifier. The default is `meta'. */);
10863 Vmac_command_modifier
= Qmeta
;
10865 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
10866 doc
: /* *Modifier key assumed when the Mac function key is pressed.
10867 The value can be `control', `meta', `alt', `hyper', or `super' for the
10868 respective modifier. Note that remapping the function key may lead to
10869 unexpected results for some keys on non-US/GB keyboards. */);
10870 Vmac_function_modifier
= Qnil
;
10872 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10873 &Vmac_emulate_three_button_mouse
,
10874 doc
: /* *Specify a way of three button mouse emulation.
10875 The value can be nil, t, or the symbol `reverse'.
10876 nil means that no emulation should be done and the modifiers should be
10877 placed on the mouse-1 event.
10878 t means that when the option-key is held down while pressing the mouse
10879 button, the click will register as mouse-2 and while the command-key
10880 is held down, the click will register as mouse-3.
10881 The symbol `reverse' means that the option-key will register for
10882 mouse-3 and the command-key will register for mouse-2. */);
10883 Vmac_emulate_three_button_mouse
= Qnil
;
10885 #if USE_CARBON_EVENTS
10886 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
10887 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
10888 Otherwise, the right click will be treated as mouse-2 and the wheel
10889 button will be mouse-3. */);
10890 mac_wheel_button_is_mouse_2
= 1;
10892 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
10893 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
10894 mac_pass_command_to_system
= 1;
10896 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
10897 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
10898 mac_pass_control_to_system
= 1;
10902 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
10903 doc
: /* *If non-nil, allow anti-aliasing.
10904 The text will be rendered using Core Graphics text rendering which
10905 may anti-alias the text. */);
10906 mac_use_core_graphics
= 0;
10908 /* Register an entry for `mac-roman' so that it can be used when
10909 creating the terminal frame on Mac OS 9 before loading
10910 term/mac-win.elc. */
10911 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10912 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
10913 Each entry should be of the form:
10915 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10917 where CHARSET-NAME is a string used in font names to identify the
10918 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
10919 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
10920 Vmac_charset_info_alist
=
10921 Fcons (list3 (build_string ("mac-roman"),
10922 make_number (smRoman
), Qnil
), Qnil
);
10925 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10926 (do not change this comment) */