1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 /* Contributed by Andrew Choi (akochoi@mac.com). */
30 #include "blockinput.h"
38 #if TARGET_API_MAC_CARBON
39 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
40 obtain events from the event queue. If set to 0, WaitNextEvent is
42 #define USE_CARBON_EVENTS 1
43 #else /* not TARGET_API_MAC_CARBON */
44 #include <Quickdraw.h>
45 #include <ToolUtils.h>
49 #include <Resources.h>
51 #include <TextUtils.h>
55 #if defined (__MRC__) || (__MSL__ >= 0x6000)
56 #include <ControlDefinitions.h>
62 #endif /* not TARGET_API_MAC_CARBON */
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 ();
288 GetClip (saved_port_clip_region
);
289 SectRgn (saved_port_clip_region
, region
, new_region
);
290 SetClip (new_region
);
295 mac_end_clip (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
630 kATSLineIsDisplayOnly
| kATSLineFractDisable
633 ATSUAttributeValuePtr values
[] = {&line_layout
};
635 err
= ATSUCreateTextLayoutWithTextPtr (text
,
636 kATSUFromTextBeginning
,
642 err
= ATSUSetLayoutControls (saved_text_layout
,
643 sizeof (tags
) / sizeof (tags
[0]),
644 tags
, sizes
, values
);
645 /* XXX: Should we do this? */
647 err
= ATSUSetTransientFontMatching (saved_text_layout
, true);
651 err
= ATSUSetRunStyle (saved_text_layout
, style
,
652 kATSUFromTextBeginning
, kATSUToTextEnd
);
654 err
= ATSUSetTextPointerLocation (saved_text_layout
, text
,
655 kATSUFromTextBeginning
,
661 *text_layout
= saved_text_layout
;
668 mac_invert_rectangle (f
, x
, y
, width
, height
)
671 unsigned int width
, height
;
675 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
677 SetRect (&r
, x
, y
, x
+ width
, y
+ height
);
684 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, mode
, bytes_per_char
)
689 int nchars
, mode
, bytes_per_char
;
691 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
692 UInt32 textFlags
, savedFlags
;
693 if (mac_use_core_graphics
) {
694 textFlags
= kQDUseCGTextRendering
;
695 savedFlags
= SwapQDTextFlags(textFlags
);
699 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
701 RGBForeColor (GC_FORE_COLOR (gc
));
703 RGBBackColor (GC_BACK_COLOR (gc
));
706 if (GC_FONT (gc
)->mac_style
)
709 ATSUTextLayout text_layout
;
711 xassert (bytes_per_char
== 2);
713 #ifndef WORDS_BIG_ENDIAN
716 UniChar
*text
= (UniChar
*)buf
;
718 for (i
= 0; i
< nchars
; i
++)
719 text
[i
] = EndianU16_BtoN (text
[i
]);
722 err
= atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr
)buf
,
724 GC_FONT (gc
)->mac_style
,
729 if (!mac_use_core_graphics
)
732 mac_begin_clip (GC_CLIP_REGION (gc
));
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
)
753 CGContextTranslateCTM (context
, 0, port_height
);
754 CGContextScaleCTM (context
, 1, -1);
755 CGContextClipToRects (context
, gc
->clip_rects
,
757 CGContextScaleCTM (context
, 1, -1);
758 CGContextTranslateCTM (context
, 0, -port_height
);
760 CGContextSetRGBFillColor
762 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
763 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
764 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
766 err
= ATSUSetLayoutControls (text_layout
,
767 sizeof (tags
) / sizeof (tags
[0]),
768 tags
, sizes
, values
);
770 ATSUDrawText (text_layout
,
771 kATSUFromTextBeginning
, kATSUToTextEnd
,
772 Long2Fix (x
), Long2Fix (port_height
- y
));
773 CGContextSynchronize (context
);
774 QDEndCGContext (port
, &context
);
776 /* This doesn't work on Mac OS X 10.1. */
777 ATSUClearLayoutControls (text_layout
,
778 sizeof (tags
) / sizeof (tags
[0]),
781 ATSUSetLayoutControls (text_layout
,
782 sizeof (tags
) / sizeof (tags
[0]),
783 tags
, sizes
, values
);
792 TextFont (GC_FONT (gc
)->mac_fontnum
);
793 TextSize (GC_FONT (gc
)->mac_fontsize
);
794 TextFace (GC_FONT (gc
)->mac_fontface
);
797 mac_begin_clip (GC_CLIP_REGION (gc
));
799 DrawText (buf
, 0, nchars
* bytes_per_char
);
800 mac_end_clip (GC_CLIP_REGION (gc
));
806 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
807 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
808 if (mac_use_core_graphics
)
809 SwapQDTextFlags(savedFlags
);
814 /* Mac replacement for XDrawString. */
817 mac_draw_string (f
, gc
, x
, y
, buf
, nchars
)
824 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcOr
, 1);
828 /* Mac replacement for XDrawString16. */
831 mac_draw_string_16 (f
, gc
, x
, y
, buf
, nchars
)
838 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcOr
, 2);
842 /* Mac replacement for XDrawImageString. */
845 mac_draw_image_string (f
, gc
, x
, y
, buf
, nchars
)
852 mac_draw_string_common (f
, gc
, x
, y
, buf
, nchars
, srcCopy
, 1);
856 /* Mac replacement for XDrawString16. */
859 mac_draw_image_string_16 (f
, gc
, x
, y
, buf
, nchars
)
866 mac_draw_string_common (f
, gc
, x
, y
, (char *) buf
, nchars
, srcCopy
, 2);
870 /* Mac replacement for XQueryTextExtents, but takes a character. If
871 STYLE is NULL, measurement is done by QuickDraw Text routines for
872 the font of the current graphics port. If CG_GLYPH is not NULL,
873 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */
876 mac_query_char_extents (style
, c
,
877 font_ascent_return
, font_descent_return
,
878 overall_return
, cg_glyph
)
885 int *font_ascent_return
, *font_descent_return
;
886 XCharStruct
*overall_return
;
887 #if USE_CG_TEXT_DRAWING
900 ATSUTextLayout text_layout
;
903 err
= atsu_get_text_layout_with_text_ptr (&ch
, 1, style
, &text_layout
);
906 ATSTrapezoid glyph_bounds
;
908 err
= ATSUGetGlyphBounds (text_layout
, 0, 0,
909 kATSUFromTextBeginning
, kATSUToTextEnd
,
910 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
911 kATSUseFractionalOrigins
,
913 kATSUseDeviceOrigins
,
915 1, &glyph_bounds
, NULL
);
918 xassert (glyph_bounds
.lowerRight
.x
- glyph_bounds
.lowerLeft
.x
919 == glyph_bounds
.upperRight
.x
- glyph_bounds
.upperLeft
.x
);
921 width
= Fix2Long (glyph_bounds
.upperRight
.x
922 - glyph_bounds
.upperLeft
.x
);
923 if (font_ascent_return
)
924 *font_ascent_return
= -Fix2Long (glyph_bounds
.upperLeft
.y
);
925 if (font_descent_return
)
926 *font_descent_return
= Fix2Long (glyph_bounds
.lowerLeft
.y
);
929 if (err
== noErr
&& overall_return
)
931 err
= ATSUMeasureTextImage (text_layout
,
932 kATSUFromTextBeginning
, kATSUToTextEnd
,
935 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
936 #if USE_CG_TEXT_DRAWING
937 if (err
== noErr
&& cg_glyph
)
940 ATSUGlyphInfoArray glyph_info_array
;
941 ByteCount count
= sizeof (ATSUGlyphInfoArray
);
943 err1
= ATSUMatchFontsToText (text_layout
, kATSUFromTextBeginning
,
944 kATSUToTextEnd
, NULL
, NULL
, NULL
);
946 err1
= ATSUGetGlyphInfo (text_layout
, kATSUFromTextBeginning
,
947 kATSUToTextEnd
, &count
,
951 xassert (glyph_info_array
.glyphs
[0].glyphID
);
952 *cg_glyph
= glyph_info_array
.glyphs
[0].glyphID
;
963 if (font_ascent_return
|| font_descent_return
)
967 GetFontInfo (&font_info
);
968 if (font_ascent_return
)
969 *font_ascent_return
= font_info
.ascent
;
970 if (font_descent_return
)
971 *font_descent_return
= font_info
.descent
;
977 width
= CharWidth (ch
);
978 QDTextBounds (1, &ch
, &char_bounds
);
979 STORE_XCHARSTRUCT (*overall_return
, width
, char_bounds
);
987 /* Mac replacement for XTextExtents16. Only sets horizontal metrics. */
990 mac_text_extents_16 (font_struct
, string
, nchars
, overall_return
)
991 XFontStruct
*font_struct
;
994 XCharStruct
*overall_return
;
997 short width
= 0, lbearing
= 0, rbearing
= 0;
1000 for (i
= 0; i
< nchars
; i
++)
1002 pcm
= mac_per_char_metric (font_struct
, string
, 0);
1004 width
+= FONT_WIDTH (font_struct
);
1007 lbearing
= min (lbearing
, width
+ pcm
->lbearing
);
1008 rbearing
= max (rbearing
, width
+ pcm
->rbearing
);
1009 width
+= pcm
->width
;
1014 overall_return
->lbearing
= lbearing
;
1015 overall_return
->rbearing
= rbearing
;
1016 overall_return
->width
= width
;
1018 /* What's the meaning of the return value of XTextExtents16? */
1022 #if USE_CG_TEXT_DRAWING
1023 static int cg_text_anti_aliasing_threshold
= 8;
1026 init_cg_text_anti_aliasing_threshold ()
1029 Fmac_get_preference (build_string ("AppleAntiAliasingThreshold"),
1033 cg_text_anti_aliasing_threshold
= XINT (val
);
1037 mac_draw_string_cg (f
, gc
, x
, y
, buf
, nchars
)
1045 float port_height
, gx
, gy
;
1047 CGContextRef context
;
1051 if (!mac_use_core_graphics
|| GC_FONT (gc
)->cg_font
== NULL
)
1054 port
= GetWindowPort (FRAME_MAC_WINDOW (f
));
1055 port_height
= FRAME_PIXEL_HEIGHT (f
);
1057 gy
= port_height
- y
;
1058 glyphs
= (CGGlyph
*)buf
;
1059 advances
= xmalloc (sizeof (CGSize
) * nchars
);
1060 for (i
= 0; i
< nchars
; i
++)
1062 XCharStruct
*pcm
= mac_per_char_metric (GC_FONT (gc
), buf
, 0);
1064 advances
[i
].width
= pcm
->width
;
1065 advances
[i
].height
= 0;
1066 glyphs
[i
] = GC_FONT (gc
)->cg_glyphs
[buf
->byte2
];
1070 QDBeginCGContext (port
, &context
);
1071 if (gc
->n_clip_rects
)
1073 CGContextTranslateCTM (context
, 0, port_height
);
1074 CGContextScaleCTM (context
, 1, -1);
1075 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1076 CGContextScaleCTM (context
, 1, -1);
1077 CGContextTranslateCTM (context
, 0, -port_height
);
1079 CGContextSetRGBFillColor (context
,
1080 RED_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1081 GREEN_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1082 BLUE_FROM_ULONG (gc
->xgcv
.foreground
) / 255.0,
1084 CGContextSetFont (context
, GC_FONT (gc
)->cg_font
);
1085 CGContextSetFontSize (context
, GC_FONT (gc
)->mac_fontsize
);
1086 if (GC_FONT (gc
)->mac_fontsize
<= cg_text_anti_aliasing_threshold
)
1087 CGContextSetShouldAntialias (context
, false);
1088 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
1089 CGContextSetTextPosition (context
, gx
, gy
);
1090 CGContextShowGlyphsWithAdvances (context
, glyphs
, advances
, nchars
);
1092 for (i
= 0; i
< nchars
; i
++)
1094 CGContextShowGlyphsAtPoint (context
, gx
, gy
, glyphs
+ i
, 1);
1095 gx
+= advances
[i
].width
;
1098 CGContextSynchronize (context
);
1099 QDEndCGContext (port
, &context
);
1108 /* Mac replacement for XCopyArea: dest must be window. */
1111 mac_copy_area (src
, f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1116 unsigned int width
, height
;
1121 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1123 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1124 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1126 ForeColor (blackColor
);
1127 BackColor (whiteColor
);
1129 mac_begin_clip (GC_CLIP_REGION (gc
));
1130 LockPixels (GetGWorldPixMap (src
));
1131 #if TARGET_API_MAC_CARBON
1136 LockPortBits (port
);
1137 CopyBits (GetPortBitMapForCopyBits (src
),
1138 GetPortBitMapForCopyBits (port
),
1139 &src_r
, &dest_r
, srcCopy
, 0);
1140 UnlockPortBits (port
);
1142 #else /* not TARGET_API_MAC_CARBON */
1143 CopyBits (&(((GrafPtr
)src
)->portBits
), &(FRAME_MAC_WINDOW (f
)->portBits
),
1144 &src_r
, &dest_r
, srcCopy
, 0);
1145 #endif /* not TARGET_API_MAC_CARBON */
1146 UnlockPixels (GetGWorldPixMap (src
));
1147 mac_end_clip (GC_CLIP_REGION (gc
));
1149 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1154 mac_copy_area_with_mask (src
, mask
, f
, gc
, src_x
, src_y
,
1155 width
, height
, dest_x
, dest_y
)
1160 unsigned int width
, height
;
1165 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1167 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1168 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1170 ForeColor (blackColor
);
1171 BackColor (whiteColor
);
1173 mac_begin_clip (GC_CLIP_REGION (gc
));
1174 LockPixels (GetGWorldPixMap (src
));
1175 LockPixels (GetGWorldPixMap (mask
));
1176 #if TARGET_API_MAC_CARBON
1181 LockPortBits (port
);
1182 CopyMask (GetPortBitMapForCopyBits (src
), GetPortBitMapForCopyBits (mask
),
1183 GetPortBitMapForCopyBits (port
),
1184 &src_r
, &src_r
, &dest_r
);
1185 UnlockPortBits (port
);
1187 #else /* not TARGET_API_MAC_CARBON */
1188 CopyMask (&(((GrafPtr
)src
)->portBits
), &(((GrafPtr
)mask
)->portBits
),
1189 &(FRAME_MAC_WINDOW (f
)->portBits
), &src_r
, &src_r
, &dest_r
);
1190 #endif /* not TARGET_API_MAC_CARBON */
1191 UnlockPixels (GetGWorldPixMap (mask
));
1192 UnlockPixels (GetGWorldPixMap (src
));
1193 mac_end_clip (GC_CLIP_REGION (gc
));
1195 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1199 /* Mac replacement for XCopyArea: used only for scrolling. */
1202 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1206 unsigned int width
, height
;
1209 #if TARGET_API_MAC_CARBON
1211 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1213 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1214 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1215 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1216 kScrollWindowNoOptions
, dummy
);
1218 #else /* not TARGET_API_MAC_CARBON */
1220 WindowPtr w
= FRAME_MAC_WINDOW (f
);
1224 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1225 SetRect (&dest_r
, dest_x
, dest_y
, dest_x
+ width
, dest_y
+ height
);
1227 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
1228 color mapping in CopyBits. Otherwise, it will be slow. */
1229 ForeColor (blackColor
);
1230 BackColor (whiteColor
);
1231 mac_begin_clip (GC_CLIP_REGION (gc
));
1232 CopyBits (&(w
->portBits
), &(w
->portBits
), &src_r
, &dest_r
, srcCopy
, 0);
1233 mac_end_clip (GC_CLIP_REGION (gc
));
1235 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f
)));
1236 #endif /* not TARGET_API_MAC_CARBON */
1240 /* Mac replacement for XChangeGC. */
1243 XChangeGC (display
, gc
, mask
, xgcv
)
1249 if (mask
& GCForeground
)
1250 XSetForeground (display
, gc
, xgcv
->foreground
);
1251 if (mask
& GCBackground
)
1252 XSetBackground (display
, gc
, xgcv
->background
);
1254 XSetFont (display
, gc
, xgcv
->font
);
1258 /* Mac replacement for XCreateGC. */
1261 XCreateGC (display
, window
, mask
, xgcv
)
1267 GC gc
= xmalloc (sizeof (*gc
));
1271 bzero (gc
, sizeof (*gc
));
1272 XChangeGC (display
, gc
, mask
, xgcv
);
1279 /* Used in xfaces.c. */
1282 XFreeGC (display
, gc
)
1286 if (gc
->clip_region
)
1287 DisposeRgn (gc
->clip_region
);
1292 /* Mac replacement for XGetGCValues. */
1295 XGetGCValues (display
, gc
, mask
, xgcv
)
1301 if (mask
& GCForeground
)
1302 xgcv
->foreground
= gc
->xgcv
.foreground
;
1303 if (mask
& GCBackground
)
1304 xgcv
->background
= gc
->xgcv
.background
;
1306 xgcv
->font
= gc
->xgcv
.font
;
1310 /* Mac replacement for XSetForeground. */
1313 XSetForeground (display
, gc
, color
)
1316 unsigned long color
;
1318 if (gc
->xgcv
.foreground
!= color
)
1320 gc
->xgcv
.foreground
= color
;
1321 gc
->fore_color
.red
= RED16_FROM_ULONG (color
);
1322 gc
->fore_color
.green
= GREEN16_FROM_ULONG (color
);
1323 gc
->fore_color
.blue
= BLUE16_FROM_ULONG (color
);
1328 /* Mac replacement for XSetBackground. */
1331 XSetBackground (display
, gc
, color
)
1334 unsigned long color
;
1336 if (gc
->xgcv
.background
!= color
)
1338 gc
->xgcv
.background
= color
;
1339 gc
->back_color
.red
= RED16_FROM_ULONG (color
);
1340 gc
->back_color
.green
= GREEN16_FROM_ULONG (color
);
1341 gc
->back_color
.blue
= BLUE16_FROM_ULONG (color
);
1346 /* Mac replacement for XSetFont. */
1349 XSetFont (display
, gc
, font
)
1354 gc
->xgcv
.font
= font
;
1358 /* Mac replacement for XSetClipRectangles. */
1361 mac_set_clip_rectangles (display
, gc
, rectangles
, n
)
1369 if (n
< 0 || n
> MAX_CLIP_RECTS
)
1373 if (gc
->clip_region
)
1375 DisposeRgn (gc
->clip_region
);
1376 gc
->clip_region
= NULL
;
1381 if (gc
->clip_region
== NULL
)
1382 gc
->clip_region
= NewRgn ();
1383 RectRgn (gc
->clip_region
, rectangles
);
1386 RgnHandle region
= NewRgn ();
1388 for (i
= 1; i
< n
; i
++)
1390 RectRgn (region
, rectangles
+ i
);
1391 UnionRgn (gc
->clip_region
, region
, gc
->clip_region
);
1393 DisposeRgn (region
);
1396 #if defined (MAC_OSX) && USE_ATSUI
1397 gc
->n_clip_rects
= n
;
1399 for (i
= 0; i
< n
; i
++)
1401 Rect
*rect
= rectangles
+ i
;
1403 gc
->clip_rects
[i
] = CGRectMake (rect
->left
, rect
->top
,
1404 rect
->right
- rect
->left
,
1405 rect
->bottom
- rect
->top
);
1411 /* Mac replacement for XSetClipMask. */
1414 mac_reset_clip_rectangles (display
, gc
)
1418 mac_set_clip_rectangles (display
, gc
, NULL
, 0);
1422 /* Mac replacement for XSetWindowBackground. */
1425 XSetWindowBackground (display
, w
, color
)
1428 unsigned long color
;
1430 #if !TARGET_API_MAC_CARBON
1431 AuxWinHandle aw_handle
;
1432 CTabHandle ctab_handle
;
1433 ColorSpecPtr ct_table
;
1438 bg_color
.red
= RED16_FROM_ULONG (color
);
1439 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1440 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1442 #if TARGET_API_MAC_CARBON
1443 SetWindowContentColor (w
, &bg_color
);
1445 if (GetAuxWin (w
, &aw_handle
))
1447 ctab_handle
= (*aw_handle
)->awCTable
;
1448 HandToHand ((Handle
*) &ctab_handle
);
1449 ct_table
= (*ctab_handle
)->ctTable
;
1450 ct_size
= (*ctab_handle
)->ctSize
;
1451 while (ct_size
> -1)
1453 if (ct_table
->value
== 0)
1455 ct_table
->rgb
= bg_color
;
1456 CTabChanged (ctab_handle
);
1457 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1465 /* x_sync is a no-op on Mac. */
1473 /* Flush display of frame F, or of all frames if F is null. */
1479 #if TARGET_API_MAC_CARBON
1482 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1484 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1490 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1491 Calls to XFlush should be unnecessary because the X output buffer
1492 is flushed automatically as needed by calls to XPending,
1493 XNextEvent, or XWindowEvent according to the XFlush man page.
1494 XTread_socket calls XPending. Removing XFlush improves
1497 #define XFlush(DISPLAY) (void) 0
1500 /* Return the struct mac_display_info corresponding to DPY. There's
1503 struct mac_display_info
*
1504 mac_display_info_for_display (dpy
)
1507 return &one_mac_display_info
;
1512 /***********************************************************************
1513 Starting and ending an update
1514 ***********************************************************************/
1516 /* Start an update of frame F. This function is installed as a hook
1517 for update_begin, i.e. it is called when update_begin is called.
1518 This function is called prior to calls to x_update_window_begin for
1519 each window being updated. */
1525 #if TARGET_API_MAC_CARBON
1526 /* During update of a frame, availability of input events is
1527 periodically checked with ReceiveNextEvent if
1528 redisplay-dont-pause is nil. That normally flushes window buffer
1529 changes for every check, and thus screen update looks waving even
1530 if no input is available. So we disable screen updates during
1531 update of a frame. */
1533 DisableScreenUpdates ();
1539 /* Start update of window W. Set the global variable updated_window
1540 to the window being updated and set output_cursor to the cursor
1544 x_update_window_begin (w
)
1547 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1548 struct mac_display_info
*display_info
= FRAME_MAC_DISPLAY_INFO (f
);
1551 set_output_cursor (&w
->cursor
);
1555 if (f
== display_info
->mouse_face_mouse_frame
)
1557 /* Don't do highlighting for mouse motion during the update. */
1558 display_info
->mouse_face_defer
= 1;
1560 /* If F needs to be redrawn, simply forget about any prior mouse
1562 if (FRAME_GARBAGED_P (f
))
1563 display_info
->mouse_face_window
= Qnil
;
1565 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1566 their mouse_face_p flag set, which means that they are always
1567 unequal to rows in a desired matrix which never have that
1568 flag set. So, rows containing mouse-face glyphs are never
1569 scrolled, and we don't have to switch the mouse highlight off
1570 here to prevent it from being scrolled. */
1572 /* Can we tell that this update does not affect the window
1573 where the mouse highlight is? If so, no need to turn off.
1574 Likewise, don't do anything if the frame is garbaged;
1575 in that case, the frame's current matrix that we would use
1576 is all wrong, and we will redisplay that line anyway. */
1577 if (!NILP (display_info
->mouse_face_window
)
1578 && w
== XWINDOW (display_info
->mouse_face_window
))
1582 for (i
= 0; i
< w
->desired_matrix
->nrows
; ++i
)
1583 if (MATRIX_ROW_ENABLED_P (w
->desired_matrix
, i
))
1586 if (i
< w
->desired_matrix
->nrows
)
1587 clear_mouse_face (display_info
);
1596 /* Draw a vertical window border from (x,y0) to (x,y1) */
1599 mac_draw_vertical_window_border (w
, x
, y0
, y1
)
1603 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1606 face
= FACE_FROM_ID (f
, VERTICAL_BORDER_FACE_ID
);
1608 XSetForeground (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
1611 mac_draw_line (f
, f
->output_data
.mac
->normal_gc
, x
, y0
, x
, y1
);
1614 /* End update of window W (which is equal to updated_window).
1616 Draw vertical borders between horizontally adjacent windows, and
1617 display W's cursor if CURSOR_ON_P is non-zero.
1619 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1620 glyphs in mouse-face were overwritten. In that case we have to
1621 make sure that the mouse-highlight is properly redrawn.
1623 W may be a menu bar pseudo-window in case we don't have X toolkit
1624 support. Such windows don't have a cursor, so don't display it
1628 x_update_window_end (w
, cursor_on_p
, mouse_face_overwritten_p
)
1630 int cursor_on_p
, mouse_face_overwritten_p
;
1632 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w
->frame
));
1634 if (!w
->pseudo_window_p
)
1639 display_and_set_cursor (w
, 1, output_cursor
.hpos
,
1641 output_cursor
.x
, output_cursor
.y
);
1643 if (draw_window_fringes (w
, 1))
1644 x_draw_vertical_border (w
);
1649 /* If a row with mouse-face was overwritten, arrange for
1650 XTframe_up_to_date to redisplay the mouse highlight. */
1651 if (mouse_face_overwritten_p
)
1653 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
1654 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
1655 dpyinfo
->mouse_face_window
= Qnil
;
1658 updated_window
= NULL
;
1662 /* End update of frame F. This function is installed as a hook in
1669 /* Mouse highlight may be displayed again. */
1670 FRAME_MAC_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
1673 #if TARGET_API_MAC_CARBON
1674 EnableScreenUpdates ();
1676 XFlush (FRAME_MAC_DISPLAY (f
));
1681 /* This function is called from various places in xdisp.c whenever a
1682 complete update has been performed. The global variable
1683 updated_window is not available here. */
1686 XTframe_up_to_date (f
)
1689 if (FRAME_MAC_P (f
))
1691 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1693 if (dpyinfo
->mouse_face_deferred_gc
1694 || f
== dpyinfo
->mouse_face_mouse_frame
)
1697 if (dpyinfo
->mouse_face_mouse_frame
)
1698 note_mouse_highlight (dpyinfo
->mouse_face_mouse_frame
,
1699 dpyinfo
->mouse_face_mouse_x
,
1700 dpyinfo
->mouse_face_mouse_y
);
1701 dpyinfo
->mouse_face_deferred_gc
= 0;
1708 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1709 arrow bitmaps, or clear the fringes if no bitmaps are required
1710 before DESIRED_ROW is made current. The window being updated is
1711 found in updated_window. This function is called from
1712 update_window_line only if it is known that there are differences
1713 between bitmaps to be drawn between current row and DESIRED_ROW. */
1716 x_after_update_window_line (desired_row
)
1717 struct glyph_row
*desired_row
;
1719 struct window
*w
= updated_window
;
1725 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
1726 desired_row
->redraw_fringe_bitmaps_p
= 1;
1728 /* When a window has disappeared, make sure that no rest of
1729 full-width rows stays visible in the internal border. Could
1730 check here if updated_window is the leftmost/rightmost window,
1731 but I guess it's not worth doing since vertically split windows
1732 are almost never used, internal border is rarely set, and the
1733 overhead is very small. */
1734 if (windows_or_buffers_changed
1735 && desired_row
->full_width_p
1736 && (f
= XFRAME (w
->frame
),
1737 width
= FRAME_INTERNAL_BORDER_WIDTH (f
),
1739 && (height
= desired_row
->visible_height
,
1742 int y
= WINDOW_TO_FRAME_PIXEL_Y (w
, max (0, desired_row
->y
));
1744 /* Internal border is drawn below the tool bar. */
1745 if (WINDOWP (f
->tool_bar_window
)
1746 && w
== XWINDOW (f
->tool_bar_window
))
1750 mac_clear_area (f
, 0, y
, width
, height
);
1751 mac_clear_area (f
, FRAME_PIXEL_WIDTH (f
) - width
, y
, width
, height
);
1757 /* Draw the bitmap WHICH in one of the left or right fringes of
1758 window W. ROW is the glyph row for which to display the bitmap; it
1759 determines the vertical position at which the bitmap has to be
1763 x_draw_fringe_bitmap (w
, row
, p
)
1765 struct glyph_row
*row
;
1766 struct draw_fringe_bitmap_params
*p
;
1768 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
1769 Display
*display
= FRAME_MAC_DISPLAY (f
);
1770 struct face
*face
= p
->face
;
1773 /* Must clip because of partially visible lines. */
1774 rowY
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
1777 /* Adjust position of "bottom aligned" bitmap on partially
1778 visible last row. */
1780 int oldVH
= row
->visible_height
;
1781 row
->visible_height
= p
->h
;
1782 row
->y
-= rowY
- p
->y
;
1783 x_clip_to_row (w
, row
, -1, face
->gc
);
1785 row
->visible_height
= oldVH
;
1788 x_clip_to_row (w
, row
, -1, face
->gc
);
1790 if (p
->bx
>= 0 && !p
->overlay_p
)
1792 #if 0 /* MAC_TODO: stipple */
1793 /* In case the same realized face is used for fringes and
1794 for something displayed in the text (e.g. face `region' on
1795 mono-displays, the fill style may have been changed to
1796 FillSolid in x_draw_glyph_string_background. */
1798 XSetFillStyle (FRAME_X_DISPLAY (f
), face
->gc
, FillOpaqueStippled
);
1800 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->background
);
1803 mac_erase_rectangle (f
, face
->gc
, p
->bx
, p
->by
, p
->nx
, p
->ny
);
1805 #if 0 /* MAC_TODO: stipple */
1807 XSetForeground (FRAME_X_DISPLAY (f
), face
->gc
, face
->foreground
);
1813 unsigned short *bits
= p
->bits
+ p
->dh
;
1816 XGetGCValues (display
, face
->gc
, GCForeground
, &gcv
);
1817 XSetForeground (display
, face
->gc
,
1819 ? (p
->overlay_p
? face
->background
1820 : f
->output_data
.mac
->cursor_pixel
)
1821 : face
->foreground
));
1822 mac_draw_bitmap (f
, face
->gc
, p
->x
, p
->y
,
1823 p
->wd
, p
->h
, bits
, p
->overlay_p
);
1824 XSetForeground (display
, face
->gc
, gcv
.foreground
);
1827 mac_reset_clip_rectangles (display
, face
->gc
);
1832 /* This is called when starting Emacs and when restarting after
1833 suspend. When starting Emacs, no window is mapped. And nothing
1834 must be done to Emacs's own window if it is suspended (though that
1838 XTset_terminal_modes ()
1842 /* This is called when exiting or suspending Emacs. Exiting will make
1843 the windows go away, and suspending requires no action. */
1846 XTreset_terminal_modes ()
1852 /***********************************************************************
1854 ***********************************************************************/
1856 /* Function prototypes of this page. */
1858 static XCharStruct
*x_per_char_metric
P_ ((XFontStruct
*, XChar2b
*));
1859 static int mac_encode_char
P_ ((int, XChar2b
*, struct font_info
*, int *));
1862 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1863 is not contained in the font. */
1865 static INLINE XCharStruct
*
1866 x_per_char_metric (font
, char2b
)
1870 /* The result metric information. */
1871 XCharStruct
*pcm
= NULL
;
1873 xassert (font
&& char2b
);
1876 if (font
->mac_style
)
1878 XCharStructRow
**row
= font
->bounds
.rows
+ char2b
->byte1
;
1882 *row
= xmalloc (sizeof (XCharStructRow
));
1884 bzero (*row
, sizeof (XCharStructRow
));
1888 pcm
= (*row
)->per_char
+ char2b
->byte2
;
1889 if (!XCHARSTRUCTROW_CHAR_VALID_P (*row
, char2b
->byte2
))
1892 mac_query_char_extents (font
->mac_style
,
1893 (char2b
->byte1
<< 8) + char2b
->byte2
,
1894 NULL
, NULL
, pcm
, NULL
);
1896 XCHARSTRUCTROW_SET_CHAR_VALID (*row
, char2b
->byte2
);
1903 if (font
->bounds
.per_char
!= NULL
)
1905 if (font
->min_byte1
== 0 && font
->max_byte1
== 0)
1907 /* min_char_or_byte2 specifies the linear character index
1908 corresponding to the first element of the per_char array,
1909 max_char_or_byte2 is the index of the last character. A
1910 character with non-zero CHAR2B->byte1 is not in the font.
1911 A character with byte2 less than min_char_or_byte2 or
1912 greater max_char_or_byte2 is not in the font. */
1913 if (char2b
->byte1
== 0
1914 && char2b
->byte2
>= font
->min_char_or_byte2
1915 && char2b
->byte2
<= font
->max_char_or_byte2
)
1916 pcm
= font
->bounds
.per_char
1917 + (char2b
->byte2
- font
->min_char_or_byte2
);
1921 /* If either min_byte1 or max_byte1 are nonzero, both
1922 min_char_or_byte2 and max_char_or_byte2 are less than
1923 256, and the 2-byte character index values corresponding
1924 to the per_char array element N (counting from 0) are:
1926 byte1 = N/D + min_byte1
1927 byte2 = N\D + min_char_or_byte2
1931 D = max_char_or_byte2 - min_char_or_byte2 + 1
1932 / = integer division
1933 \ = integer modulus */
1934 if (char2b
->byte1
>= font
->min_byte1
1935 && char2b
->byte1
<= font
->max_byte1
1936 && char2b
->byte2
>= font
->min_char_or_byte2
1937 && char2b
->byte2
<= font
->max_char_or_byte2
)
1939 pcm
= (font
->bounds
.per_char
1940 + ((font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1)
1941 * (char2b
->byte1
- font
->min_byte1
))
1942 + (char2b
->byte2
- font
->min_char_or_byte2
));
1948 /* If the per_char pointer is null, all glyphs between the first
1949 and last character indexes inclusive have the same
1950 information, as given by both min_bounds and max_bounds. */
1951 if (char2b
->byte2
>= font
->min_char_or_byte2
1952 && char2b
->byte2
<= font
->max_char_or_byte2
)
1953 pcm
= &font
->max_bounds
;
1959 return ((pcm
== NULL
1960 || (pcm
->width
== 0 && (pcm
->rbearing
- pcm
->lbearing
) == 0))
1967 static XCharStruct
*
1968 mac_per_char_metric (font
, char2b
, font_type
)
1973 return x_per_char_metric (font
, char2b
);
1977 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1978 the two-byte form of C. Encoding is returned in *CHAR2B. */
1981 mac_encode_char (c
, char2b
, font_info
, two_byte_p
)
1984 struct font_info
*font_info
;
1987 int charset
= CHAR_CHARSET (c
);
1988 XFontStruct
*font
= font_info
->font
;
1990 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1991 This may be either a program in a special encoder language or a
1993 if (font_info
->font_encoder
)
1995 /* It's a program. */
1996 struct ccl_program
*ccl
= font_info
->font_encoder
;
1998 check_ccl_update (ccl
);
1999 if (CHARSET_DIMENSION (charset
) == 1)
2001 ccl
->reg
[0] = charset
;
2002 ccl
->reg
[1] = char2b
->byte2
;
2007 ccl
->reg
[0] = charset
;
2008 ccl
->reg
[1] = char2b
->byte1
;
2009 ccl
->reg
[2] = char2b
->byte2
;
2012 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
2014 /* We assume that MSBs are appropriately set/reset by CCL
2016 if (font
->max_byte1
== 0) /* 1-byte font */
2017 char2b
->byte1
= 0, char2b
->byte2
= ccl
->reg
[1];
2019 char2b
->byte1
= ccl
->reg
[1], char2b
->byte2
= ccl
->reg
[2];
2021 else if (font_info
->encoding
[charset
])
2023 /* Fixed encoding scheme. See fontset.h for the meaning of the
2024 encoding numbers. */
2025 int enc
= font_info
->encoding
[charset
];
2027 if ((enc
== 1 || enc
== 2)
2028 && CHARSET_DIMENSION (charset
) == 2)
2029 char2b
->byte1
|= 0x80;
2031 if (enc
== 1 || enc
== 3)
2032 char2b
->byte2
|= 0x80;
2038 ENCODE_SJIS (char2b
->byte1
, char2b
->byte2
, sjis1
, sjis2
);
2039 char2b
->byte1
= sjis1
;
2040 char2b
->byte2
= sjis2
;
2045 *two_byte_p
= ((XFontStruct
*) (font_info
->font
))->max_byte1
> 0;
2047 return FONT_TYPE_UNKNOWN
;
2052 /***********************************************************************
2054 ***********************************************************************/
2058 static void x_set_glyph_string_clipping
P_ ((struct glyph_string
*));
2059 static void x_set_glyph_string_gc
P_ ((struct glyph_string
*));
2060 static void x_draw_glyph_string_background
P_ ((struct glyph_string
*,
2062 static void x_draw_glyph_string_foreground
P_ ((struct glyph_string
*));
2063 static void x_draw_composite_glyph_string_foreground
P_ ((struct glyph_string
*));
2064 static void x_draw_glyph_string_box
P_ ((struct glyph_string
*));
2065 static void x_draw_glyph_string
P_ ((struct glyph_string
*));
2066 static void mac_compute_glyph_string_overhangs
P_ ((struct glyph_string
*));
2067 static void x_set_cursor_gc
P_ ((struct glyph_string
*));
2068 static void x_set_mode_line_face_gc
P_ ((struct glyph_string
*));
2069 static void x_set_mouse_face_gc
P_ ((struct glyph_string
*));
2070 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2071 unsigned long *, double, int));*/
2072 static void x_setup_relief_color
P_ ((struct frame
*, struct relief
*,
2073 double, int, unsigned long));
2074 static void x_setup_relief_colors
P_ ((struct glyph_string
*));
2075 static void x_draw_image_glyph_string
P_ ((struct glyph_string
*));
2076 static void x_draw_image_relief
P_ ((struct glyph_string
*));
2077 static void x_draw_image_foreground
P_ ((struct glyph_string
*));
2078 static void x_draw_image_foreground_1
P_ ((struct glyph_string
*, Pixmap
));
2079 static void x_clear_glyph_string_rect
P_ ((struct glyph_string
*, int,
2081 static void x_draw_relief_rect
P_ ((struct frame
*, int, int, int, int,
2082 int, int, int, int, int, int,
2084 static void x_draw_box_rect
P_ ((struct glyph_string
*, int, int, int, int,
2085 int, int, int, Rect
*));
2088 static void x_check_font
P_ ((struct frame
*, XFontStruct
*));
2092 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2097 struct glyph_string
*s
;
2099 if (s
->font
== FRAME_FONT (s
->f
)
2100 && s
->face
->background
== FRAME_BACKGROUND_PIXEL (s
->f
)
2101 && s
->face
->foreground
== FRAME_FOREGROUND_PIXEL (s
->f
)
2103 s
->gc
= s
->f
->output_data
.mac
->cursor_gc
;
2106 /* Cursor on non-default face: must merge. */
2110 xgcv
.background
= s
->f
->output_data
.mac
->cursor_pixel
;
2111 xgcv
.foreground
= s
->face
->background
;
2113 /* If the glyph would be invisible, try a different foreground. */
2114 if (xgcv
.foreground
== xgcv
.background
)
2115 xgcv
.foreground
= s
->face
->foreground
;
2116 if (xgcv
.foreground
== xgcv
.background
)
2117 xgcv
.foreground
= s
->f
->output_data
.mac
->cursor_foreground_pixel
;
2118 if (xgcv
.foreground
== xgcv
.background
)
2119 xgcv
.foreground
= s
->face
->foreground
;
2121 /* Make sure the cursor is distinct from text in this face. */
2122 if (xgcv
.background
== s
->face
->background
2123 && xgcv
.foreground
== s
->face
->foreground
)
2125 xgcv
.background
= s
->face
->foreground
;
2126 xgcv
.foreground
= s
->face
->background
;
2129 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2130 xgcv
.font
= s
->font
;
2131 mask
= GCForeground
| GCBackground
| GCFont
;
2133 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2134 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2137 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2138 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2140 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2145 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2148 x_set_mouse_face_gc (s
)
2149 struct glyph_string
*s
;
2154 /* What face has to be used last for the mouse face? */
2155 face_id
= FRAME_X_DISPLAY_INFO (s
->f
)->mouse_face_face_id
;
2156 face
= FACE_FROM_ID (s
->f
, face_id
);
2158 face
= FACE_FROM_ID (s
->f
, MOUSE_FACE_ID
);
2160 if (s
->first_glyph
->type
== CHAR_GLYPH
)
2161 face_id
= FACE_FOR_CHAR (s
->f
, face
, s
->first_glyph
->u
.ch
);
2163 face_id
= FACE_FOR_CHAR (s
->f
, face
, 0);
2164 s
->face
= FACE_FROM_ID (s
->f
, face_id
);
2165 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2167 /* If font in this face is same as S->font, use it. */
2168 if (s
->font
== s
->face
->font
)
2169 s
->gc
= s
->face
->gc
;
2172 /* Otherwise construct scratch_cursor_gc with values from FACE
2177 xgcv
.background
= s
->face
->background
;
2178 xgcv
.foreground
= s
->face
->foreground
;
2179 IF_DEBUG (x_check_font (s
->f
, s
->font
));
2180 xgcv
.font
= s
->font
;
2181 mask
= GCForeground
| GCBackground
| GCFont
;
2183 if (FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
)
2184 XChangeGC (s
->display
, FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
,
2187 FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
2188 = XCreateGC (s
->display
, s
->window
, mask
, &xgcv
);
2190 s
->gc
= FRAME_MAC_DISPLAY_INFO (s
->f
)->scratch_cursor_gc
;
2193 xassert (s
->gc
!= 0);
2197 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2198 Faces to use in the mode line have already been computed when the
2199 matrix was built, so there isn't much to do, here. */
2202 x_set_mode_line_face_gc (s
)
2203 struct glyph_string
*s
;
2205 s
->gc
= s
->face
->gc
;
2209 /* Set S->gc of glyph string S for drawing that glyph string. Set
2210 S->stippled_p to a non-zero value if the face of S has a stipple
2214 x_set_glyph_string_gc (s
)
2215 struct glyph_string
*s
;
2217 PREPARE_FACE_FOR_DISPLAY (s
->f
, s
->face
);
2219 if (s
->hl
== DRAW_NORMAL_TEXT
)
2221 s
->gc
= s
->face
->gc
;
2222 s
->stippled_p
= s
->face
->stipple
!= 0;
2224 else if (s
->hl
== DRAW_INVERSE_VIDEO
)
2226 x_set_mode_line_face_gc (s
);
2227 s
->stippled_p
= s
->face
->stipple
!= 0;
2229 else if (s
->hl
== DRAW_CURSOR
)
2231 x_set_cursor_gc (s
);
2234 else if (s
->hl
== DRAW_MOUSE_FACE
)
2236 x_set_mouse_face_gc (s
);
2237 s
->stippled_p
= s
->face
->stipple
!= 0;
2239 else if (s
->hl
== DRAW_IMAGE_RAISED
2240 || s
->hl
== DRAW_IMAGE_SUNKEN
)
2242 s
->gc
= s
->face
->gc
;
2243 s
->stippled_p
= s
->face
->stipple
!= 0;
2247 s
->gc
= s
->face
->gc
;
2248 s
->stippled_p
= s
->face
->stipple
!= 0;
2251 /* GC must have been set. */
2252 xassert (s
->gc
!= 0);
2256 /* Set clipping for output of glyph string S. S may be part of a mode
2257 line or menu if we don't have X toolkit support. */
2260 x_set_glyph_string_clipping (s
)
2261 struct glyph_string
*s
;
2263 Rect rects
[MAX_CLIP_RECTS
];
2266 n
= get_glyph_string_clip_rects (s
, rects
, MAX_CLIP_RECTS
);
2267 mac_set_clip_rectangles (s
->display
, s
->gc
, rects
, n
);
2272 Compute left and right overhang of glyph string S. If S is a glyph
2273 string for a composition, assume overhangs don't exist. */
2276 mac_compute_glyph_string_overhangs (s
)
2277 struct glyph_string
*s
;
2280 && s
->first_glyph
->type
== CHAR_GLYPH
)
2283 || s
->font
->mac_style
2289 mac_text_extents_16 (s
->font
, s
->char2b
, s
->nchars
, &cs
);
2290 s
->right_overhang
= cs
.rbearing
> cs
.width
? cs
.rbearing
- cs
.width
: 0;
2291 s
->left_overhang
= cs
.lbearing
< 0 ? -cs
.lbearing
: 0;
2296 MacFontStruct
*font
= s
->font
;
2298 TextFont (font
->mac_fontnum
);
2299 TextSize (font
->mac_fontsize
);
2300 TextFace (font
->mac_fontface
);
2302 QDTextBounds (s
->nchars
* 2, (char *)s
->char2b
, &r
);
2304 s
->right_overhang
= r
.right
> s
->width
? r
.right
- s
->width
: 0;
2305 s
->left_overhang
= r
.left
< 0 ? -r
.left
: 0;
2310 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2313 x_clear_glyph_string_rect (s
, x
, y
, w
, h
)
2314 struct glyph_string
*s
;
2317 mac_erase_rectangle (s
->f
, s
->gc
, x
, y
, w
, h
);
2321 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2322 on Mac OS X because:
2323 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2324 into an offscreen graphics world first. So performance gain
2325 cannot be expected.)
2326 - It lowers rendering quality.
2327 - Some fonts leave garbage on cursor movement. */
2329 /* Draw the background of glyph_string S. If S->background_filled_p
2330 is non-zero don't draw it. FORCE_P non-zero means draw the
2331 background even if it wouldn't be drawn normally. This is used
2332 when a string preceding S draws into the background of S, or S
2333 contains the first component of a composition. */
2336 x_draw_glyph_string_background (s
, force_p
)
2337 struct glyph_string
*s
;
2340 /* Nothing to do if background has already been drawn or if it
2341 shouldn't be drawn in the first place. */
2342 if (!s
->background_filled_p
)
2344 int box_line_width
= max (s
->face
->box_line_width
, 0);
2346 #if 0 /* MAC_TODO: stipple */
2349 /* Fill background with a stipple pattern. */
2350 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
2351 XFillRectangle (s
->display
, s
->window
, s
->gc
, s
->x
,
2352 s
->y
+ box_line_width
,
2353 s
->background_width
,
2354 s
->height
- 2 * box_line_width
);
2355 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
2356 s
->background_filled_p
= 1;
2360 #if defined (MAC_OS8) && !USE_ATSUI
2361 if (FONT_HEIGHT (s
->font
) < s
->height
- 2 * box_line_width
2362 || s
->font_not_found_p
2363 || s
->extends_to_end_of_line_p
2367 x_clear_glyph_string_rect (s
, s
->x
, s
->y
+ box_line_width
,
2368 s
->background_width
,
2369 s
->height
- 2 * box_line_width
);
2370 s
->background_filled_p
= 1;
2376 /* Draw the foreground of glyph string S. */
2379 x_draw_glyph_string_foreground (s
)
2380 struct glyph_string
*s
;
2384 /* If first glyph of S has a left box line, start drawing the text
2385 of S to the right of that box line. */
2386 if (s
->face
->box
!= FACE_NO_BOX
2387 && s
->first_glyph
->left_box_line_p
)
2388 x
= s
->x
+ abs (s
->face
->box_line_width
);
2392 /* Draw characters of S as rectangles if S's font could not be
2394 if (s
->font_not_found_p
)
2396 for (i
= 0; i
< s
->nchars
; ++i
)
2398 struct glyph
*g
= s
->first_glyph
+ i
;
2399 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2400 g
->pixel_width
- 1, s
->height
- 1);
2401 x
+= g
->pixel_width
;
2406 char *char1b
= (char *) s
->char2b
;
2407 int boff
= s
->font_info
->baseline_offset
;
2409 if (s
->font_info
->vertical_centering
)
2410 boff
= VCENTER_BASELINE_OFFSET (s
->font
, s
->f
) - boff
;
2412 /* If we can use 8-bit functions, condense S->char2b. */
2415 && GC_FONT (s
->gc
)->mac_style
== NULL
2418 for (i
= 0; i
< s
->nchars
; ++i
)
2419 char1b
[i
] = s
->char2b
[i
].byte2
;
2421 #if defined (MAC_OS8) && !USE_ATSUI
2422 /* Draw text with XDrawString if background has already been
2423 filled. Otherwise, use XDrawImageString. (Note that
2424 XDrawImageString is usually faster than XDrawString.) Always
2425 use XDrawImageString when drawing the cursor so that there is
2426 no chance that characters under a box cursor are invisible. */
2428 || (s
->background_filled_p
&& s
->hl
!= DRAW_CURSOR
))
2431 /* Draw characters with 16-bit or 8-bit functions. */
2434 || GC_FONT (s
->gc
)->mac_style
2437 #if USE_CG_TEXT_DRAWING
2439 && mac_draw_string_cg (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2440 s
->char2b
, s
->nchars
))
2444 mac_draw_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2445 s
->char2b
, s
->nchars
);
2447 mac_draw_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2450 #if defined (MAC_OS8) && !USE_ATSUI
2454 mac_draw_image_string_16 (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2455 s
->char2b
, s
->nchars
);
2457 mac_draw_image_string (s
->f
, s
->gc
, x
, s
->ybase
- boff
,
2464 /* Draw the foreground of composite glyph string S. */
2467 x_draw_composite_glyph_string_foreground (s
)
2468 struct glyph_string
*s
;
2472 /* If first glyph of S has a left box line, start drawing the text
2473 of S to the right of that box line. */
2474 if (s
->face
->box
!= FACE_NO_BOX
2475 && s
->first_glyph
->left_box_line_p
)
2476 x
= s
->x
+ abs (s
->face
->box_line_width
);
2480 /* S is a glyph string for a composition. S->gidx is the index of
2481 the first character drawn for glyphs of this composition.
2482 S->gidx == 0 means we are drawing the very first character of
2483 this composition. */
2485 /* Draw a rectangle for the composition if the font for the very
2486 first character of the composition could not be loaded. */
2487 if (s
->font_not_found_p
)
2490 mac_draw_rectangle (s
->f
, s
->gc
, x
, s
->y
,
2491 s
->width
- 1, s
->height
- 1);
2495 for (i
= 0; i
< s
->nchars
; i
++, ++s
->gidx
)
2496 mac_draw_string_16 (s
->f
, s
->gc
,
2497 x
+ s
->cmp
->offsets
[s
->gidx
* 2],
2498 s
->ybase
- s
->cmp
->offsets
[s
->gidx
* 2 + 1],
2504 #ifdef USE_X_TOOLKIT
2506 static struct frame
*x_frame_of_widget
P_ ((Widget
));
2509 /* Return the frame on which widget WIDGET is used.. Abort if frame
2510 cannot be determined. */
2512 static struct frame
*
2513 x_frame_of_widget (widget
)
2516 struct x_display_info
*dpyinfo
;
2520 dpyinfo
= x_display_info_for_display (XtDisplay (widget
));
2522 /* Find the top-level shell of the widget. Note that this function
2523 can be called when the widget is not yet realized, so XtWindow
2524 (widget) == 0. That's the reason we can't simply use
2525 x_any_window_to_frame. */
2526 while (!XtIsTopLevelShell (widget
))
2527 widget
= XtParent (widget
);
2529 /* Look for a frame with that top-level widget. Allocate the color
2530 on that frame to get the right gamma correction value. */
2531 for (tail
= Vframe_list
; GC_CONSP (tail
); tail
= XCDR (tail
))
2532 if (GC_FRAMEP (XCAR (tail
))
2533 && (f
= XFRAME (XCAR (tail
)),
2534 (f
->output_data
.nothing
!= 1
2535 && FRAME_X_DISPLAY_INFO (f
) == dpyinfo
))
2536 && f
->output_data
.x
->widget
== widget
)
2543 /* Allocate the color COLOR->pixel on the screen and display of
2544 widget WIDGET in colormap CMAP. If an exact match cannot be
2545 allocated, try the nearest color available. Value is non-zero
2546 if successful. This is called from lwlib. */
2549 x_alloc_nearest_color_for_widget (widget
, cmap
, color
)
2554 struct frame
*f
= x_frame_of_widget (widget
);
2555 return x_alloc_nearest_color (f
, cmap
, color
);
2559 #endif /* USE_X_TOOLKIT */
2561 #if 0 /* MAC_TODO */
2563 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2564 CMAP. If an exact match can't be allocated, try the nearest color
2565 available. Value is non-zero if successful. Set *COLOR to the
2569 x_alloc_nearest_color (f
, cmap
, color
)
2574 Display
*display
= FRAME_X_DISPLAY (f
);
2575 Screen
*screen
= FRAME_X_SCREEN (f
);
2578 gamma_correct (f
, color
);
2579 rc
= XAllocColor (display
, cmap
, color
);
2582 /* If we got to this point, the colormap is full, so we're going
2583 to try to get the next closest color. The algorithm used is
2584 a least-squares matching, which is what X uses for closest
2585 color matching with StaticColor visuals. */
2587 unsigned long nearest_delta
= ~0;
2588 int ncells
= XDisplayCells (display
, XScreenNumberOfScreen (screen
));
2589 XColor
*cells
= (XColor
*) alloca (ncells
* sizeof *cells
);
2591 for (i
= 0; i
< ncells
; ++i
)
2593 XQueryColors (display
, cmap
, cells
, ncells
);
2595 for (nearest
= i
= 0; i
< ncells
; ++i
)
2597 long dred
= (color
->red
>> 8) - (cells
[i
].red
>> 8);
2598 long dgreen
= (color
->green
>> 8) - (cells
[i
].green
>> 8);
2599 long dblue
= (color
->blue
>> 8) - (cells
[i
].blue
>> 8);
2600 unsigned long delta
= dred
* dred
+ dgreen
* dgreen
+ dblue
* dblue
;
2602 if (delta
< nearest_delta
)
2605 nearest_delta
= delta
;
2609 color
->red
= cells
[nearest
].red
;
2610 color
->green
= cells
[nearest
].green
;
2611 color
->blue
= cells
[nearest
].blue
;
2612 rc
= XAllocColor (display
, cmap
, color
);
2615 #ifdef DEBUG_X_COLORS
2617 register_color (color
->pixel
);
2618 #endif /* DEBUG_X_COLORS */
2624 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2625 It's necessary to do this instead of just using PIXEL directly to
2626 get color reference counts right. */
2629 x_copy_color (f
, pixel
)
2631 unsigned long pixel
;
2635 color
.pixel
= pixel
;
2637 XQueryColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2638 XAllocColor (FRAME_X_DISPLAY (f
), FRAME_X_COLORMAP (f
), &color
);
2640 #ifdef DEBUG_X_COLORS
2641 register_color (pixel
);
2647 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2648 It's necessary to do this instead of just using PIXEL directly to
2649 get color reference counts right. */
2652 x_copy_dpy_color (dpy
, cmap
, pixel
)
2655 unsigned long pixel
;
2659 color
.pixel
= pixel
;
2661 XQueryColor (dpy
, cmap
, &color
);
2662 XAllocColor (dpy
, cmap
, &color
);
2664 #ifdef DEBUG_X_COLORS
2665 register_color (pixel
);
2670 #endif /* MAC_TODO */
2673 /* Brightness beyond which a color won't have its highlight brightness
2676 Nominally, highlight colors for `3d' faces are calculated by
2677 brightening an object's color by a constant scale factor, but this
2678 doesn't yield good results for dark colors, so for colors who's
2679 brightness is less than this value (on a scale of 0-255) have to
2680 use an additional additive factor.
2682 The value here is set so that the default menu-bar/mode-line color
2683 (grey75) will not have its highlights changed at all. */
2684 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2687 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2688 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2689 If this produces the same color as COLOR, try a color where all RGB
2690 values have DELTA added. Return the allocated color in *COLOR.
2691 DISPLAY is the X display, CMAP is the colormap to operate on.
2692 Value is non-zero if successful. */
2695 mac_alloc_lighter_color (f
, color
, factor
, delta
)
2697 unsigned long *color
;
2704 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2707 /* Change RGB values by specified FACTOR. Avoid overflow! */
2708 xassert (factor
>= 0);
2709 new = RGB_TO_ULONG (min (0xff, (int) (factor
* RED_FROM_ULONG (*color
))),
2710 min (0xff, (int) (factor
* GREEN_FROM_ULONG (*color
))),
2711 min (0xff, (int) (factor
* BLUE_FROM_ULONG (*color
))));
2713 /* Calculate brightness of COLOR. */
2714 bright
= (2 * RED_FROM_ULONG (*color
) + 3 * GREEN_FROM_ULONG (*color
)
2715 + BLUE_FROM_ULONG (*color
)) / 6;
2717 /* We only boost colors that are darker than
2718 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2719 if (bright
< HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
)
2720 /* Make an additive adjustment to NEW, because it's dark enough so
2721 that scaling by FACTOR alone isn't enough. */
2723 /* How far below the limit this color is (0 - 1, 1 being darker). */
2724 double dimness
= 1 - (double)bright
/ HIGHLIGHT_COLOR_DARK_BOOST_LIMIT
;
2725 /* The additive adjustment. */
2726 int min_delta
= delta
* dimness
* factor
/ 2;
2729 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color
)) - min_delta
)),
2730 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color
)) - min_delta
)),
2731 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color
)) - min_delta
)));
2733 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta
+ RED_FROM_ULONG (*color
)))),
2734 max (0, min (0xff, (int) (min_delta
+ GREEN_FROM_ULONG (*color
)))),
2735 max (0, min (0xff, (int) (min_delta
+ BLUE_FROM_ULONG (*color
)))));
2739 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta
+ RED_FROM_ULONG (*color
)))),
2740 max (0, min (0xff, (int) (delta
+ GREEN_FROM_ULONG (*color
)))),
2741 max (0, min (0xff, (int) (delta
+ BLUE_FROM_ULONG (*color
)))));
2743 /* MAC_TODO: Map to palette and retry with delta if same? */
2744 /* MAC_TODO: Free colors (if using palette)? */
2755 /* Set up the foreground color for drawing relief lines of glyph
2756 string S. RELIEF is a pointer to a struct relief containing the GC
2757 with which lines will be drawn. Use a color that is FACTOR or
2758 DELTA lighter or darker than the relief's background which is found
2759 in S->f->output_data.x->relief_background. If such a color cannot
2760 be allocated, use DEFAULT_PIXEL, instead. */
2763 x_setup_relief_color (f
, relief
, factor
, delta
, default_pixel
)
2765 struct relief
*relief
;
2768 unsigned long default_pixel
;
2771 struct mac_output
*di
= f
->output_data
.mac
;
2772 unsigned long mask
= GCForeground
;
2773 unsigned long pixel
;
2774 unsigned long background
= di
->relief_background
;
2775 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2777 /* MAC_TODO: Free colors (if using palette)? */
2779 /* Allocate new color. */
2780 xgcv
.foreground
= default_pixel
;
2782 if (dpyinfo
->n_planes
!= 1
2783 && mac_alloc_lighter_color (f
, &pixel
, factor
, delta
))
2785 relief
->allocated_p
= 1;
2786 xgcv
.foreground
= relief
->pixel
= pixel
;
2789 if (relief
->gc
== 0)
2791 #if 0 /* MAC_TODO: stipple */
2792 xgcv
.stipple
= dpyinfo
->gray
;
2795 relief
->gc
= XCreateGC (NULL
, FRAME_MAC_WINDOW (f
), mask
, &xgcv
);
2798 XChangeGC (NULL
, relief
->gc
, mask
, &xgcv
);
2802 /* Set up colors for the relief lines around glyph string S. */
2805 x_setup_relief_colors (s
)
2806 struct glyph_string
*s
;
2808 struct mac_output
*di
= s
->f
->output_data
.mac
;
2809 unsigned long color
;
2811 if (s
->face
->use_box_color_for_shadows_p
)
2812 color
= s
->face
->box_color
;
2813 else if (s
->first_glyph
->type
== IMAGE_GLYPH
2815 && !IMAGE_BACKGROUND_TRANSPARENT (s
->img
, s
->f
, 0))
2816 color
= IMAGE_BACKGROUND (s
->img
, s
->f
, 0);
2821 /* Get the background color of the face. */
2822 XGetGCValues (s
->display
, s
->gc
, GCBackground
, &xgcv
);
2823 color
= xgcv
.background
;
2826 if (di
->white_relief
.gc
== 0
2827 || color
!= di
->relief_background
)
2829 di
->relief_background
= color
;
2830 x_setup_relief_color (s
->f
, &di
->white_relief
, 1.2, 0x8000,
2831 WHITE_PIX_DEFAULT (s
->f
));
2832 x_setup_relief_color (s
->f
, &di
->black_relief
, 0.6, 0x4000,
2833 BLACK_PIX_DEFAULT (s
->f
));
2838 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2839 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2840 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2841 relief. LEFT_P non-zero means draw a relief on the left side of
2842 the rectangle. RIGHT_P non-zero means draw a relief on the right
2843 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2847 x_draw_relief_rect (f
, left_x
, top_y
, right_x
, bottom_y
, width
,
2848 raised_p
, top_p
, bot_p
, left_p
, right_p
, clip_rect
)
2850 int left_x
, top_y
, right_x
, bottom_y
, width
;
2851 int top_p
, bot_p
, left_p
, right_p
, raised_p
;
2854 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
2859 gc
= f
->output_data
.mac
->white_relief
.gc
;
2861 gc
= f
->output_data
.mac
->black_relief
.gc
;
2862 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2866 for (i
= 0; i
< width
; ++i
)
2867 mac_draw_line (f
, gc
,
2868 left_x
+ i
* left_p
, top_y
+ i
,
2869 right_x
- i
* right_p
, top_y
+ i
);
2873 for (i
= 0; i
< width
; ++i
)
2874 mac_draw_line (f
, gc
,
2875 left_x
+ i
, top_y
+ i
, left_x
+ i
, bottom_y
- i
);
2877 mac_reset_clip_rectangles (dpy
, gc
);
2879 gc
= f
->output_data
.mac
->black_relief
.gc
;
2881 gc
= f
->output_data
.mac
->white_relief
.gc
;
2882 mac_set_clip_rectangles (dpy
, gc
, clip_rect
, 1);
2886 for (i
= 0; i
< width
; ++i
)
2887 mac_draw_line (f
, gc
,
2888 left_x
+ i
* left_p
, bottom_y
- i
,
2889 right_x
- i
* right_p
, bottom_y
- i
);
2893 for (i
= 0; i
< width
; ++i
)
2894 mac_draw_line (f
, gc
,
2895 right_x
- i
, top_y
+ i
+ 1, right_x
- i
, bottom_y
- i
- 1);
2897 mac_reset_clip_rectangles (dpy
, gc
);
2901 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2902 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2903 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2904 left side of the rectangle. RIGHT_P non-zero means draw a line
2905 on the right side of the rectangle. CLIP_RECT is the clipping
2906 rectangle to use when drawing. */
2909 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2910 left_p
, right_p
, clip_rect
)
2911 struct glyph_string
*s
;
2912 int left_x
, top_y
, right_x
, bottom_y
, width
, left_p
, right_p
;
2917 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
2918 XSetForeground (s
->display
, s
->gc
, s
->face
->box_color
);
2919 mac_set_clip_rectangles (s
->display
, s
->gc
, clip_rect
, 1);
2922 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2923 right_x
- left_x
+ 1, width
);
2927 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, top_y
,
2928 width
, bottom_y
- top_y
+ 1);
2931 mac_fill_rectangle (s
->f
, s
->gc
, left_x
, bottom_y
- width
+ 1,
2932 right_x
- left_x
+ 1, width
);
2936 mac_fill_rectangle (s
->f
, s
->gc
, right_x
- width
+ 1,
2937 top_y
, width
, bottom_y
- top_y
+ 1);
2939 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
2940 mac_reset_clip_rectangles (s
->display
, s
->gc
);
2944 /* Draw a box around glyph string S. */
2947 x_draw_glyph_string_box (s
)
2948 struct glyph_string
*s
;
2950 int width
, left_x
, right_x
, top_y
, bottom_y
, last_x
, raised_p
;
2951 int left_p
, right_p
;
2952 struct glyph
*last_glyph
;
2955 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2956 ? WINDOW_RIGHT_EDGE_X (s
->w
)
2957 : window_box_right (s
->w
, s
->area
));
2959 /* The glyph that may have a right box line. */
2960 last_glyph
= (s
->cmp
|| s
->img
2962 : s
->first_glyph
+ s
->nchars
- 1);
2964 width
= abs (s
->face
->box_line_width
);
2965 raised_p
= s
->face
->box
== FACE_RAISED_BOX
;
2967 right_x
= (s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2969 : min (last_x
, s
->x
+ s
->background_width
) - 1);
2971 bottom_y
= top_y
+ s
->height
- 1;
2973 left_p
= (s
->first_glyph
->left_box_line_p
2974 || (s
->hl
== DRAW_MOUSE_FACE
2976 || s
->prev
->hl
!= s
->hl
)));
2977 right_p
= (last_glyph
->right_box_line_p
2978 || (s
->hl
== DRAW_MOUSE_FACE
2980 || s
->next
->hl
!= s
->hl
)));
2982 get_glyph_string_clip_rect (s
, &clip_rect
);
2984 if (s
->face
->box
== FACE_SIMPLE_BOX
)
2985 x_draw_box_rect (s
, left_x
, top_y
, right_x
, bottom_y
, width
,
2986 left_p
, right_p
, &clip_rect
);
2989 x_setup_relief_colors (s
);
2990 x_draw_relief_rect (s
->f
, left_x
, top_y
, right_x
, bottom_y
,
2991 width
, raised_p
, 1, 1, left_p
, right_p
, &clip_rect
);
2996 /* Draw foreground of image glyph string S. */
2999 x_draw_image_foreground (s
)
3000 struct glyph_string
*s
;
3003 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3005 /* If first glyph of S has a left box line, start drawing it to the
3006 right of that line. */
3007 if (s
->face
->box
!= FACE_NO_BOX
3008 && s
->first_glyph
->left_box_line_p
3010 x
+= abs (s
->face
->box_line_width
);
3012 /* If there is a margin around the image, adjust x- and y-position
3014 if (s
->slice
.x
== 0)
3015 x
+= s
->img
->hmargin
;
3016 if (s
->slice
.y
== 0)
3017 y
+= s
->img
->vmargin
;
3021 x_set_glyph_string_clipping (s
);
3024 mac_copy_area_with_mask (s
->img
->pixmap
, s
->img
->mask
,
3025 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3026 s
->slice
.width
, s
->slice
.height
, x
, y
);
3029 mac_copy_area (s
->img
->pixmap
,
3030 s
->f
, s
->gc
, s
->slice
.x
, s
->slice
.y
,
3031 s
->slice
.width
, s
->slice
.height
, x
, y
);
3033 /* When the image has a mask, we can expect that at
3034 least part of a mouse highlight or a block cursor will
3035 be visible. If the image doesn't have a mask, make
3036 a block cursor visible by drawing a rectangle around
3037 the image. I believe it's looking better if we do
3038 nothing here for mouse-face. */
3039 if (s
->hl
== DRAW_CURSOR
)
3041 int r
= s
->img
->relief
;
3043 mac_draw_rectangle (s
->f
, s
->gc
, x
- r
, y
- r
,
3044 s
->slice
.width
+ r
*2 - 1,
3045 s
->slice
.height
+ r
*2 - 1);
3050 /* Draw a rectangle if image could not be loaded. */
3051 mac_draw_rectangle (s
->f
, s
->gc
, x
, y
,
3052 s
->slice
.width
- 1, s
->slice
.height
- 1);
3056 /* Draw a relief around the image glyph string S. */
3059 x_draw_image_relief (s
)
3060 struct glyph_string
*s
;
3062 int x0
, y0
, x1
, y1
, thick
, raised_p
;
3065 int y
= s
->ybase
- image_ascent (s
->img
, s
->face
, &s
->slice
);
3067 /* If first glyph of S has a left box line, start drawing it to the
3068 right of that line. */
3069 if (s
->face
->box
!= FACE_NO_BOX
3070 && s
->first_glyph
->left_box_line_p
3072 x
+= abs (s
->face
->box_line_width
);
3074 /* If there is a margin around the image, adjust x- and y-position
3076 if (s
->slice
.x
== 0)
3077 x
+= s
->img
->hmargin
;
3078 if (s
->slice
.y
== 0)
3079 y
+= s
->img
->vmargin
;
3081 if (s
->hl
== DRAW_IMAGE_SUNKEN
3082 || s
->hl
== DRAW_IMAGE_RAISED
)
3084 thick
= tool_bar_button_relief
>= 0 ? tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
3085 raised_p
= s
->hl
== DRAW_IMAGE_RAISED
;
3089 thick
= abs (s
->img
->relief
);
3090 raised_p
= s
->img
->relief
> 0;
3095 x1
= x
+ s
->slice
.width
+ thick
- 1;
3096 y1
= y
+ s
->slice
.height
+ thick
- 1;
3098 x_setup_relief_colors (s
);
3099 get_glyph_string_clip_rect (s
, &r
);
3100 x_draw_relief_rect (s
->f
, x0
, y0
, x1
, y1
, thick
, raised_p
,
3102 s
->slice
.y
+ s
->slice
.height
== s
->img
->height
,
3104 s
->slice
.x
+ s
->slice
.width
== s
->img
->width
,
3109 /* Draw part of the background of glyph string S. X, Y, W, and H
3110 give the rectangle to draw. */
3113 x_draw_glyph_string_bg_rect (s
, x
, y
, w
, h
)
3114 struct glyph_string
*s
;
3117 #if 0 /* MAC_TODO: stipple */
3120 /* Fill background with a stipple pattern. */
3121 XSetFillStyle (s
->display
, s
->gc
, FillOpaqueStippled
);
3122 XFillRectangle (s
->display
, s
->window
, s
->gc
, x
, y
, w
, h
);
3123 XSetFillStyle (s
->display
, s
->gc
, FillSolid
);
3126 #endif /* MAC_TODO */
3127 x_clear_glyph_string_rect (s
, x
, y
, w
, h
);
3131 /* Draw image glyph string S.
3134 s->x +-------------------------
3137 | +-------------------------
3140 | | +-------------------
3146 x_draw_image_glyph_string (s
)
3147 struct glyph_string
*s
;
3150 int box_line_hwidth
= abs (s
->face
->box_line_width
);
3151 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
3155 height
= s
->height
- 2 * box_line_vwidth
;
3158 /* Fill background with face under the image. Do it only if row is
3159 taller than image or if image has a clip mask to reduce
3161 s
->stippled_p
= s
->face
->stipple
!= 0;
3162 if (height
> s
->slice
.height
3166 || s
->img
->pixmap
== 0
3167 || s
->width
!= s
->background_width
)
3170 if (s
->first_glyph
->left_box_line_p
3172 x
+= box_line_hwidth
;
3175 if (s
->slice
.y
== 0)
3176 y
+= box_line_vwidth
;
3178 x_draw_glyph_string_bg_rect (s
, x
, y
, s
->background_width
, height
);
3180 s
->background_filled_p
= 1;
3183 /* Draw the foreground. */
3184 x_draw_image_foreground (s
);
3186 /* If we must draw a relief around the image, do it. */
3188 || s
->hl
== DRAW_IMAGE_RAISED
3189 || s
->hl
== DRAW_IMAGE_SUNKEN
)
3190 x_draw_image_relief (s
);
3194 /* Draw stretch glyph string S. */
3197 x_draw_stretch_glyph_string (s
)
3198 struct glyph_string
*s
;
3200 xassert (s
->first_glyph
->type
== STRETCH_GLYPH
);
3201 s
->stippled_p
= s
->face
->stipple
!= 0;
3203 if (s
->hl
== DRAW_CURSOR
3204 && !x_stretch_cursor_p
)
3206 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3207 as wide as the stretch glyph. */
3208 int width
= min (FRAME_COLUMN_WIDTH (s
->f
), s
->background_width
);
3211 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, width
, s
->height
);
3213 /* Clear rest using the GC of the original non-cursor face. */
3214 if (width
< s
->background_width
)
3216 int x
= s
->x
+ width
, y
= s
->y
;
3217 int w
= s
->background_width
- width
, h
= s
->height
;
3221 if (s
->row
->mouse_face_p
3222 && cursor_in_mouse_face_p (s
->w
))
3224 x_set_mouse_face_gc (s
);
3230 get_glyph_string_clip_rect (s
, &r
);
3231 mac_set_clip_rectangles (s
->display
, gc
, &r
, 1);
3233 #if 0 /* MAC_TODO: stipple */
3234 if (s
->face
->stipple
)
3236 /* Fill background with a stipple pattern. */
3237 XSetFillStyle (s
->display
, gc
, FillOpaqueStippled
);
3238 XFillRectangle (s
->display
, s
->window
, gc
, x
, y
, w
, h
);
3239 XSetFillStyle (s
->display
, gc
, FillSolid
);
3242 #endif /* MAC_TODO */
3243 mac_erase_rectangle (s
->f
, gc
, x
, y
, w
, h
);
3246 else if (!s
->background_filled_p
)
3247 x_draw_glyph_string_bg_rect (s
, s
->x
, s
->y
, s
->background_width
,
3250 s
->background_filled_p
= 1;
3254 /* Draw glyph string S. */
3257 x_draw_glyph_string (s
)
3258 struct glyph_string
*s
;
3260 int relief_drawn_p
= 0;
3262 /* If S draws into the background of its successor that does not
3263 draw a cursor, draw the background of the successor first so that
3264 S can draw into it. This makes S->next use XDrawString instead
3265 of XDrawImageString. */
3266 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
3267 && s
->next
->hl
!= DRAW_CURSOR
)
3269 xassert (s
->next
->img
== NULL
);
3270 x_set_glyph_string_gc (s
->next
);
3271 x_set_glyph_string_clipping (s
->next
);
3272 x_draw_glyph_string_background (s
->next
, 1);
3275 /* Set up S->gc, set clipping and draw S. */
3276 x_set_glyph_string_gc (s
);
3278 /* Draw relief (if any) in advance for char/composition so that the
3279 glyph string can be drawn over it. */
3280 if (!s
->for_overlaps
3281 && s
->face
->box
!= FACE_NO_BOX
3282 && (s
->first_glyph
->type
== CHAR_GLYPH
3283 || s
->first_glyph
->type
== COMPOSITE_GLYPH
))
3286 x_set_glyph_string_clipping (s
);
3287 x_draw_glyph_string_background (s
, 1);
3288 x_draw_glyph_string_box (s
);
3289 x_set_glyph_string_clipping (s
);
3293 x_set_glyph_string_clipping (s
);
3295 switch (s
->first_glyph
->type
)
3298 x_draw_image_glyph_string (s
);
3302 x_draw_stretch_glyph_string (s
);
3306 if (s
->for_overlaps
)
3307 s
->background_filled_p
= 1;
3309 x_draw_glyph_string_background (s
, 0);
3310 x_draw_glyph_string_foreground (s
);
3313 case COMPOSITE_GLYPH
:
3314 if (s
->for_overlaps
|| s
->gidx
> 0)
3315 s
->background_filled_p
= 1;
3317 x_draw_glyph_string_background (s
, 1);
3318 x_draw_composite_glyph_string_foreground (s
);
3325 if (!s
->for_overlaps
)
3327 /* Draw underline. */
3328 if (s
->face
->underline_p
)
3330 unsigned long h
= 1;
3331 unsigned long dy
= s
->height
- h
;
3333 if (s
->face
->underline_defaulted_p
)
3334 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3339 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3340 XSetForeground (s
->display
, s
->gc
, s
->face
->underline_color
);
3341 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3343 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3347 /* Draw overline. */
3348 if (s
->face
->overline_p
)
3350 unsigned long dy
= 0, h
= 1;
3352 if (s
->face
->overline_color_defaulted_p
)
3353 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3358 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3359 XSetForeground (s
->display
, s
->gc
, s
->face
->overline_color
);
3360 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3362 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3366 /* Draw strike-through. */
3367 if (s
->face
->strike_through_p
)
3369 unsigned long h
= 1;
3370 unsigned long dy
= (s
->height
- h
) / 2;
3372 if (s
->face
->strike_through_color_defaulted_p
)
3373 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3378 XGetGCValues (s
->display
, s
->gc
, GCForeground
, &xgcv
);
3379 XSetForeground (s
->display
, s
->gc
, s
->face
->strike_through_color
);
3380 mac_fill_rectangle (s
->f
, s
->gc
, s
->x
, s
->y
+ dy
,
3382 XSetForeground (s
->display
, s
->gc
, xgcv
.foreground
);
3386 /* Draw relief if not yet drawn. */
3387 if (!relief_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3388 x_draw_glyph_string_box (s
);
3391 /* Reset clipping. */
3392 mac_reset_clip_rectangles (s
->display
, s
->gc
);
3395 /* Shift display to make room for inserted glyphs. */
3398 mac_shift_glyphs_for_insert (f
, x
, y
, width
, height
, shift_by
)
3400 int x
, y
, width
, height
, shift_by
;
3402 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3403 x
, y
, width
, height
,
3407 /* Delete N glyphs at the nominal cursor position. Not implemented
3418 /* Clear entire frame. If updating_frame is non-null, clear that
3419 frame. Otherwise clear the selected frame. */
3429 f
= SELECTED_FRAME ();
3431 /* Clearing the frame will erase any cursor, so mark them all as no
3433 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f
)));
3434 output_cursor
.hpos
= output_cursor
.vpos
= 0;
3435 output_cursor
.x
= -1;
3437 /* We don't set the output cursor here because there will always
3438 follow an explicit cursor_to. */
3440 mac_clear_window (f
);
3442 /* We have to clear the scroll bars, too. If we have changed
3443 colors or something like that, then they should be notified. */
3444 x_scroll_bar_clear (f
);
3446 XFlush (FRAME_MAC_DISPLAY (f
));
3452 /* Invert the middle quarter of the frame for .15 sec. */
3454 /* We use the select system call to do the waiting, so we have to make
3455 sure it's available. If it isn't, we just won't do visual bells. */
3457 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3460 /* Subtract the `struct timeval' values X and Y, storing the result in
3461 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3464 timeval_subtract (result
, x
, y
)
3465 struct timeval
*result
, x
, y
;
3467 /* Perform the carry for the later subtraction by updating y. This
3468 is safer because on some systems the tv_sec member is unsigned. */
3469 if (x
.tv_usec
< y
.tv_usec
)
3471 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
3472 y
.tv_usec
-= 1000000 * nsec
;
3476 if (x
.tv_usec
- y
.tv_usec
> 1000000)
3478 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
3479 y
.tv_usec
+= 1000000 * nsec
;
3483 /* Compute the time remaining to wait. tv_usec is certainly
3485 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
3486 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
3488 /* Return indication of whether the result should be considered
3490 return x
.tv_sec
< y
.tv_sec
;
3497 /* Get the height not including a menu bar widget. */
3498 int height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, FRAME_LINES (f
));
3499 /* Height of each line to flash. */
3500 int flash_height
= FRAME_LINE_HEIGHT (f
);
3501 /* These will be the left and right margins of the rectangles. */
3502 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
3503 int flash_right
= FRAME_PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
3507 /* Don't flash the area between a scroll bar and the frame
3508 edge it is next to. */
3509 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
3511 case vertical_scroll_bar_left
:
3512 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3515 case vertical_scroll_bar_right
:
3516 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3523 width
= flash_right
- flash_left
;
3527 /* If window is tall, flash top and bottom line. */
3528 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3530 mac_invert_rectangle (f
, flash_left
,
3531 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3532 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3533 width
, flash_height
);
3534 mac_invert_rectangle (f
, flash_left
,
3535 (height
- flash_height
3536 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3537 width
, flash_height
);
3540 /* If it is short, flash it all. */
3541 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3542 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3547 struct timeval wakeup
;
3549 EMACS_GET_TIME (wakeup
);
3551 /* Compute time to wait until, propagating carry from usecs. */
3552 wakeup
.tv_usec
+= 150000;
3553 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
3554 wakeup
.tv_usec
%= 1000000;
3556 /* Keep waiting until past the time wakeup or any input gets
3558 while (! detect_input_pending ())
3560 struct timeval current
;
3561 struct timeval timeout
;
3563 EMACS_GET_TIME (current
);
3565 /* Break if result would be negative. */
3566 if (timeval_subtract (¤t
, wakeup
, current
))
3569 /* How long `select' should wait. */
3571 timeout
.tv_usec
= 10000;
3573 /* Try to wait that long--but we might wake up sooner. */
3574 select (0, NULL
, NULL
, NULL
, &timeout
);
3578 /* If window is tall, flash top and bottom line. */
3579 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
3581 mac_invert_rectangle (f
, flash_left
,
3582 (FRAME_INTERNAL_BORDER_WIDTH (f
)
3583 + FRAME_TOOL_BAR_LINES (f
) * FRAME_LINE_HEIGHT (f
)),
3584 width
, flash_height
);
3585 mac_invert_rectangle (f
, flash_left
,
3586 (height
- flash_height
3587 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
3588 width
, flash_height
);
3591 /* If it is short, flash it all. */
3592 mac_invert_rectangle (f
, flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
3593 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
3600 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3603 /* Make audible bell. */
3608 struct frame
*f
= SELECTED_FRAME ();
3610 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3618 XFlush (FRAME_MAC_DISPLAY (f
));
3624 /* Specify how many text lines, from the top of the window,
3625 should be affected by insert-lines and delete-lines operations.
3626 This, and those operations, are used only within an update
3627 that is bounded by calls to x_update_begin and x_update_end. */
3630 XTset_terminal_window (n
)
3633 /* This function intentionally left blank. */
3638 /***********************************************************************
3640 ***********************************************************************/
3642 /* Perform an insert-lines or delete-lines operation, inserting N
3643 lines or deleting -N lines at vertical position VPOS. */
3646 x_ins_del_lines (vpos
, n
)
3653 /* Scroll part of the display as described by RUN. */
3656 x_scroll_run (w
, run
)
3660 struct frame
*f
= XFRAME (w
->frame
);
3661 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
3663 /* Get frame-relative bounding box of the text display area of W,
3664 without mode lines. Include in this box the left and right
3666 window_box (w
, -1, &x
, &y
, &width
, &height
);
3668 from_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->current_y
);
3669 to_y
= WINDOW_TO_FRAME_PIXEL_Y (w
, run
->desired_y
);
3670 bottom_y
= y
+ height
;
3674 /* Scrolling up. Make sure we don't copy part of the mode
3675 line at the bottom. */
3676 if (from_y
+ run
->height
> bottom_y
)
3677 height
= bottom_y
- from_y
;
3679 height
= run
->height
;
3683 /* Scolling down. Make sure we don't copy over the mode line.
3685 if (to_y
+ run
->height
> bottom_y
)
3686 height
= bottom_y
- to_y
;
3688 height
= run
->height
;
3693 /* Cursor off. Will be switched on again in x_update_window_end. */
3697 mac_scroll_area (f
, f
->output_data
.mac
->normal_gc
,
3707 /***********************************************************************
3709 ***********************************************************************/
3717 ControlRef root_control
;
3720 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3722 ActivateControl (root_control
);
3724 x_update_cursor (f
, 1);
3728 frame_unhighlight (f
)
3732 ControlRef root_control
;
3735 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3737 DeactivateControl (root_control
);
3739 x_update_cursor (f
, 1);
3742 /* The focus has changed. Update the frames as necessary to reflect
3743 the new situation. Note that we can't change the selected frame
3744 here, because the Lisp code we are interrupting might become confused.
3745 Each event gets marked with the frame in which it occurred, so the
3746 Lisp code can tell when the switch took place by examining the events. */
3749 x_new_focus_frame (dpyinfo
, frame
)
3750 struct x_display_info
*dpyinfo
;
3751 struct frame
*frame
;
3753 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
3755 if (frame
!= dpyinfo
->x_focus_frame
)
3757 /* Set this before calling other routines, so that they see
3758 the correct value of x_focus_frame. */
3759 dpyinfo
->x_focus_frame
= frame
;
3761 if (old_focus
&& old_focus
->auto_lower
)
3762 x_lower_frame (old_focus
);
3765 selected_frame
= frame
;
3766 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
3768 Fselect_window (selected_frame
->selected_window
, Qnil
);
3769 choose_minibuf_frame ();
3772 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
3773 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
3775 pending_autoraise_frame
= 0;
3778 x_frame_rehighlight (dpyinfo
);
3781 /* Handle FocusIn and FocusOut state changes for FRAME.
3782 If FRAME has focus and there exists more than one frame, puts
3783 a FOCUS_IN_EVENT into *BUFP. */
3786 mac_focus_changed (type
, dpyinfo
, frame
, bufp
)
3788 struct mac_display_info
*dpyinfo
;
3789 struct frame
*frame
;
3790 struct input_event
*bufp
;
3792 if (type
== activeFlag
)
3794 if (dpyinfo
->x_focus_event_frame
!= frame
)
3796 x_new_focus_frame (dpyinfo
, frame
);
3797 dpyinfo
->x_focus_event_frame
= frame
;
3799 /* Don't stop displaying the initial startup message
3800 for a switch-frame event we don't need. */
3801 if (GC_NILP (Vterminal_frame
)
3802 && GC_CONSP (Vframe_list
)
3803 && !GC_NILP (XCDR (Vframe_list
)))
3805 bufp
->kind
= FOCUS_IN_EVENT
;
3806 XSETFRAME (bufp
->frame_or_window
, frame
);
3812 if (dpyinfo
->x_focus_event_frame
== frame
)
3814 dpyinfo
->x_focus_event_frame
= 0;
3815 x_new_focus_frame (dpyinfo
, 0);
3820 /* The focus may have changed. Figure out if it is a real focus change,
3821 by checking both FocusIn/Out and Enter/LeaveNotify events.
3823 Returns FOCUS_IN_EVENT event in *BUFP. */
3826 x_detect_focus_change (dpyinfo
, event
, bufp
)
3827 struct mac_display_info
*dpyinfo
;
3829 struct input_event
*bufp
;
3831 struct frame
*frame
;
3833 frame
= mac_window_to_frame ((WindowPtr
) event
->message
);
3837 /* On Mac, this is only called from focus events, so no switch needed. */
3838 mac_focus_changed ((event
->modifiers
& activeFlag
),
3839 dpyinfo
, frame
, bufp
);
3843 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3846 x_mouse_leave (dpyinfo
)
3847 struct x_display_info
*dpyinfo
;
3849 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
3852 /* The focus has changed, or we have redirected a frame's focus to
3853 another frame (this happens when a frame uses a surrogate
3854 mini-buffer frame). Shift the highlight as appropriate.
3856 The FRAME argument doesn't necessarily have anything to do with which
3857 frame is being highlighted or un-highlighted; we only use it to find
3858 the appropriate X display info. */
3861 XTframe_rehighlight (frame
)
3862 struct frame
*frame
;
3864 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
3868 x_frame_rehighlight (dpyinfo
)
3869 struct x_display_info
*dpyinfo
;
3871 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
3873 if (dpyinfo
->x_focus_frame
)
3875 dpyinfo
->x_highlight_frame
3876 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
3877 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
3878 : dpyinfo
->x_focus_frame
);
3879 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
3881 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
3882 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
3886 dpyinfo
->x_highlight_frame
= 0;
3888 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
3891 frame_unhighlight (old_highlight
);
3892 if (dpyinfo
->x_highlight_frame
)
3893 frame_highlight (dpyinfo
->x_highlight_frame
);
3899 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3901 #if 0 /* MAC_TODO */
3902 /* Initialize mode_switch_bit and modifier_meaning. */
3904 x_find_modifier_meanings (dpyinfo
)
3905 struct x_display_info
*dpyinfo
;
3907 int min_code
, max_code
;
3910 XModifierKeymap
*mods
;
3912 dpyinfo
->meta_mod_mask
= 0;
3913 dpyinfo
->shift_lock_mask
= 0;
3914 dpyinfo
->alt_mod_mask
= 0;
3915 dpyinfo
->super_mod_mask
= 0;
3916 dpyinfo
->hyper_mod_mask
= 0;
3919 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
3921 min_code
= dpyinfo
->display
->min_keycode
;
3922 max_code
= dpyinfo
->display
->max_keycode
;
3925 syms
= XGetKeyboardMapping (dpyinfo
->display
,
3926 min_code
, max_code
- min_code
+ 1,
3928 mods
= XGetModifierMapping (dpyinfo
->display
);
3930 /* Scan the modifier table to see which modifier bits the Meta and
3931 Alt keysyms are on. */
3933 int row
, col
; /* The row and column in the modifier table. */
3935 for (row
= 3; row
< 8; row
++)
3936 for (col
= 0; col
< mods
->max_keypermod
; col
++)
3939 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
3941 /* Zeroes are used for filler. Skip them. */
3945 /* Are any of this keycode's keysyms a meta key? */
3949 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
3951 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
3957 dpyinfo
->meta_mod_mask
|= (1 << row
);
3962 dpyinfo
->alt_mod_mask
|= (1 << row
);
3967 dpyinfo
->hyper_mod_mask
|= (1 << row
);
3972 dpyinfo
->super_mod_mask
|= (1 << row
);
3976 /* Ignore this if it's not on the lock modifier. */
3977 if ((1 << row
) == LockMask
)
3978 dpyinfo
->shift_lock_mask
= LockMask
;
3986 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3987 if (! dpyinfo
->meta_mod_mask
)
3989 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
3990 dpyinfo
->alt_mod_mask
= 0;
3993 /* If some keys are both alt and meta,
3994 make them just meta, not alt. */
3995 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
3997 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
4000 XFree ((char *) syms
);
4001 XFreeModifiermap (mods
);
4004 #endif /* MAC_TODO */
4006 /* Convert between the modifier bits X uses and the modifier bits
4010 x_mac_to_emacs_modifiers (dpyinfo
, state
)
4011 struct x_display_info
*dpyinfo
;
4012 unsigned short state
;
4014 return (((state
& shiftKey
) ? shift_modifier
: 0)
4015 | ((state
& controlKey
) ? ctrl_modifier
: 0)
4016 | ((state
& cmdKey
) ? meta_modifier
: 0)
4017 | ((state
& optionKey
) ? alt_modifier
: 0));
4020 #if 0 /* MAC_TODO */
4021 static unsigned short
4022 x_emacs_to_x_modifiers (dpyinfo
, state
)
4023 struct x_display_info
*dpyinfo
;
4026 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
4027 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
4028 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
4029 | ((state
& shift_modifier
) ? ShiftMask
: 0)
4030 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
4031 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
4033 #endif /* MAC_TODO */
4035 /* Convert a keysym to its name. */
4038 x_get_keysym_name (keysym
)
4045 value
= XKeysymToString (keysym
);
4056 /* Function to report a mouse movement to the mainstream Emacs code.
4057 The input handler calls this.
4059 We have received a mouse movement event, which is given in *event.
4060 If the mouse is over a different glyph than it was last time, tell
4061 the mainstream emacs code by setting mouse_moved. If not, ask for
4062 another motion event, so we can check again the next time it moves. */
4064 static Point last_mouse_motion_position
;
4065 static Lisp_Object last_mouse_motion_frame
;
4068 note_mouse_movement (frame
, pos
)
4072 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (frame
);
4073 #if TARGET_API_MAC_CARBON
4077 last_mouse_movement_time
= TickCount () * (1000 / 60); /* to milliseconds */
4078 last_mouse_motion_position
= *pos
;
4079 XSETFRAME (last_mouse_motion_frame
, frame
);
4081 #if TARGET_API_MAC_CARBON
4082 if (!PtInRect (*pos
, GetWindowPortBounds (FRAME_MAC_WINDOW (frame
), &r
)))
4084 if (!PtInRect (*pos
, &FRAME_MAC_WINDOW (frame
)->portRect
))
4087 if (frame
== dpyinfo
->mouse_face_mouse_frame
)
4088 /* This case corresponds to LeaveNotify in X11. */
4090 /* If we move outside the frame, then we're certainly no
4091 longer on any text in the frame. */
4092 clear_mouse_face (dpyinfo
);
4093 dpyinfo
->mouse_face_mouse_frame
= 0;
4094 if (!dpyinfo
->grabbed
)
4095 rif
->define_frame_cursor (frame
,
4096 frame
->output_data
.mac
->nontext_cursor
);
4100 /* Has the mouse moved off the glyph it was on at the last sighting? */
4101 if (frame
!= last_mouse_glyph_frame
4102 || !PtInRect (*pos
, &last_mouse_glyph
))
4104 frame
->mouse_moved
= 1;
4105 last_mouse_scroll_bar
= Qnil
;
4106 note_mouse_highlight (frame
, pos
->h
, pos
->v
);
4107 /* Remember which glyph we're now on. */
4108 remember_mouse_glyph (frame
, pos
->h
, pos
->v
, &last_mouse_glyph
);
4109 last_mouse_glyph_frame
= frame
;
4117 /************************************************************************
4119 ************************************************************************/
4121 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
4124 redo_mouse_highlight ()
4126 if (!NILP (last_mouse_motion_frame
)
4127 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame
)))
4128 note_mouse_highlight (XFRAME (last_mouse_motion_frame
),
4129 last_mouse_motion_position
.h
,
4130 last_mouse_motion_position
.v
);
4134 static struct frame
*
4135 mac_focus_frame (dpyinfo
)
4136 struct mac_display_info
*dpyinfo
;
4138 if (dpyinfo
->x_focus_frame
)
4139 return dpyinfo
->x_focus_frame
;
4141 /* Mac version may get events, such as a menu bar click, even when
4142 all the frames are invisible. In this case, we regard the
4143 event came to the selected frame. */
4144 return SELECTED_FRAME ();
4148 /* Return the current position of the mouse.
4149 *FP should be a frame which indicates which display to ask about.
4151 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
4152 and *PART to the frame, window, and scroll bar part that the mouse
4153 is over. Set *X and *Y to the portion and whole of the mouse's
4154 position on the scroll bar.
4156 If the mouse movement started elsewhere, set *FP to the frame the
4157 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
4160 Set *TIME to the server time-stamp for the time at which the mouse
4161 was at this position.
4163 Don't store anything if we don't have a valid set of values to report.
4165 This clears the mouse_moved flag, so we can wait for the next mouse
4169 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
4172 Lisp_Object
*bar_window
;
4173 enum scroll_bar_part
*part
;
4175 unsigned long *time
;
4181 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
4182 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
4185 Lisp_Object frame
, tail
;
4187 /* Clear the mouse-moved flag for every frame on this display. */
4188 FOR_EACH_FRAME (tail
, frame
)
4189 XFRAME (frame
)->mouse_moved
= 0;
4191 last_mouse_scroll_bar
= Qnil
;
4193 if (FRAME_MAC_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
4194 && FRAME_LIVE_P (last_mouse_frame
))
4195 f1
= last_mouse_frame
;
4197 f1
= mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp
));
4201 /* Ok, we found a frame. Store all the values.
4202 last_mouse_glyph is a rectangle used to reduce the
4203 generation of mouse events. To not miss any motion
4204 events, we must divide the frame into rectangles of the
4205 size of the smallest character that could be displayed
4206 on it, i.e. into the same rectangles that matrices on
4207 the frame are divided into. */
4210 SetPortWindowPort (FRAME_MAC_WINDOW (f1
));
4211 GetMouse (&mouse_pos
);
4212 remember_mouse_glyph (f1
, mouse_pos
.h
, mouse_pos
.v
,
4214 last_mouse_glyph_frame
= f1
;
4219 XSETINT (*x
, mouse_pos
.h
);
4220 XSETINT (*y
, mouse_pos
.v
);
4221 *time
= last_mouse_movement_time
;
4229 /************************************************************************
4231 ************************************************************************/
4233 #ifdef USE_TOOLKIT_SCROLL_BARS
4235 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
4236 static OSStatus install_scroll_bar_timer
P_ ((void));
4237 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
4238 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
4239 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
4240 struct input_event
*));
4241 static OSErr get_control_part_bounds
P_ ((ControlHandle
, ControlPartCode
,
4243 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
4245 struct input_event
*));
4246 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
4247 struct input_event
*));
4248 static void x_scroll_bar_handle_drag
P_ ((WindowPtr
, struct scroll_bar
*,
4249 Point
, struct input_event
*));
4250 static void x_set_toolkit_scroll_bar_thumb
P_ ((struct scroll_bar
*,
4253 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
4255 static int last_scroll_bar_part
;
4257 static EventLoopTimerRef scroll_bar_timer
;
4259 static int scroll_bar_timer_event_posted_p
;
4261 #define SCROLL_BAR_FIRST_DELAY 0.5
4262 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
4265 scroll_bar_timer_callback (timer
, data
)
4266 EventLoopTimerRef timer
;
4269 EventRef event
= NULL
;
4272 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
4273 kEventAttributeNone
, &event
);
4278 GetMouse (&mouse_pos
);
4279 LocalToGlobal (&mouse_pos
);
4280 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
4281 sizeof (Point
), &mouse_pos
);
4285 UInt32 modifiers
= GetCurrentKeyModifiers ();
4287 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
4288 sizeof (UInt32
), &modifiers
);
4291 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
4292 kEventPriorityStandard
);
4294 scroll_bar_timer_event_posted_p
= 1;
4297 ReleaseEvent (event
);
4301 install_scroll_bar_timer ()
4303 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
4305 if (scroll_bar_timer_callbackUPP
== NULL
)
4306 scroll_bar_timer_callbackUPP
=
4307 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
4309 if (scroll_bar_timer
== NULL
)
4310 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
4311 kEventDurationForever as delays. */
4313 InstallEventLoopTimer (GetCurrentEventLoop (),
4314 kEventDurationForever
, kEventDurationForever
,
4315 scroll_bar_timer_callbackUPP
, NULL
,
4320 set_scroll_bar_timer (delay
)
4321 EventTimerInterval delay
;
4323 if (scroll_bar_timer
== NULL
)
4324 install_scroll_bar_timer ();
4326 scroll_bar_timer_event_posted_p
= 0;
4328 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
4332 control_part_code_to_scroll_bar_part (part_code
)
4333 ControlPartCode part_code
;
4337 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
4338 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
4339 case kControlPageUpPart
: return scroll_bar_above_handle
;
4340 case kControlPageDownPart
: return scroll_bar_below_handle
;
4341 case kControlIndicatorPart
: return scroll_bar_handle
;
4348 construct_scroll_bar_click (bar
, part
, bufp
)
4349 struct scroll_bar
*bar
;
4351 struct input_event
*bufp
;
4353 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4354 bufp
->frame_or_window
= bar
->window
;
4358 XSETINT (bufp
->x
, 0);
4359 XSETINT (bufp
->y
, 0);
4360 bufp
->modifiers
= 0;
4364 get_control_part_bounds (ch
, part_code
, rect
)
4366 ControlPartCode part_code
;
4369 RgnHandle region
= NewRgn ();
4372 err
= GetControlRegion (ch
, part_code
, region
);
4374 GetRegionBounds (region
, rect
);
4375 DisposeRgn (region
);
4381 x_scroll_bar_handle_press (bar
, part_code
, bufp
)
4382 struct scroll_bar
*bar
;
4383 ControlPartCode part_code
;
4384 struct input_event
*bufp
;
4386 int part
= control_part_code_to_scroll_bar_part (part_code
);
4391 if (part
!= scroll_bar_handle
)
4393 construct_scroll_bar_click (bar
, part
, bufp
);
4394 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4395 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
4398 last_scroll_bar_part
= part
;
4399 bar
->dragging
= Qnil
;
4400 tracked_scroll_bar
= bar
;
4404 x_scroll_bar_handle_release (bar
, bufp
)
4405 struct scroll_bar
*bar
;
4406 struct input_event
*bufp
;
4408 if (last_scroll_bar_part
!= scroll_bar_handle
4409 || !GC_NILP (bar
->dragging
))
4410 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
4412 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4413 set_scroll_bar_timer (kEventDurationForever
);
4415 last_scroll_bar_part
= -1;
4416 bar
->dragging
= Qnil
;
4417 tracked_scroll_bar
= NULL
;
4421 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
4423 struct scroll_bar
*bar
;
4425 struct input_event
*bufp
;
4427 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4429 if (last_scroll_bar_part
== scroll_bar_handle
)
4434 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar
),
4435 kControlIndicatorPart
, &r
);
4437 if (GC_NILP (bar
->dragging
))
4438 XSETINT (bar
->dragging
, mouse_pos
.v
- r
.top
);
4440 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
4441 top_range
= (XINT (bar
->track_height
) - (r
.bottom
- r
.top
)) *
4442 (1.0 + (float) GetControlViewSize (ch
) / GetControl32BitMaximum (ch
))
4447 if (top
> top_range
)
4450 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
4451 XSETINT (bufp
->x
, top
);
4452 XSETINT (bufp
->y
, top_range
);
4456 ControlPartCode part_code
;
4457 int unhilite_p
= 0, part
;
4459 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
4463 part
= control_part_code_to_scroll_bar_part (part_code
);
4465 switch (last_scroll_bar_part
)
4467 case scroll_bar_above_handle
:
4468 case scroll_bar_below_handle
:
4469 if (part
!= scroll_bar_above_handle
4470 && part
!= scroll_bar_below_handle
)
4474 case scroll_bar_up_arrow
:
4475 case scroll_bar_down_arrow
:
4476 if (part
!= scroll_bar_up_arrow
4477 && part
!= scroll_bar_down_arrow
)
4484 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), 0);
4485 else if (part
!= last_scroll_bar_part
4486 || scroll_bar_timer_event_posted_p
)
4488 construct_scroll_bar_click (bar
, part
, bufp
);
4489 last_scroll_bar_part
= part
;
4490 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar
), part_code
);
4491 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
4496 /* Set the thumb size and position of scroll bar BAR. We are currently
4497 displaying PORTION out of a whole WHOLE, and our position POSITION. */
4500 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
4501 struct scroll_bar
*bar
;
4502 int portion
, position
, whole
;
4504 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4506 int value
, viewsize
, maximum
;
4508 if (whole
== 0 || XINT (bar
->track_height
) == 0)
4509 value
= 0, viewsize
= 1, maximum
= 0;
4514 maximum
= max (0, whole
- portion
);
4519 SetControl32BitMinimum (ch
, 0);
4520 SetControl32BitMaximum (ch
, maximum
);
4521 SetControl32BitValue (ch
, value
);
4522 SetControlViewSize (ch
, viewsize
);
4527 #endif /* USE_TOOLKIT_SCROLL_BARS */
4531 /************************************************************************
4532 Scroll bars, general
4533 ************************************************************************/
4535 /* Create a scroll bar and return the scroll bar vector for it. W is
4536 the Emacs window on which to create the scroll bar. TOP, LEFT,
4537 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4540 static struct scroll_bar
*
4541 x_scroll_bar_create (w
, top
, left
, width
, height
, disp_top
, disp_height
)
4543 int top
, left
, width
, height
, disp_top
, disp_height
;
4545 struct frame
*f
= XFRAME (w
->frame
);
4546 struct scroll_bar
*bar
4547 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
4555 r
.right
= left
+ width
;
4556 r
.bottom
= disp_top
+ disp_height
;
4558 #if TARGET_API_MAC_CARBON
4559 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4560 0, 0, 0, kControlScrollBarProc
, (long) bar
);
4562 ch
= NewControl (FRAME_MAC_WINDOW (f
), &r
, "\p", width
< disp_height
,
4563 0, 0, 0, scrollBarProc
, (long) bar
);
4565 SET_SCROLL_BAR_CONTROL_HANDLE (bar
, ch
);
4567 XSETWINDOW (bar
->window
, w
);
4568 XSETINT (bar
->top
, top
);
4569 XSETINT (bar
->left
, left
);
4570 XSETINT (bar
->width
, width
);
4571 XSETINT (bar
->height
, height
);
4572 XSETINT (bar
->start
, 0);
4573 XSETINT (bar
->end
, 0);
4574 bar
->dragging
= Qnil
;
4575 #ifdef USE_TOOLKIT_SCROLL_BARS
4576 bar
->track_top
= Qnil
;
4577 bar
->track_height
= Qnil
;
4580 /* Add bar to its frame's list of scroll bars. */
4581 bar
->next
= FRAME_SCROLL_BARS (f
);
4583 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4584 if (!NILP (bar
->next
))
4585 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4592 /* Draw BAR's handle in the proper position.
4594 If the handle is already drawn from START to END, don't bother
4595 redrawing it, unless REBUILD is non-zero; in that case, always
4596 redraw it. (REBUILD is handy for drawing the handle after expose
4599 Normally, we want to constrain the start and end of the handle to
4600 fit inside its rectangle, but if the user is dragging the scroll
4601 bar handle, we want to let them drag it down all the way, so that
4602 the bar's top is as far down as it goes; otherwise, there's no way
4603 to move to the very end of the buffer. */
4605 #ifndef USE_TOOLKIT_SCROLL_BARS
4608 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
4609 struct scroll_bar
*bar
;
4613 int dragging
= ! NILP (bar
->dragging
);
4614 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4615 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4616 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
4617 int length
= end
- start
;
4619 /* If the display is already accurate, do nothing. */
4621 && start
== XINT (bar
->start
)
4622 && end
== XINT (bar
->end
))
4627 /* Make sure the values are reasonable, and try to preserve the
4628 distance between start and end. */
4631 else if (start
> top_range
)
4633 end
= start
+ length
;
4637 else if (end
> top_range
&& ! dragging
)
4640 /* Store the adjusted setting in the scroll bar. */
4641 XSETINT (bar
->start
, start
);
4642 XSETINT (bar
->end
, end
);
4644 /* Clip the end position, just for display. */
4645 if (end
> top_range
)
4648 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4649 top positions, to make sure the handle is always at least that
4650 many pixels tall. */
4651 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
4653 SetControlMinimum (ch
, 0);
4654 /* Don't inadvertently activate deactivated scroll bars */
4655 if (GetControlMaximum (ch
) != -1)
4656 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
4658 SetControlValue (ch
, start
);
4659 #if TARGET_API_MAC_CARBON
4660 SetControlViewSize (ch
, end
- start
);
4666 #endif /* !USE_TOOLKIT_SCROLL_BARS */
4668 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4672 x_scroll_bar_remove (bar
)
4673 struct scroll_bar
*bar
;
4675 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
4679 /* Destroy the Mac scroll bar control */
4680 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar
));
4682 /* Disassociate this scroll bar from its window. */
4683 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
4689 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4690 that we are displaying PORTION characters out of a total of WHOLE
4691 characters, starting at POSITION. If WINDOW has no scroll bar,
4695 XTset_vertical_scroll_bar (w
, portion
, whole
, position
)
4697 int portion
, whole
, position
;
4699 struct frame
*f
= XFRAME (w
->frame
);
4700 struct scroll_bar
*bar
;
4701 int top
, height
, left
, sb_left
, width
, sb_width
, disp_top
, disp_height
;
4702 int window_y
, window_height
;
4704 /* Get window dimensions. */
4705 window_box (w
, -1, 0, &window_y
, 0, &window_height
);
4707 width
= WINDOW_CONFIG_SCROLL_BAR_COLS (w
) * FRAME_COLUMN_WIDTH (f
);
4708 height
= window_height
;
4710 /* Compute the left edge of the scroll bar area. */
4711 left
= WINDOW_SCROLL_BAR_AREA_X (w
);
4713 /* Compute the width of the scroll bar which might be less than
4714 the width of the area reserved for the scroll bar. */
4715 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
) > 0)
4716 sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH (w
);
4720 /* Compute the left edge of the scroll bar. */
4721 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w
))
4724 sb_left
= left
+ width
- sb_width
;
4726 /* Adjustments according to Inside Macintosh to make it look nice */
4728 disp_height
= height
;
4734 else if (disp_top
== FRAME_PIXEL_HEIGHT (f
) - 16)
4740 if (sb_left
+ sb_width
== FRAME_PIXEL_WIDTH (f
))
4743 /* Does the scroll bar exist yet? */
4744 if (NILP (w
->vertical_scroll_bar
))
4747 mac_clear_area (f
, left
, top
, width
, height
);
4749 bar
= x_scroll_bar_create (w
, top
, sb_left
, sb_width
, height
, disp_top
,
4751 XSETVECTOR (w
->vertical_scroll_bar
, bar
);
4755 /* It may just need to be moved and resized. */
4758 bar
= XSCROLL_BAR (w
->vertical_scroll_bar
);
4759 ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4763 /* If already correctly positioned, do nothing. */
4764 if (!(XINT (bar
->left
) == sb_left
4765 && XINT (bar
->top
) == top
4766 && XINT (bar
->width
) == sb_width
4767 && XINT (bar
->height
) == height
))
4769 /* Since toolkit scroll bars are smaller than the space reserved
4770 for them on the frame, we have to clear "under" them. */
4771 mac_clear_area (f
, left
, top
, width
, height
);
4774 MoveControl (ch
, sb_left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, disp_top
);
4775 SizeControl (ch
, sb_width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2,
4777 if (sb_width
< disp_height
)
4780 /* Remember new settings. */
4781 XSETINT (bar
->left
, sb_left
);
4782 XSETINT (bar
->top
, top
);
4783 XSETINT (bar
->width
, sb_width
);
4784 XSETINT (bar
->height
, height
);
4785 #ifdef USE_TOOLKIT_SCROLL_BARS
4786 bar
->track_top
= Qnil
;
4787 bar
->track_height
= Qnil
;
4794 #ifdef USE_TOOLKIT_SCROLL_BARS
4795 if (NILP (bar
->track_top
))
4797 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
4802 SetControl32BitMinimum (ch
, 0);
4803 SetControl32BitMaximum (ch
, 1);
4804 SetControlViewSize (ch
, 1);
4806 /* Move the scroll bar thumb to the top. */
4807 SetControl32BitValue (ch
, 0);
4808 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
4810 /* Move the scroll bar thumb to the bottom. */
4811 SetControl32BitValue (ch
, 1);
4812 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
4814 UnionRect (&r0
, &r1
, &r0
);
4815 XSETINT (bar
->track_top
, r0
.top
);
4816 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
4821 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
);
4822 #else /* not USE_TOOLKIT_SCROLL_BARS */
4823 /* Set the scroll bar's current state, unless we're currently being
4825 if (NILP (bar
->dragging
))
4827 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, height
);
4830 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
4833 int start
= ((double) position
* top_range
) / whole
;
4834 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
4835 x_scroll_bar_set_handle (bar
, start
, end
, 0);
4838 #endif /* not USE_TOOLKIT_SCROLL_BARS */
4842 /* The following three hooks are used when we're doing a thorough
4843 redisplay of the frame. We don't explicitly know which scroll bars
4844 are going to be deleted, because keeping track of when windows go
4845 away is a real pain - "Can you say set-window-configuration, boys
4846 and girls?" Instead, we just assert at the beginning of redisplay
4847 that *all* scroll bars are to be removed, and then save a scroll bar
4848 from the fiery pit when we actually redisplay its window. */
4850 /* Arrange for all scroll bars on FRAME to be removed at the next call
4851 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4852 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4855 XTcondemn_scroll_bars (frame
)
4858 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4859 while (! NILP (FRAME_SCROLL_BARS (frame
)))
4862 bar
= FRAME_SCROLL_BARS (frame
);
4863 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
4864 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
4865 XSCROLL_BAR (bar
)->prev
= Qnil
;
4866 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
4867 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
4868 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
4873 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4874 Note that WINDOW isn't necessarily condemned at all. */
4877 XTredeem_scroll_bar (window
)
4878 struct window
*window
;
4880 struct scroll_bar
*bar
;
4883 /* We can't redeem this window's scroll bar if it doesn't have one. */
4884 if (NILP (window
->vertical_scroll_bar
))
4887 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
4889 /* Unlink it from the condemned list. */
4890 f
= XFRAME (WINDOW_FRAME (window
));
4891 if (NILP (bar
->prev
))
4893 /* If the prev pointer is nil, it must be the first in one of
4895 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
4896 /* It's not condemned. Everything's fine. */
4898 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
4899 window
->vertical_scroll_bar
))
4900 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
4902 /* If its prev pointer is nil, it must be at the front of
4903 one or the other! */
4907 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
4909 if (! NILP (bar
->next
))
4910 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
4912 bar
->next
= FRAME_SCROLL_BARS (f
);
4914 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
4915 if (! NILP (bar
->next
))
4916 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
4919 /* Remove all scroll bars on FRAME that haven't been saved since the
4920 last call to `*condemn_scroll_bars_hook'. */
4923 XTjudge_scroll_bars (f
)
4926 Lisp_Object bar
, next
;
4928 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
4930 /* Clear out the condemned list now so we won't try to process any
4931 more events on the hapless scroll bars. */
4932 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
4934 for (; ! NILP (bar
); bar
= next
)
4936 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
4938 x_scroll_bar_remove (b
);
4941 b
->next
= b
->prev
= Qnil
;
4944 /* Now there should be no references to the condemned scroll bars,
4945 and they should get garbage-collected. */
4949 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4950 is set to something other than NO_EVENT, it is enqueued.
4952 This may be called from a signal handler, so we have to ignore GC
4956 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
4957 struct scroll_bar
*bar
;
4958 ControlPartCode part_code
;
4960 struct input_event
*bufp
;
4962 int win_y
, top_range
;
4964 if (! GC_WINDOWP (bar
->window
))
4967 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
4968 bufp
->frame_or_window
= bar
->window
;
4971 bar
->dragging
= Qnil
;
4975 case kControlUpButtonPart
:
4976 bufp
->part
= scroll_bar_up_arrow
;
4978 case kControlDownButtonPart
:
4979 bufp
->part
= scroll_bar_down_arrow
;
4981 case kControlPageUpPart
:
4982 bufp
->part
= scroll_bar_above_handle
;
4984 case kControlPageDownPart
:
4985 bufp
->part
= scroll_bar_below_handle
;
4987 #if TARGET_API_MAC_CARBON
4990 case kControlIndicatorPart
:
4992 if (er
->what
== mouseDown
)
4993 bar
->dragging
= make_number (0);
4994 XSETVECTOR (last_mouse_scroll_bar
, bar
);
4995 bufp
->part
= scroll_bar_handle
;
4999 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
5000 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
5002 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5006 if (! NILP (bar
->dragging
))
5007 win_y
-= XINT (bar
->dragging
);
5011 if (win_y
> top_range
)
5014 XSETINT (bufp
->x
, win_y
);
5015 XSETINT (bufp
->y
, top_range
);
5018 #ifndef USE_TOOLKIT_SCROLL_BARS
5020 /* Handle some mouse motion while someone is dragging the scroll bar.
5022 This may be called from a signal handler, so we have to ignore GC
5026 x_scroll_bar_note_movement (bar
, y_pos
, t
)
5027 struct scroll_bar
*bar
;
5031 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
5033 last_mouse_movement_time
= t
;
5036 XSETVECTOR (last_mouse_scroll_bar
, bar
);
5038 /* If we're dragging the bar, display it. */
5039 if (! GC_NILP (bar
->dragging
))
5041 /* Where should the handle be now? */
5042 int new_start
= y_pos
- 24;
5044 if (new_start
!= XINT (bar
->start
))
5046 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
5048 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
5053 #endif /* !USE_TOOLKIT_SCROLL_BARS */
5055 /* Return information to the user about the current position of the mouse
5056 on the scroll bar. */
5059 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
5061 Lisp_Object
*bar_window
;
5062 enum scroll_bar_part
*part
;
5064 unsigned long *time
;
5066 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
5067 ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (bar
);
5068 #if TARGET_API_MAC_CARBON
5069 WindowPtr wp
= GetControlOwner (ch
);
5071 WindowPtr wp
= (*ch
)->contrlOwner
;
5074 struct frame
*f
= mac_window_to_frame (wp
);
5075 int win_y
, top_range
;
5077 SetPortWindowPort (wp
);
5079 GetMouse (&mouse_pos
);
5081 win_y
= mouse_pos
.v
- XINT (bar
->top
);
5082 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
5084 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
5088 if (! NILP (bar
->dragging
))
5089 win_y
-= XINT (bar
->dragging
);
5093 if (win_y
> top_range
)
5097 *bar_window
= bar
->window
;
5099 if (! NILP (bar
->dragging
))
5100 *part
= scroll_bar_handle
;
5101 else if (win_y
< XINT (bar
->start
))
5102 *part
= scroll_bar_above_handle
;
5103 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
5104 *part
= scroll_bar_handle
;
5106 *part
= scroll_bar_below_handle
;
5108 XSETINT (*x
, win_y
);
5109 XSETINT (*y
, top_range
);
5112 last_mouse_scroll_bar
= Qnil
;
5114 *time
= last_mouse_movement_time
;
5118 /* The screen has been cleared so we may have changed foreground or
5119 background colors, and the scroll bars may need to be redrawn.
5120 Clear out the scroll bars, and ask for expose events, so we can
5124 x_scroll_bar_clear (f
)
5127 XTcondemn_scroll_bars (f
);
5128 XTjudge_scroll_bars (f
);
5132 /***********************************************************************
5134 ***********************************************************************/
5136 /* Set clipping for output in glyph row ROW. W is the window in which
5137 we operate. GC is the graphics context to set clipping in.
5139 ROW may be a text row or, e.g., a mode line. Text rows must be
5140 clipped to the interior of the window dedicated to text display,
5141 mode lines must be clipped to the whole window. */
5144 x_clip_to_row (w
, row
, area
, gc
)
5146 struct glyph_row
*row
;
5150 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5152 int window_x
, window_y
, window_width
;
5154 window_box (w
, area
, &window_x
, &window_y
, &window_width
, 0);
5156 clip_rect
.left
= window_x
;
5157 clip_rect
.top
= WINDOW_TO_FRAME_PIXEL_Y (w
, row
->y
);
5158 clip_rect
.top
= max (clip_rect
.top
, window_y
);
5159 clip_rect
.right
= clip_rect
.left
+ window_width
;
5160 clip_rect
.bottom
= clip_rect
.top
+ row
->visible_height
;
5162 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f
), gc
, &clip_rect
, 1);
5166 /* Draw a hollow box cursor on window W in glyph row ROW. */
5169 x_draw_hollow_cursor (w
, row
)
5171 struct glyph_row
*row
;
5173 struct frame
*f
= XFRAME (WINDOW_FRAME (w
));
5174 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
5175 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5178 struct glyph
*cursor_glyph
;
5181 /* Get the glyph the cursor is on. If we can't tell because
5182 the current matrix is invalid or such, give up. */
5183 cursor_glyph
= get_phys_cursor_glyph (w
);
5184 if (cursor_glyph
== NULL
)
5187 /* Compute frame-relative coordinates for phys cursor. */
5188 x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
);
5189 y
= get_phys_cursor_geometry (w
, row
, cursor_glyph
, &h
);
5190 wd
= w
->phys_cursor_width
;
5192 /* The foreground of cursor_gc is typically the same as the normal
5193 background color, which can cause the cursor box to be invisible. */
5194 xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5195 if (dpyinfo
->scratch_cursor_gc
)
5196 XChangeGC (dpy
, dpyinfo
->scratch_cursor_gc
, GCForeground
, &xgcv
);
5198 dpyinfo
->scratch_cursor_gc
= XCreateGC (dpy
, FRAME_MAC_WINDOW (f
),
5199 GCForeground
, &xgcv
);
5200 gc
= dpyinfo
->scratch_cursor_gc
;
5202 /* Set clipping, draw the rectangle, and reset clipping again. */
5203 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5204 mac_draw_rectangle (f
, gc
, x
, y
, wd
, h
);
5205 mac_reset_clip_rectangles (dpy
, gc
);
5209 /* Draw a bar cursor on window W in glyph row ROW.
5211 Implementation note: One would like to draw a bar cursor with an
5212 angle equal to the one given by the font property XA_ITALIC_ANGLE.
5213 Unfortunately, I didn't find a font yet that has this property set.
5217 x_draw_bar_cursor (w
, row
, width
, kind
)
5219 struct glyph_row
*row
;
5221 enum text_cursor_kinds kind
;
5223 struct frame
*f
= XFRAME (w
->frame
);
5224 struct glyph
*cursor_glyph
;
5226 /* If cursor is out of bounds, don't draw garbage. This can happen
5227 in mini-buffer windows when switching between echo area glyphs
5229 cursor_glyph
= get_phys_cursor_glyph (w
);
5230 if (cursor_glyph
== NULL
)
5233 /* If on an image, draw like a normal cursor. That's usually better
5234 visible than drawing a bar, esp. if the image is large so that
5235 the bar might not be in the window. */
5236 if (cursor_glyph
->type
== IMAGE_GLYPH
)
5238 struct glyph_row
*row
;
5239 row
= MATRIX_ROW (w
->current_matrix
, w
->phys_cursor
.vpos
);
5240 draw_phys_cursor_glyph (w
, row
, DRAW_CURSOR
);
5244 Display
*dpy
= FRAME_MAC_DISPLAY (f
);
5245 Window window
= FRAME_MAC_WINDOW (f
);
5246 GC gc
= FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
;
5247 unsigned long mask
= GCForeground
| GCBackground
;
5248 struct face
*face
= FACE_FROM_ID (f
, cursor_glyph
->face_id
);
5251 /* If the glyph's background equals the color we normally draw
5252 the bar cursor in, the bar cursor in its normal color is
5253 invisible. Use the glyph's foreground color instead in this
5254 case, on the assumption that the glyph's colors are chosen so
5255 that the glyph is legible. */
5256 if (face
->background
== f
->output_data
.mac
->cursor_pixel
)
5257 xgcv
.background
= xgcv
.foreground
= face
->foreground
;
5259 xgcv
.background
= xgcv
.foreground
= f
->output_data
.mac
->cursor_pixel
;
5262 XChangeGC (dpy
, gc
, mask
, &xgcv
);
5265 gc
= XCreateGC (dpy
, window
, mask
, &xgcv
);
5266 FRAME_MAC_DISPLAY_INFO (f
)->scratch_cursor_gc
= gc
;
5270 width
= FRAME_CURSOR_WIDTH (f
);
5271 width
= min (cursor_glyph
->pixel_width
, width
);
5273 w
->phys_cursor_width
= width
;
5274 x_clip_to_row (w
, row
, TEXT_AREA
, gc
);
5276 if (kind
== BAR_CURSOR
)
5277 mac_fill_rectangle (f
, gc
,
5278 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5279 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
),
5280 width
, row
->height
);
5282 mac_fill_rectangle (f
, gc
,
5283 WINDOW_TEXT_TO_FRAME_PIXEL_X (w
, w
->phys_cursor
.x
),
5284 WINDOW_TO_FRAME_PIXEL_Y (w
, w
->phys_cursor
.y
+
5285 row
->height
- width
),
5286 cursor_glyph
->pixel_width
,
5289 mac_reset_clip_rectangles (dpy
, gc
);
5294 /* RIF: Define cursor CURSOR on frame F. */
5297 mac_define_frame_cursor (f
, cursor
)
5301 SetThemeCursor (cursor
);
5305 /* RIF: Clear area on frame F. */
5308 mac_clear_frame_area (f
, x
, y
, width
, height
)
5310 int x
, y
, width
, height
;
5312 mac_clear_area (f
, x
, y
, width
, height
);
5316 /* RIF: Draw cursor on window W. */
5319 mac_draw_window_cursor (w
, glyph_row
, x
, y
, cursor_type
, cursor_width
, on_p
, active_p
)
5321 struct glyph_row
*glyph_row
;
5323 int cursor_type
, cursor_width
;
5328 w
->phys_cursor_type
= cursor_type
;
5329 w
->phys_cursor_on_p
= 1;
5331 if (glyph_row
->exact_window_width_line_p
5332 && w
->phys_cursor
.hpos
>= glyph_row
->used
[TEXT_AREA
])
5334 glyph_row
->cursor_in_fringe_p
= 1;
5335 draw_fringe_bitmap (w
, glyph_row
, 0);
5338 switch (cursor_type
)
5340 case HOLLOW_BOX_CURSOR
:
5341 x_draw_hollow_cursor (w
, glyph_row
);
5344 case FILLED_BOX_CURSOR
:
5345 draw_phys_cursor_glyph (w
, glyph_row
, DRAW_CURSOR
);
5349 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, BAR_CURSOR
);
5353 x_draw_bar_cursor (w
, glyph_row
, cursor_width
, HBAR_CURSOR
);
5357 w
->phys_cursor_width
= 0;
5369 #if 0 /* MAC_TODO: no icon support yet. */
5371 x_bitmap_icon (f
, icon
)
5377 if (FRAME_W32_WINDOW (f
) == 0)
5381 hicon
= LoadIcon (hinst
, EMACS_CLASS
);
5382 else if (STRINGP (icon
))
5383 hicon
= LoadImage (NULL
, (LPCTSTR
) SDATA (icon
), IMAGE_ICON
, 0, 0,
5384 LR_DEFAULTSIZE
| LR_LOADFROMFILE
);
5385 else if (SYMBOLP (icon
))
5389 if (EQ (icon
, intern ("application")))
5390 name
= (LPCTSTR
) IDI_APPLICATION
;
5391 else if (EQ (icon
, intern ("hand")))
5392 name
= (LPCTSTR
) IDI_HAND
;
5393 else if (EQ (icon
, intern ("question")))
5394 name
= (LPCTSTR
) IDI_QUESTION
;
5395 else if (EQ (icon
, intern ("exclamation")))
5396 name
= (LPCTSTR
) IDI_EXCLAMATION
;
5397 else if (EQ (icon
, intern ("asterisk")))
5398 name
= (LPCTSTR
) IDI_ASTERISK
;
5399 else if (EQ (icon
, intern ("winlogo")))
5400 name
= (LPCTSTR
) IDI_WINLOGO
;
5404 hicon
= LoadIcon (NULL
, name
);
5412 PostMessage (FRAME_W32_WINDOW (f
), WM_SETICON
, (WPARAM
) ICON_BIG
,
5417 #endif /* MAC_TODO */
5419 /************************************************************************
5421 ************************************************************************/
5423 /* Display Error Handling functions not used on W32. Listing them here
5424 helps diff stay in step when comparing w32term.c with xterm.c.
5426 x_error_catcher (display, error)
5427 x_catch_errors (dpy)
5428 x_catch_errors_unwind (old_val)
5429 x_check_errors (dpy, format)
5430 x_had_errors_p (dpy)
5431 x_clear_errors (dpy)
5432 x_uncatch_errors (dpy, count)
5434 x_connection_signal (signalnum)
5435 x_connection_closed (dpy, error_message)
5436 x_error_quitter (display, error)
5437 x_error_handler (display, error)
5438 x_io_error_quitter (display)
5443 /* Changing the font of the frame. */
5445 /* Give frame F the font named FONTNAME as its default font, and
5446 return the full name of that font. FONTNAME may be a wildcard
5447 pattern; in that case, we choose some font that fits the pattern.
5448 The return value shows which font we chose. */
5451 x_new_font (f
, fontname
)
5453 register char *fontname
;
5455 struct font_info
*fontp
5456 = FS_LOAD_FONT (f
, 0, fontname
, -1);
5461 FRAME_FONT (f
) = (XFontStruct
*) (fontp
->font
);
5462 FRAME_BASELINE_OFFSET (f
) = fontp
->baseline_offset
;
5463 FRAME_FONTSET (f
) = -1;
5465 FRAME_COLUMN_WIDTH (f
) = fontp
->average_width
;
5466 FRAME_SPACE_WIDTH (f
) = fontp
->space_width
;
5467 FRAME_LINE_HEIGHT (f
) = FONT_HEIGHT (FRAME_FONT (f
));
5469 compute_fringe_widths (f
, 1);
5471 /* Compute the scroll bar width in character columns. */
5472 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) > 0)
5474 int wid
= FRAME_COLUMN_WIDTH (f
);
5475 FRAME_CONFIG_SCROLL_BAR_COLS (f
)
5476 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f
) + wid
-1) / wid
;
5480 int wid
= FRAME_COLUMN_WIDTH (f
);
5481 FRAME_CONFIG_SCROLL_BAR_COLS (f
) = (14 + wid
- 1) / wid
;
5484 /* Now make the frame display the given font. */
5485 if (FRAME_MAC_WINDOW (f
) != 0)
5487 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->normal_gc
,
5489 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->reverse_gc
,
5491 XSetFont (FRAME_MAC_DISPLAY (f
), f
->output_data
.mac
->cursor_gc
,
5494 /* Don't change the size of a tip frame; there's no point in
5495 doing it because it's done in Fx_show_tip, and it leads to
5496 problems because the tip frame has no widget. */
5497 if (NILP (tip_frame
) || XFRAME (tip_frame
) != f
)
5498 x_set_window_size (f
, 0, FRAME_COLS (f
), FRAME_LINES (f
));
5501 return build_string (fontp
->full_name
);
5504 /* Give frame F the fontset named FONTSETNAME as its default font, and
5505 return the full name of that fontset. FONTSETNAME may be a wildcard
5506 pattern; in that case, we choose some fontset that fits the pattern.
5507 The return value shows which fontset we chose. */
5510 x_new_fontset (f
, fontsetname
)
5514 int fontset
= fs_query_fontset (build_string (fontsetname
), 0);
5520 if (FRAME_FONTSET (f
) == fontset
)
5521 /* This fontset is already set in frame F. There's nothing more
5523 return fontset_name (fontset
);
5525 result
= x_new_font (f
, (SDATA (fontset_ascii (fontset
))));
5527 if (!STRINGP (result
))
5528 /* Can't load ASCII font. */
5531 /* Since x_new_font doesn't update any fontset information, do it now. */
5532 FRAME_FONTSET (f
) = fontset
;
5534 return build_string (fontsetname
);
5538 /***********************************************************************
5539 TODO: W32 Input Methods
5540 ***********************************************************************/
5541 /* Listing missing functions from xterm.c helps diff stay in step.
5543 xim_destroy_callback (xim, client_data, call_data)
5544 xim_open_dpy (dpyinfo, resource_name)
5546 xim_instantiate_callback (display, client_data, call_data)
5547 xim_initialize (dpyinfo, resource_name)
5548 xim_close_dpy (dpyinfo)
5554 mac_get_window_bounds (f
, inner
, outer
)
5556 Rect
*inner
, *outer
;
5558 #if TARGET_API_MAC_CARBON
5559 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
5560 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
5561 #else /* not TARGET_API_MAC_CARBON */
5562 RgnHandle region
= NewRgn ();
5564 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
5565 *inner
= (*region
)->rgnBBox
;
5566 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
5567 *outer
= (*region
)->rgnBBox
;
5568 DisposeRgn (region
);
5569 #endif /* not TARGET_API_MAC_CARBON */
5574 /* Calculate the absolute position in frame F
5575 from its current recorded position values and gravity. */
5578 x_calc_absolute_position (f
)
5581 int width_diff
= 0, height_diff
= 0;
5582 int flags
= f
->size_hint_flags
;
5585 /* We have nothing to do if the current position
5586 is already for the top-left corner. */
5587 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5590 /* Find the offsets of the outside upper-left corner of
5591 the inner window, with respect to the outer window. */
5592 mac_get_window_bounds (f
, &inner
, &outer
);
5594 width_diff
= (outer
.right
- outer
.left
) - (inner
.right
- inner
.left
);
5595 height_diff
= (outer
.bottom
- outer
.top
) - (inner
.bottom
- inner
.top
);
5597 /* Treat negative positions as relative to the leftmost bottommost
5598 position that fits on the screen. */
5599 if (flags
& XNegative
)
5600 f
->left_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->width
5602 - FRAME_PIXEL_WIDTH (f
)
5605 if (flags
& YNegative
)
5606 f
->top_pos
= (FRAME_MAC_DISPLAY_INFO (f
)->height
5608 - FRAME_PIXEL_HEIGHT (f
)
5611 /* The left_pos and top_pos
5612 are now relative to the top and left screen edges,
5613 so the flags should correspond. */
5614 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5617 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5618 to really change the position, and 0 when calling from
5619 x_make_frame_visible (in that case, XOFF and YOFF are the current
5620 position values). It is -1 when calling from x_set_frame_parameters,
5621 which means, do adjust for borders but don't change the gravity. */
5624 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5626 register int xoff
, yoff
;
5629 if (change_gravity
> 0)
5633 f
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5635 f
->size_hint_flags
|= XNegative
;
5637 f
->size_hint_flags
|= YNegative
;
5638 f
->win_gravity
= NorthWestGravity
;
5640 x_calc_absolute_position (f
);
5643 x_wm_set_size_hint (f
, (long) 0, 0);
5645 #if TARGET_API_MAC_CARBON
5646 MoveWindowStructure (FRAME_MAC_WINDOW (f
), f
->left_pos
, f
->top_pos
);
5647 /* If the title bar is completely outside the screen, adjust the
5649 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
5650 kWindowConstrainMoveRegardlessOfFit
5651 | kWindowConstrainAllowPartial
, NULL
, NULL
);
5652 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5655 Rect inner
, outer
, screen_rect
, dummy
;
5656 RgnHandle region
= NewRgn ();
5658 mac_get_window_bounds (f
, &inner
, &outer
);
5659 f
->x_pixels_diff
= inner
.left
- outer
.left
;
5660 f
->y_pixels_diff
= inner
.top
- outer
.top
;
5661 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5662 f
->top_pos
+ f
->y_pixels_diff
, false);
5664 /* If the title bar is completely outside the screen, adjust the
5665 position. The variable `outer' holds the title bar rectangle.
5666 The variable `inner' holds slightly smaller one than `outer',
5667 so that the calculation of overlapping may not become too
5669 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
, region
);
5670 outer
= (*region
)->rgnBBox
;
5671 DisposeRgn (region
);
5673 InsetRect (&inner
, 8, 8);
5674 screen_rect
= qd
.screenBits
.bounds
;
5675 screen_rect
.top
+= GetMBarHeight ();
5677 if (!SectRect (&inner
, &screen_rect
, &dummy
))
5679 if (inner
.right
<= screen_rect
.left
)
5680 f
->left_pos
= screen_rect
.left
;
5681 else if (inner
.left
>= screen_rect
.right
)
5682 f
->left_pos
= screen_rect
.right
- (outer
.right
- outer
.left
);
5684 if (inner
.bottom
<= screen_rect
.top
)
5685 f
->top_pos
= screen_rect
.top
;
5686 else if (inner
.top
>= screen_rect
.bottom
)
5687 f
->top_pos
= screen_rect
.bottom
- (outer
.bottom
- outer
.top
);
5689 MoveWindow (FRAME_MAC_WINDOW (f
), f
->left_pos
+ f
->x_pixels_diff
,
5690 f
->top_pos
+ f
->y_pixels_diff
, false);
5698 /* Call this to change the size of frame F's x-window.
5699 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5700 for this size change and subsequent size changes.
5701 Otherwise we leave the window gravity unchanged. */
5704 x_set_window_size (f
, change_gravity
, cols
, rows
)
5709 int pixelwidth
, pixelheight
;
5713 check_frame_size (f
, &rows
, &cols
);
5714 f
->scroll_bar_actual_width
5715 = FRAME_SCROLL_BAR_COLS (f
) * FRAME_COLUMN_WIDTH (f
);
5717 compute_fringe_widths (f
, 0);
5719 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, cols
);
5720 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
5722 f
->win_gravity
= NorthWestGravity
;
5723 x_wm_set_size_hint (f
, (long) 0, 0);
5725 SizeWindow (FRAME_MAC_WINDOW (f
), pixelwidth
, pixelheight
, 0);
5726 #if TARGET_API_MAC_CARBON
5727 if (f
->output_data
.mac
->hourglass_control
)
5728 MoveControl (f
->output_data
.mac
->hourglass_control
,
5729 pixelwidth
- HOURGLASS_WIDTH
, 0);
5732 /* Now, strictly speaking, we can't be sure that this is accurate,
5733 but the window manager will get around to dealing with the size
5734 change request eventually, and we'll hear how it went when the
5735 ConfigureNotify event gets here.
5737 We could just not bother storing any of this information here,
5738 and let the ConfigureNotify event set everything up, but that
5739 might be kind of confusing to the Lisp code, since size changes
5740 wouldn't be reported in the frame parameters until some random
5741 point in the future when the ConfigureNotify event arrives.
5743 We pass 1 for DELAY since we can't run Lisp code inside of
5745 change_frame_size (f
, rows
, cols
, 0, 1, 0);
5746 FRAME_PIXEL_WIDTH (f
) = pixelwidth
;
5747 FRAME_PIXEL_HEIGHT (f
) = pixelheight
;
5749 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5750 receive in the ConfigureNotify event; if we get what we asked
5751 for, then the event won't cause the screen to become garbaged, so
5752 we have to make sure to do it here. */
5753 SET_FRAME_GARBAGED (f
);
5755 XFlush (FRAME_X_DISPLAY (f
));
5757 /* If cursor was outside the new size, mark it as off. */
5758 mark_window_cursors_off (XWINDOW (f
->root_window
));
5760 /* Clear out any recollection of where the mouse highlighting was,
5761 since it might be in a place that's outside the new frame size.
5762 Actually checking whether it is outside is a pain in the neck,
5763 so don't try--just let the highlighting be done afresh with new size. */
5764 cancel_mouse_face (f
);
5769 /* Mouse warping. */
5771 void x_set_mouse_pixel_position (struct frame
*f
, int pix_x
, int pix_y
);
5774 x_set_mouse_position (f
, x
, y
)
5780 pix_x
= FRAME_COL_TO_PIXEL_X (f
, x
) + FRAME_COLUMN_WIDTH (f
) / 2;
5781 pix_y
= FRAME_LINE_TO_PIXEL_Y (f
, y
) + FRAME_LINE_HEIGHT (f
) / 2;
5783 if (pix_x
< 0) pix_x
= 0;
5784 if (pix_x
> FRAME_PIXEL_WIDTH (f
)) pix_x
= FRAME_PIXEL_WIDTH (f
);
5786 if (pix_y
< 0) pix_y
= 0;
5787 if (pix_y
> FRAME_PIXEL_HEIGHT (f
)) pix_y
= FRAME_PIXEL_HEIGHT (f
);
5789 x_set_mouse_pixel_position (f
, pix_x
, pix_y
);
5793 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5797 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5800 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5801 0, 0, 0, 0, pix_x
, pix_y
);
5806 /* focus shifting, raising and lowering. */
5809 x_focus_on_frame (f
)
5812 #if 0 /* This proves to be unpleasant. */
5816 /* I don't think that the ICCCM allows programs to do things like this
5817 without the interaction of the window manager. Whatever you end up
5818 doing with this code, do it to x_unfocus_frame too. */
5819 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5820 RevertToPointerRoot
, CurrentTime
);
5830 /* Raise frame F. */
5836 if (f
->async_visible
)
5839 SelectWindow (FRAME_MAC_WINDOW (f
));
5844 /* Lower frame F. */
5850 if (f
->async_visible
)
5853 SendBehind (FRAME_MAC_WINDOW (f
), nil
);
5859 XTframe_raise_lower (f
, raise_flag
)
5869 /* Change of visibility. */
5872 mac_handle_visibility_change (f
)
5875 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
5876 int visible
= 0, iconified
= 0;
5877 struct input_event buf
;
5879 if (IsWindowVisible (wp
))
5880 if (IsWindowCollapsed (wp
))
5885 if (!f
->async_visible
&& visible
)
5889 /* wait_reading_process_output will notice this and update
5890 the frame's display structures. If we were made
5891 invisible, we should not set garbaged, because that stops
5892 redrawing on Update events. */
5893 SET_FRAME_GARBAGED (f
);
5896 buf
.kind
= DEICONIFY_EVENT
;
5897 XSETFRAME (buf
.frame_or_window
, f
);
5898 kbd_buffer_store_event (&buf
);
5900 else if (! NILP (Vframe_list
) && ! NILP (XCDR (Vframe_list
)))
5901 /* Force a redisplay sooner or later to update the
5902 frame titles in case this is the second frame. */
5903 record_asynch_buffer_change ();
5905 else if (f
->async_visible
&& !visible
)
5909 buf
.kind
= ICONIFY_EVENT
;
5910 XSETFRAME (buf
.frame_or_window
, f
);
5911 kbd_buffer_store_event (&buf
);
5914 f
->async_visible
= visible
;
5915 f
->async_iconified
= iconified
;
5918 /* This tries to wait until the frame is really visible.
5919 However, if the window manager asks the user where to position
5920 the frame, this will return before the user finishes doing that.
5921 The frame will not actually be visible at that time,
5922 but it will become visible later when the window manager
5923 finishes with it. */
5926 x_make_frame_visible (f
)
5930 int original_top
, original_left
;
5934 if (! FRAME_VISIBLE_P (f
))
5936 /* We test FRAME_GARBAGED_P here to make sure we don't
5937 call x_set_offset a second time
5938 if we get to x_make_frame_visible a second time
5939 before the window gets really visible. */
5940 if (! FRAME_ICONIFIED_P (f
)
5941 && ! f
->output_data
.mac
->asked_for_visible
)
5942 #if TARGET_API_MAC_CARBON
5943 if (!(FRAME_SIZE_HINTS (f
)->flags
& (USPosition
| PPosition
)))
5945 struct frame
*sf
= SELECTED_FRAME ();
5946 if (!FRAME_MAC_P (sf
))
5947 RepositionWindow (FRAME_MAC_WINDOW (f
), NULL
,
5948 kWindowCenterOnMainScreen
);
5950 RepositionWindow (FRAME_MAC_WINDOW (f
),
5951 FRAME_MAC_WINDOW (sf
),
5952 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
5953 kWindowCascadeStartAtParentWindowScreen
5955 kWindowCascadeOnParentWindowScreen
5958 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
5962 x_set_offset (f
, f
->left_pos
, f
->top_pos
, 0);
5964 f
->output_data
.mac
->asked_for_visible
= 1;
5966 SelectWindow (FRAME_MAC_WINDOW (f
));
5967 CollapseWindow (FRAME_MAC_WINDOW (f
), false);
5968 ShowWindow (FRAME_MAC_WINDOW (f
));
5971 XFlush (FRAME_MAC_DISPLAY (f
));
5973 /* Synchronize to ensure Emacs knows the frame is visible
5974 before we do anything else. We do this loop with input not blocked
5975 so that incoming events are handled. */
5980 /* This must come after we set COUNT. */
5983 XSETFRAME (frame
, f
);
5985 /* Wait until the frame is visible. Process X events until a
5986 MapNotify event has been seen, or until we think we won't get a
5987 MapNotify at all.. */
5988 for (count
= input_signal_count
+ 10;
5989 input_signal_count
< count
&& !FRAME_VISIBLE_P (f
);)
5991 /* Force processing of queued events. */
5994 /* Machines that do polling rather than SIGIO have been
5995 observed to go into a busy-wait here. So we'll fake an
5996 alarm signal to let the handler know that there's something
5997 to be read. We used to raise a real alarm, but it seems
5998 that the handler isn't always enabled here. This is
6000 if (input_polling_used ())
6002 /* It could be confusing if a real alarm arrives while
6003 processing the fake one. Turn it off and let the
6004 handler reset it. */
6005 extern void poll_for_input_1
P_ ((void));
6006 int old_poll_suppress_count
= poll_suppress_count
;
6007 poll_suppress_count
= 1;
6008 poll_for_input_1 ();
6009 poll_suppress_count
= old_poll_suppress_count
;
6012 /* See if a MapNotify event has been processed. */
6013 FRAME_SAMPLE_VISIBILITY (f
);
6018 /* Change from mapped state to withdrawn state. */
6020 /* Make the frame visible (mapped and not iconified). */
6023 x_make_frame_invisible (f
)
6026 /* A deactivate event does not occur when the last visible frame is
6027 made invisible. So if we clear the highlight here, it will not
6028 be rehighlighted when it is made visible. */
6030 /* Don't keep the highlight on an invisible frame. */
6031 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6032 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6037 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
6038 that the current position of the window is user-specified, rather than
6039 program-specified, so that when the window is mapped again, it will be
6040 placed at the same location, without forcing the user to position it
6041 by hand again (they have already done that once for this window.) */
6042 x_wm_set_size_hint (f
, (long) 0, 1);
6044 HideWindow (FRAME_MAC_WINDOW (f
));
6048 #if !USE_CARBON_EVENTS
6049 mac_handle_visibility_change (f
);
6053 /* Change window state from mapped to iconified. */
6061 /* A deactivate event does not occur when the last visible frame is
6062 iconified. So if we clear the highlight here, it will not be
6063 rehighlighted when it is deiconified. */
6065 /* Don't keep the highlight on an invisible frame. */
6066 if (FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6067 FRAME_MAC_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6070 if (f
->async_iconified
)
6075 FRAME_SAMPLE_VISIBILITY (f
);
6077 if (! FRAME_VISIBLE_P (f
))
6078 ShowWindow (FRAME_MAC_WINDOW (f
));
6080 err
= CollapseWindow (FRAME_MAC_WINDOW (f
), true);
6085 error ("Can't notify window manager of iconification");
6087 #if !USE_CARBON_EVENTS
6088 mac_handle_visibility_change (f
);
6093 /* Free X resources of frame F. */
6096 x_free_frame_resources (f
)
6099 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6100 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
6104 if (wp
!= tip_window
)
6105 remove_window_handler (wp
);
6108 if (wp
== tip_window
)
6109 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
6110 closed' event. So we reset tip_window here. */
6113 free_frame_menubar (f
);
6115 if (FRAME_FACE_CACHE (f
))
6116 free_frame_faces (f
);
6120 if (FRAME_SIZE_HINTS (f
))
6121 xfree (FRAME_SIZE_HINTS (f
));
6123 xfree (f
->output_data
.mac
);
6124 f
->output_data
.mac
= NULL
;
6126 if (f
== dpyinfo
->x_focus_frame
)
6127 dpyinfo
->x_focus_frame
= 0;
6128 if (f
== dpyinfo
->x_focus_event_frame
)
6129 dpyinfo
->x_focus_event_frame
= 0;
6130 if (f
== dpyinfo
->x_highlight_frame
)
6131 dpyinfo
->x_highlight_frame
= 0;
6133 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6135 dpyinfo
->mouse_face_beg_row
6136 = dpyinfo
->mouse_face_beg_col
= -1;
6137 dpyinfo
->mouse_face_end_row
6138 = dpyinfo
->mouse_face_end_col
= -1;
6139 dpyinfo
->mouse_face_window
= Qnil
;
6140 dpyinfo
->mouse_face_deferred_gc
= 0;
6141 dpyinfo
->mouse_face_mouse_frame
= 0;
6148 /* Destroy the X window of frame F. */
6151 x_destroy_window (f
)
6154 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
6156 x_free_frame_resources (f
);
6158 dpyinfo
->reference_count
--;
6162 /* Setting window manager hints. */
6164 /* Set the normal size hints for the window manager, for frame F.
6165 FLAGS is the flags word to use--or 0 meaning preserve the flags
6166 that the window now has.
6167 If USER_POSITION is nonzero, we set the USPosition
6168 flag (this is useful when FLAGS is 0). */
6170 x_wm_set_size_hint (f
, flags
, user_position
)
6175 int base_width
, base_height
, width_inc
, height_inc
;
6176 int min_rows
= 0, min_cols
= 0;
6177 XSizeHints
*size_hints
;
6179 base_width
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, 0);
6180 base_height
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, 0);
6181 width_inc
= FRAME_COLUMN_WIDTH (f
);
6182 height_inc
= FRAME_LINE_HEIGHT (f
);
6184 check_frame_size (f
, &min_rows
, &min_cols
);
6186 size_hints
= FRAME_SIZE_HINTS (f
);
6187 if (size_hints
== NULL
)
6189 size_hints
= FRAME_SIZE_HINTS (f
) = xmalloc (sizeof (XSizeHints
));
6190 bzero (size_hints
, sizeof (XSizeHints
));
6193 size_hints
->flags
|= PResizeInc
| PMinSize
| PBaseSize
;
6194 size_hints
->width_inc
= width_inc
;
6195 size_hints
->height_inc
= height_inc
;
6196 size_hints
->min_width
= base_width
+ min_cols
* width_inc
;
6197 size_hints
->min_height
= base_height
+ min_rows
* height_inc
;
6198 size_hints
->base_width
= base_width
;
6199 size_hints
->base_height
= base_height
;
6202 size_hints
->flags
= flags
;
6203 else if (user_position
)
6205 size_hints
->flags
&= ~ PPosition
;
6206 size_hints
->flags
|= USPosition
;
6210 #if 0 /* MAC_TODO: hide application instead of iconify? */
6211 /* Used for IconicState or NormalState */
6214 x_wm_set_window_state (f
, state
)
6218 #ifdef USE_X_TOOLKIT
6221 XtSetArg (al
[0], XtNinitialState
, state
);
6222 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6223 #else /* not USE_X_TOOLKIT */
6224 Window window
= FRAME_X_WINDOW (f
);
6226 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6227 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6229 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6230 #endif /* not USE_X_TOOLKIT */
6234 x_wm_set_icon_pixmap (f
, pixmap_id
)
6240 #ifndef USE_X_TOOLKIT
6241 Window window
= FRAME_X_WINDOW (f
);
6246 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6247 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6251 /* It seems there is no way to turn off use of an icon pixmap.
6252 The following line does it, only if no icon has yet been created,
6253 for some window managers. But with mwm it crashes.
6254 Some people say it should clear the IconPixmapHint bit in this case,
6255 but that doesn't work, and the X consortium said it isn't the
6256 right thing at all. Since there is no way to win,
6257 best to explicitly give up. */
6259 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6265 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6269 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6270 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6273 #else /* not USE_X_TOOLKIT */
6275 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6276 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6278 #endif /* not USE_X_TOOLKIT */
6281 #endif /* MAC_TODO */
6284 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6288 #if 0 /* MAC_TODO: no icons on Mac */
6289 #ifdef USE_X_TOOLKIT
6290 Window window
= XtWindow (f
->output_data
.x
->widget
);
6292 Window window
= FRAME_X_WINDOW (f
);
6295 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6296 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6297 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6299 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6300 #endif /* MAC_TODO */
6304 /***********************************************************************
6306 ***********************************************************************/
6308 /* An XLFD pattern is divided into blocks delimited by '*'. This
6309 structure holds information for each block. */
6310 struct xlfdpat_block
6312 /* Length of the pattern string in this block. Non-zero except for
6313 the first and the last blocks. */
6316 /* Pattern string except the last character in this block. The last
6317 character is replaced with NUL in order to use it as a
6319 unsigned char *pattern
;
6321 /* Last character of the pattern string. Must not be '?'. */
6322 unsigned char last_char
;
6324 /* One of the tables for the Boyer-Moore string search. It
6325 specifies the number of positions to proceed for each character
6326 with which the match fails. */
6329 /* The skip value for the last character in the above `skip' is
6330 assigned to `infinity' in order to simplify a loop condition.
6331 The original value is saved here. */
6337 /* Normalized pattern string. "Normalized" means that capital
6338 letters are lowered, blocks are not empty except the first and
6339 the last ones, and trailing '?'s in a block that is not the last
6340 one are moved to the next one. The last character in each block
6341 is replaced with NUL. */
6344 /* Number of characters except '*'s and trailing '?'s in the
6345 normalized pattern string. */
6348 /* Number of trailing '?'s in the normalized pattern string. */
6349 int trailing_anychars
;
6351 /* Number of blocks and information for each block. The latter is
6352 NULL if the pattern is exact (no '*' or '?' in it). */
6354 struct xlfdpat_block
*blocks
;
6358 xlfdpat_destroy (pat
)
6359 struct xlfdpat
*pat
;
6366 xfree (pat
->blocks
);
6373 static struct xlfdpat
*
6374 xlfdpat_create (pattern
)
6377 struct xlfdpat
*pat
;
6378 int nblocks
, i
, skip
;
6379 unsigned char last_char
, *p
, *q
, *anychar_head
;
6380 struct xlfdpat_block
*blk
;
6382 pat
= xmalloc (sizeof (struct xlfdpat
));
6386 pat
->buf
= xmalloc (strlen (pattern
) + 1);
6387 if (pat
->buf
== NULL
)
6390 /* Normalize the pattern string and store it to `pat->buf'. */
6392 anychar_head
= NULL
;
6395 for (p
= pattern
; *p
; p
++)
6397 unsigned char c
= *p
;
6400 if (last_char
== '*')
6401 /* ...a** -> ...a* */
6405 if (last_char
== '?')
6406 if (anychar_head
> pat
->buf
&& *(anychar_head
- 1) == '*')
6407 /* ...*??* -> ...*?? */
6410 /* ...a??* -> ...a*?? */
6412 *anychar_head
++ = '*';
6419 if (last_char
!= '?')
6423 /* On Mac OS X 10.3, tolower also converts non-ASCII
6424 characters for some locales. */
6428 *q
++ = last_char
= c
;
6432 pat
->nblocks
= nblocks
;
6433 if (last_char
!= '?')
6434 pat
->trailing_anychars
= 0;
6437 pat
->trailing_anychars
= q
- anychar_head
;
6440 pat
->nchars
= q
- pat
->buf
- (nblocks
- 1);
6442 if (anychar_head
== NULL
&& nblocks
== 1)
6444 /* The pattern is exact. */
6449 pat
->blocks
= xmalloc (sizeof (struct xlfdpat_block
) * nblocks
);
6450 if (pat
->blocks
== NULL
)
6453 /* Divide the normalized pattern into blocks. */
6455 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
- 1; blk
++)
6460 blk
->len
= p
- blk
->pattern
;
6464 blk
->len
= q
- blk
->pattern
;
6466 /* Setup a table for the Boyer-Moore string search. */
6467 for (blk
= pat
->blocks
; blk
< pat
->blocks
+ nblocks
; blk
++)
6470 blk
->last_char
= blk
->pattern
[blk
->len
- 1];
6471 blk
->pattern
[blk
->len
- 1] = '\0';
6473 for (skip
= 1; skip
< blk
->len
; skip
++)
6474 if (blk
->pattern
[blk
->len
- skip
- 1] == '?')
6477 for (i
= 0; i
< 256; i
++)
6478 blk
->skip
[i
] = skip
;
6480 p
= blk
->pattern
+ (blk
->len
- skip
);
6482 blk
->skip
[*p
++] = skip
;
6484 blk
->last_char_skip
= blk
->skip
[blk
->last_char
];
6490 xlfdpat_destroy (pat
);
6495 xlfdpat_exact_p (pat
)
6496 struct xlfdpat
*pat
;
6498 return pat
->blocks
== NULL
;
6501 /* Return the first string in STRING + 0, ..., STRING + START_MAX such
6502 that the pattern in *BLK matches with its prefix. Return NULL
6503 there is no such strings. STRING must be lowered in advance. */
6506 xlfdpat_block_match_1 (blk
, string
, start_max
)
6507 struct xlfdpat_block
*blk
;
6508 unsigned char *string
;
6511 int start
, infinity
;
6512 unsigned char *p
, *s
;
6514 xassert (blk
->len
> 0);
6515 xassert (start_max
+ blk
->len
<= strlen (string
));
6516 xassert (blk
->last_char
!= '?');
6518 /* See the comments in the function `boyer_moore' (search.c) for the
6519 use of `infinity'. */
6520 infinity
= start_max
+ blk
->len
+ 1;
6521 blk
->skip
[blk
->last_char
] = infinity
;
6526 /* Check the last character of the pattern. */
6527 s
= string
+ blk
->len
- 1;
6530 start
+= blk
->skip
[*(s
+ start
)];
6532 while (start
<= start_max
);
6534 if (start
< infinity
)
6535 /* Couldn't find the last character. */
6538 /* No less than `infinity' means we could find the last
6539 character at `s[start - infinity]'. */
6542 /* Check the remaining characters. We prefer making no-'?'
6543 cases faster because the use of '?' is really rare. */
6548 while (*p
++ == *s
++)
6551 while (*(p
- 1) == '?');
6553 if (*(p
- 1) == '\0')
6555 return string
+ start
;
6558 start
+= blk
->last_char_skip
;
6560 while (start
<= start_max
);
6565 #define xlfdpat_block_match(b, s, m) \
6566 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \
6567 : xlfdpat_block_match_1 (b, s, m))
6569 /* Check if XLFD pattern PAT, which is generated by `xfldpat_create',
6570 matches with STRING. STRING must be lowered in advance. */
6573 xlfdpat_match (pat
, string
)
6574 struct xlfdpat
*pat
;
6575 unsigned char *string
;
6577 int str_len
, nblocks
, i
, start_max
;
6578 struct xlfdpat_block
*blk
;
6581 xassert (pat
->nblocks
> 0);
6583 if (xlfdpat_exact_p (pat
))
6584 return strcmp (pat
->buf
, string
) == 0;
6586 /* The number of the characters in the string must not be smaller
6587 than that in the pattern. */
6588 str_len
= strlen (string
);
6589 if (str_len
< pat
->nchars
+ pat
->trailing_anychars
)
6592 /* Chop off the trailing '?'s. */
6593 str_len
-= pat
->trailing_anychars
;
6595 /* The last block. When it is non-empty, it must match at the end
6597 nblocks
= pat
->nblocks
;
6598 blk
= pat
->blocks
+ (nblocks
- 1);
6600 /* The last block is also the first one. */
6601 return (str_len
== blk
->len
6602 && (blk
->len
== 0 || xlfdpat_block_match (blk
, string
, 0)));
6603 else if (blk
->len
!= 0)
6604 if (!xlfdpat_block_match (blk
, string
+ (str_len
- blk
->len
), 0))
6607 /* The first block. When it is non-empty, it must match at the
6608 beginning of the string. */
6612 s
= xlfdpat_block_match (blk
, string
, 0);
6615 string
= s
+ blk
->len
;
6618 /* The rest of the blocks. */
6619 start_max
= str_len
- pat
->nchars
;
6620 for (i
= 1, blk
++; i
< nblocks
- 1; i
++, blk
++)
6622 s
= xlfdpat_block_match (blk
, string
, start_max
);
6625 start_max
-= s
- string
;
6626 string
= s
+ blk
->len
;
6633 /***********************************************************************
6635 ***********************************************************************/
6637 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6640 x_get_font_info (f
, font_idx
)
6644 return (FRAME_MAC_FONT_TABLE (f
) + font_idx
);
6647 /* the global font name table */
6648 static char **font_name_table
= NULL
;
6649 static int font_name_table_size
= 0;
6650 static int font_name_count
= 0;
6652 /* Alist linking font family names to Font Manager font family
6653 references (which can also be used as QuickDraw font IDs). We use
6654 an alist because hash tables are not ready when the terminal frame
6655 for Mac OS Classic is created. */
6656 static Lisp_Object fm_font_family_alist
;
6658 /* Hash table linking font family names to ATSU font IDs. */
6659 static Lisp_Object atsu_font_id_hash
;
6662 /* Alist linking character set strings to Mac text encoding and Emacs
6664 static Lisp_Object Vmac_charset_info_alist
;
6667 create_text_encoding_info_alist ()
6669 Lisp_Object result
= Qnil
, rest
;
6671 for (rest
= Vmac_charset_info_alist
; CONSP (rest
); rest
= XCDR (rest
))
6673 Lisp_Object charset_info
= XCAR (rest
);
6674 Lisp_Object charset
, coding_system
, text_encoding
;
6675 Lisp_Object existing_info
;
6677 if (!(CONSP (charset_info
)
6678 && STRINGP (charset
= XCAR (charset_info
))
6679 && CONSP (XCDR (charset_info
))
6680 && INTEGERP (text_encoding
= XCAR (XCDR (charset_info
)))
6681 && CONSP (XCDR (XCDR (charset_info
)))
6682 && SYMBOLP (coding_system
= XCAR (XCDR (XCDR (charset_info
))))))
6685 existing_info
= assq_no_quit (text_encoding
, result
);
6686 if (NILP (existing_info
))
6687 result
= Fcons (list3 (text_encoding
, coding_system
, charset
),
6690 if (NILP (Fmember (charset
, XCDR (XCDR (existing_info
)))))
6691 XSETCDR (XCDR (existing_info
),
6692 Fcons (charset
, XCDR (XCDR (existing_info
))));
6700 decode_mac_font_name (name
, size
, coding_system
)
6703 Lisp_Object coding_system
;
6705 struct coding_system coding
;
6708 if (!NILP (coding_system
) && !NILP (Fcoding_system_p (coding_system
)))
6710 for (p
= name
; *p
; p
++)
6711 if (!isascii (*p
) || iscntrl (*p
))
6716 setup_coding_system (coding_system
, &coding
);
6717 coding
.src_multibyte
= 0;
6718 coding
.dst_multibyte
= 1;
6719 coding
.mode
|= CODING_MODE_LAST_BLOCK
;
6720 coding
.composing
= COMPOSITION_DISABLED
;
6721 buf
= (char *) alloca (size
);
6723 decode_coding (&coding
, name
, buf
, strlen (name
), size
- 1);
6724 bcopy (buf
, name
, coding
.produced
);
6725 name
[coding
.produced
] = '\0';
6729 /* If there's just one occurrence of '-' in the family name, it is
6730 replaced with '_'. (More than one occurrence of '-' means a
6731 "FOUNDRY-FAMILY-CHARSET"-style name.) */
6732 p
= strchr (name
, '-');
6733 if (p
&& strchr (p
+ 1, '-') == NULL
)
6736 for (p
= name
; *p
; p
++)
6737 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6738 for some locales. */
6745 mac_to_x_fontname (name
, size
, style
, charset
)
6753 char xf
[256], *result
;
6756 if (sscanf (name
, "%31[^-]-%255[^-]-%31s", foundry
, family
, cs
) == 3)
6760 strcpy(foundry
, "Apple");
6761 strcpy(family
, name
);
6764 sprintf (xf
, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s",
6765 style
& bold
? "bold" : "medium", style
& italic
? 'i' : 'r',
6766 size
, size
* 10, size
? 72 : 0, size
? 72 : 0, size
* 10, charset
);
6768 result
= xmalloc (strlen (foundry
) + strlen (family
) + strlen (xf
) + 3 + 1);
6769 sprintf (result
, "-%s-%s-%s", foundry
, family
, xf
);
6770 for (p
= result
; *p
; p
++)
6771 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6772 for some locales. */
6779 /* Parse fully-specified and instantiated X11 font spec XF, and store
6780 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the
6781 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the
6782 caller must allocate at least 256 and 32 bytes respectively. For
6783 ordinary Mac fonts, the value stored to FAMILY should just be their
6784 names, like "monaco", "Taipei", etc. Fonts converted from the GNU
6785 intlfonts collection contain their charset designation in their
6786 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both
6787 types of font names are handled accordingly. */
6789 const int kDefaultFontSize
= 12;
6792 parse_x_font_name (xf
, family
, size
, style
, charset
)
6798 Str31 foundry
, weight
;
6799 int point_size
, avgwidth
;
6802 if (sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6803 foundry
, family
, weight
, slant
, size
,
6804 &point_size
, &avgwidth
, charset
) != 8
6805 && sscanf (xf
, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s",
6806 foundry
, family
, weight
, slant
, size
,
6807 &point_size
, &avgwidth
, charset
) != 8)
6813 *size
= point_size
/ 10;
6814 else if (avgwidth
> 0)
6815 *size
= avgwidth
/ 10;
6818 *size
= kDefaultFontSize
;
6821 if (strcmp (weight
, "bold") == 0)
6826 if (NILP (Fassoc (build_string (charset
), Vmac_charset_info_alist
)))
6828 int foundry_len
= strlen (foundry
), family_len
= strlen (family
);
6830 if (foundry_len
+ family_len
+ strlen (charset
) + 2 < sizeof (Str255
))
6832 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset),
6833 but take overlap into account. */
6834 memmove (family
+ foundry_len
+ 1, family
, family_len
);
6835 memcpy (family
, foundry
, foundry_len
);
6836 family
[foundry_len
] = '-';
6837 family
[foundry_len
+ 1 + family_len
] = '-';
6838 strcpy (family
+ foundry_len
+ 1 + family_len
+ 1, charset
);
6844 for (p
= family
; *p
; p
++)
6845 /* On Mac OS X 10.3, tolower also converts non-ASCII characters
6846 for some locales. */
6855 add_font_name_table_entry (char *font_name
)
6857 if (font_name_table_size
== 0)
6859 font_name_table_size
= 256;
6860 font_name_table
= (char **)
6861 xmalloc (font_name_table_size
* sizeof (char *));
6863 else if (font_name_count
+ 1 >= font_name_table_size
)
6865 font_name_table_size
*= 2;
6866 font_name_table
= (char **)
6867 xrealloc (font_name_table
,
6868 font_name_table_size
* sizeof (char *));
6871 font_name_table
[font_name_count
++] = font_name
;
6874 /* Sets up the table font_name_table to contain the list of all fonts
6875 in the system the first time the table is used so that the Resource
6876 Manager need not be accessed every time this information is
6880 init_font_name_table ()
6882 #if TARGET_API_MAC_CARBON
6883 FMFontFamilyIterator ffi
;
6884 FMFontFamilyInstanceIterator ffii
;
6886 Lisp_Object text_encoding_info_alist
;
6887 struct gcpro gcpro1
;
6889 text_encoding_info_alist
= create_text_encoding_info_alist ();
6892 #if USE_CG_TEXT_DRAWING
6893 init_cg_text_anti_aliasing_threshold ();
6895 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode
),
6896 text_encoding_info_alist
)))
6899 ItemCount nfonts
, i
;
6900 ATSUFontID
*font_ids
= NULL
;
6901 Ptr name
, prev_name
= NULL
;
6905 make_hash_table (Qequal
, make_number (DEFAULT_HASH_SIZE
),
6906 make_float (DEFAULT_REHASH_SIZE
),
6907 make_float (DEFAULT_REHASH_THRESHOLD
),
6909 err
= ATSUFontCount (&nfonts
);
6911 font_ids
= xmalloc (sizeof (ATSUFontID
) * nfonts
);
6913 err
= ATSUGetFontIDs (font_ids
, nfonts
, NULL
);
6915 for (i
= 0; i
< nfonts
; i
++)
6917 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6918 kFontMacintoshPlatform
, kFontNoScript
,
6919 kFontNoLanguage
, 0, NULL
, &name_len
, NULL
);
6922 name
= xmalloc (name_len
+ 1);
6925 name
[name_len
] = '\0';
6926 err
= ATSUFindFontName (font_ids
[i
], kFontFamilyName
,
6927 kFontMacintoshPlatform
, kFontNoScript
,
6928 kFontNoLanguage
, name_len
, name
,
6931 decode_mac_font_name (name
, name_len
+ 1, Qnil
);
6934 && (prev_name
== NULL
6935 || strcmp (name
, prev_name
) != 0))
6937 static char *cs
= "iso10646-1";
6939 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6941 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6943 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6945 add_font_name_table_entry (mac_to_x_fontname (name
, 0,
6946 italic
| bold
, cs
));
6947 Fputhash (make_unibyte_string (name
, name_len
),
6948 long_to_cons (font_ids
[i
]), atsu_font_id_hash
);
6962 /* Create a dummy instance iterator here to avoid creating and
6963 destroying it in the loop. */
6964 if (FMCreateFontFamilyInstanceIterator (0, &ffii
) != noErr
)
6966 /* Create an iterator to enumerate the font families. */
6967 if (FMCreateFontFamilyIterator (NULL
, NULL
, kFMDefaultOptions
, &ffi
)
6970 FMDisposeFontFamilyInstanceIterator (&ffii
);
6974 GCPRO1 (text_encoding_info_alist
);
6976 while (FMGetNextFontFamily (&ffi
, &ff
) == noErr
)
6982 TextEncoding encoding
;
6983 TextEncodingBase sc
;
6984 Lisp_Object text_encoding_info
;
6986 if (FMGetFontFamilyName (ff
, name
) != noErr
)
6992 if (FMGetFontFamilyTextEncoding (ff
, &encoding
) != noErr
)
6994 sc
= GetTextEncodingBase (encoding
);
6995 text_encoding_info
= assq_no_quit (make_number (sc
),
6996 text_encoding_info_alist
);
6997 if (NILP (text_encoding_info
))
6998 text_encoding_info
= assq_no_quit (make_number (kTextEncodingMacRoman
),
6999 text_encoding_info_alist
);
7000 decode_mac_font_name (name
, sizeof (name
),
7001 XCAR (XCDR (text_encoding_info
)));
7002 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7004 fm_font_family_alist
);
7006 /* Point the instance iterator at the current font family. */
7007 if (FMResetFontFamilyInstanceIterator (ff
, &ffii
) != noErr
)
7010 while (FMGetNextFontFamilyInstance (&ffii
, &font
, &style
, &size
)
7013 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7015 if (size
> 0 || style
== normal
)
7016 for (; !NILP (rest
); rest
= XCDR (rest
))
7018 char *cs
= SDATA (XCAR (rest
));
7022 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7024 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7026 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7028 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7034 add_font_name_table_entry (mac_to_x_fontname (name
, size
,
7043 /* Dispose of the iterators. */
7044 FMDisposeFontFamilyIterator (&ffi
);
7045 FMDisposeFontFamilyInstanceIterator (&ffii
);
7046 #else /* !TARGET_API_MAC_CARBON */
7048 SInt16 fontnum
, old_fontnum
;
7049 int num_mac_fonts
= CountResources('FOND');
7051 Handle font_handle
, font_handle_2
;
7052 short id
, scriptcode
;
7055 struct FontAssoc
*fat
;
7056 struct AsscEntry
*assc_entry
;
7057 Lisp_Object text_encoding_info_alist
, text_encoding_info
;
7058 struct gcpro gcpro1
;
7060 GetPort (&port
); /* save the current font number used */
7061 old_fontnum
= port
->txFont
;
7063 text_encoding_info_alist
= create_text_encoding_info_alist ();
7065 GCPRO1 (text_encoding_info_alist
);
7067 for (i
= 1; i
<= num_mac_fonts
; i
++) /* get all available fonts */
7069 font_handle
= GetIndResource ('FOND', i
);
7073 GetResInfo (font_handle
, &id
, &type
, name
);
7074 GetFNum (name
, &fontnum
);
7080 scriptcode
= FontToScript (fontnum
);
7081 text_encoding_info
= assq_no_quit (make_number (scriptcode
),
7082 text_encoding_info_alist
);
7083 if (NILP (text_encoding_info
))
7084 text_encoding_info
= assq_no_quit (make_number (smRoman
),
7085 text_encoding_info_alist
);
7086 decode_mac_font_name (name
, sizeof (name
),
7087 XCAR (XCDR (text_encoding_info
)));
7088 fm_font_family_alist
= Fcons (Fcons (build_string (name
),
7089 make_number (fontnum
)),
7090 fm_font_family_alist
);
7093 HLock (font_handle
);
7095 if (GetResourceSizeOnDisk (font_handle
)
7096 >= sizeof (struct FamRec
))
7098 fat
= (struct FontAssoc
*) (*font_handle
7099 + sizeof (struct FamRec
));
7101 = (struct AsscEntry
*) (*font_handle
7102 + sizeof (struct FamRec
)
7103 + sizeof (struct FontAssoc
));
7105 for (j
= 0; j
<= fat
->numAssoc
; j
++, assc_entry
++)
7107 Lisp_Object rest
= XCDR (XCDR (text_encoding_info
));
7109 for (; !NILP (rest
); rest
= XCDR (rest
))
7111 char *cs
= SDATA (XCAR (rest
));
7113 add_font_name_table_entry (mac_to_x_fontname (name
,
7114 assc_entry
->fontSize
,
7115 assc_entry
->fontStyle
,
7121 HUnlock (font_handle
);
7122 font_handle_2
= GetNextFOND (font_handle
);
7123 ReleaseResource (font_handle
);
7124 font_handle
= font_handle_2
;
7126 while (ResError () == noErr
&& font_handle
);
7131 TextFont (old_fontnum
);
7132 #endif /* !TARGET_API_MAC_CARBON */
7137 mac_clear_font_name_table ()
7141 for (i
= 0; i
< font_name_count
; i
++)
7142 xfree (font_name_table
[i
]);
7143 xfree (font_name_table
);
7144 font_name_table
= NULL
;
7145 font_name_table_size
= font_name_count
= 0;
7146 fm_font_family_alist
= Qnil
;
7150 enum xlfd_scalable_field_index
7152 XLFD_SCL_PIXEL_SIZE
,
7153 XLFD_SCL_POINT_SIZE
,
7158 static int xlfd_scalable_fields
[] =
7167 mac_do_list_fonts (pattern
, maxnames
)
7172 Lisp_Object font_list
= Qnil
;
7173 struct xlfdpat
*pat
;
7175 int scl_val
[XLFD_SCL_LAST
], *field
, *val
;
7178 if (font_name_table
== NULL
) /* Initialize when first used. */
7179 init_font_name_table ();
7181 for (i
= 0; i
< XLFD_SCL_LAST
; i
++)
7184 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
7185 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
7186 fonts are scaled according to the specified size. */
7189 field
= xlfd_scalable_fields
;
7197 if ('0' <= *ptr
&& *ptr
<= '9')
7199 *val
= *ptr
++ - '0';
7200 while ('0' <= *ptr
&& *ptr
<= '9' && *val
< 10000)
7201 *val
= *val
* 10 + *ptr
++ - '0';
7208 ptr
= strchr (ptr
, '-');
7211 while (ptr
&& i
< 14);
7213 if (i
== 14 && ptr
== NULL
)
7215 if (scl_val
[XLFD_SCL_PIXEL_SIZE
] < 0)
7216 scl_val
[XLFD_SCL_PIXEL_SIZE
] =
7217 (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
] / 10
7218 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
] / 10
7220 if (scl_val
[XLFD_SCL_POINT_SIZE
] < 0)
7221 scl_val
[XLFD_SCL_POINT_SIZE
] =
7222 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7223 : (scl_val
[XLFD_SCL_AVGWIDTH
] > 0 ? scl_val
[XLFD_SCL_AVGWIDTH
]
7225 if (scl_val
[XLFD_SCL_AVGWIDTH
] < 0)
7226 scl_val
[XLFD_SCL_AVGWIDTH
] =
7227 (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0 ? scl_val
[XLFD_SCL_PIXEL_SIZE
] * 10
7228 : (scl_val
[XLFD_SCL_POINT_SIZE
] > 0 ? scl_val
[XLFD_SCL_POINT_SIZE
]
7232 scl_val
[XLFD_SCL_PIXEL_SIZE
] = -1;
7234 pat
= xlfdpat_create (pattern
);
7238 exact
= xlfdpat_exact_p (pat
);
7240 for (i
= 0; i
< font_name_count
; i
++)
7242 if (xlfdpat_match (pat
, font_name_table
[i
]))
7244 font_list
= Fcons (build_string (font_name_table
[i
]), font_list
);
7245 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7248 else if (scl_val
[XLFD_SCL_PIXEL_SIZE
] > 0
7249 && (ptr
= strstr (font_name_table
[i
], "-0-0-0-0-m-0-")))
7251 int former_len
= ptr
- font_name_table
[i
];
7253 scaled
= xmalloc (strlen (font_name_table
[i
]) + 20 + 1);
7256 memcpy (scaled
, font_name_table
[i
], former_len
);
7257 sprintf (scaled
+ former_len
,
7258 "-%d-%d-72-72-m-%d-%s",
7259 scl_val
[XLFD_SCL_PIXEL_SIZE
],
7260 scl_val
[XLFD_SCL_POINT_SIZE
],
7261 scl_val
[XLFD_SCL_AVGWIDTH
],
7262 ptr
+ sizeof ("-0-0-0-0-m-0-") - 1);
7264 if (xlfdpat_match (pat
, scaled
))
7266 font_list
= Fcons (build_string (scaled
), font_list
);
7268 if (exact
|| maxnames
> 0 && ++n_fonts
>= maxnames
)
7276 xlfdpat_destroy (pat
);
7281 /* Return a list of names of available fonts matching PATTERN on frame F.
7283 Frame F null means we have not yet created any frame on Mac, and
7284 consult the first display in x_display_list. MAXNAMES sets a limit
7285 on how many fonts to match. */
7288 x_list_fonts (f
, pattern
, size
, maxnames
)
7290 Lisp_Object pattern
;
7293 Lisp_Object list
= Qnil
, patterns
, tem
, key
;
7294 struct mac_display_info
*dpyinfo
7295 = f
? FRAME_MAC_DISPLAY_INFO (f
) : x_display_list
;
7297 xassert (size
<= 0);
7299 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
7300 if (NILP (patterns
))
7301 patterns
= Fcons (pattern
, Qnil
);
7303 for (; CONSP (patterns
); patterns
= XCDR (patterns
))
7305 pattern
= XCAR (patterns
);
7307 if (!STRINGP (pattern
))
7310 tem
= XCAR (XCDR (dpyinfo
->name_list_element
));
7311 key
= Fcons (pattern
, make_number (maxnames
));
7313 list
= Fassoc (key
, tem
);
7316 list
= Fcdr_safe (list
);
7317 /* We have a cashed list. Don't have to get the list again. */
7322 list
= mac_do_list_fonts (SDATA (pattern
), maxnames
);
7325 /* MAC_TODO: add code for matching outline fonts here */
7327 /* Now store the result in the cache. */
7328 XSETCAR (XCDR (dpyinfo
->name_list_element
),
7329 Fcons (Fcons (key
, list
),
7330 XCAR (XCDR (dpyinfo
->name_list_element
))));
7333 if (NILP (list
)) continue; /* Try the remaining alternatives. */
7342 /* Check that FONT is valid on frame F. It is if it can be found in F's
7346 x_check_font (f
, font
)
7351 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
7353 xassert (font
!= NULL
);
7355 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7356 if (dpyinfo
->font_table
[i
].name
7357 && font
== dpyinfo
->font_table
[i
].font
)
7360 xassert (i
< dpyinfo
->n_fonts
);
7363 #endif /* GLYPH_DEBUG != 0 */
7365 /* Set *W to the minimum width, *H to the minimum font height of FONT.
7366 Note: There are (broken) X fonts out there with invalid XFontStruct
7367 min_bounds contents. For example, handa@etl.go.jp reports that
7368 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
7369 have font->min_bounds.width == 0. */
7372 x_font_min_bounds (font
, w
, h
)
7373 MacFontStruct
*font
;
7376 *h
= FONT_HEIGHT (font
);
7377 *w
= font
->min_bounds
.width
;
7381 /* Compute the smallest character width and smallest font height over
7382 all fonts available on frame F. Set the members smallest_char_width
7383 and smallest_font_height in F's x_display_info structure to
7384 the values computed. Value is non-zero if smallest_font_height or
7385 smallest_char_width become smaller than they were before. */
7388 x_compute_min_glyph_bounds (f
)
7392 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7393 MacFontStruct
*font
;
7394 int old_width
= dpyinfo
->smallest_char_width
;
7395 int old_height
= dpyinfo
->smallest_font_height
;
7397 dpyinfo
->smallest_font_height
= 100000;
7398 dpyinfo
->smallest_char_width
= 100000;
7400 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7401 if (dpyinfo
->font_table
[i
].name
)
7403 struct font_info
*fontp
= dpyinfo
->font_table
+ i
;
7406 font
= (MacFontStruct
*) fontp
->font
;
7407 xassert (font
!= (MacFontStruct
*) ~0);
7408 x_font_min_bounds (font
, &w
, &h
);
7410 dpyinfo
->smallest_font_height
= min (dpyinfo
->smallest_font_height
, h
);
7411 dpyinfo
->smallest_char_width
= min (dpyinfo
->smallest_char_width
, w
);
7414 xassert (dpyinfo
->smallest_char_width
> 0
7415 && dpyinfo
->smallest_font_height
> 0);
7417 return (dpyinfo
->n_fonts
== 1
7418 || dpyinfo
->smallest_char_width
< old_width
7419 || dpyinfo
->smallest_font_height
< old_height
);
7423 /* Determine whether given string is a fully-specified XLFD: all 14
7424 fields are present, none is '*'. */
7427 is_fully_specified_xlfd (char *p
)
7435 for (i
= 0; i
< 13; i
++)
7437 q
= strchr (p
+ 1, '-');
7440 if (q
- p
== 2 && *(p
+ 1) == '*')
7445 if (strchr (p
+ 1, '-') != NULL
)
7448 if (*(p
+ 1) == '*' && *(p
+ 2) == '\0')
7455 /* XLoadQueryFont creates and returns an internal representation for a
7456 font in a MacFontStruct struct. There is really no concept
7457 corresponding to "loading" a font on the Mac. But we check its
7458 existence and find the font number and all other information for it
7459 and store them in the returned MacFontStruct. */
7461 static MacFontStruct
*
7462 XLoadQueryFont (Display
*dpy
, char *fontname
)
7470 static ATSUFontID font_id
;
7471 ATSUStyle mac_style
= NULL
;
7474 #if TARGET_API_MAC_CARBON
7475 TextEncoding encoding
;
7480 MacFontStruct
*font
;
7481 XCharStruct
*space_bounds
= NULL
, *pcm
;
7483 if (is_fully_specified_xlfd (fontname
))
7487 Lisp_Object matched_fonts
;
7489 matched_fonts
= mac_do_list_fonts (fontname
, 1);
7490 if (NILP (matched_fonts
))
7492 name
= SDATA (XCAR (matched_fonts
));
7495 if (parse_x_font_name (name
, family
, &size
, &fontface
, charset
) == 0)
7499 if (strcmp (charset
, "iso10646-1") == 0) /* XXX */
7502 ATSUAttributeTag tags
[] = {kATSUFontTag
, kATSUSizeTag
,
7503 kATSUQDBoldfaceTag
, kATSUQDItalicTag
};
7504 ByteCount sizes
[] = {sizeof (ATSUFontID
), sizeof (Fixed
),
7505 sizeof (Boolean
), sizeof (Boolean
)};
7506 static Fixed size_fixed
;
7507 static Boolean bold_p
, italic_p
;
7508 ATSUAttributeValuePtr values
[] = {&font_id
, &size_fixed
,
7509 &bold_p
, &italic_p
};
7510 ATSUFontFeatureType types
[] = {kAllTypographicFeaturesType
};
7511 ATSUFontFeatureSelector selectors
[] = {kAllTypeFeaturesOffSelector
};
7512 Lisp_Object font_id_cons
;
7514 font_id_cons
= Fgethash (make_unibyte_string (family
, strlen (family
)),
7515 atsu_font_id_hash
, Qnil
);
7516 if (NILP (font_id_cons
))
7518 font_id
= cons_to_long (font_id_cons
);
7519 size_fixed
= Long2Fix (size
);
7520 bold_p
= (fontface
& bold
) != 0;
7521 italic_p
= (fontface
& italic
) != 0;
7522 err
= ATSUCreateStyle (&mac_style
);
7525 err
= ATSUSetFontFeatures (mac_style
, sizeof (types
) / sizeof (types
[0]),
7529 err
= ATSUSetAttributes (mac_style
, sizeof (tags
) / sizeof (tags
[0]),
7530 tags
, sizes
, values
);
7532 scriptcode
= kTextEncodingMacUnicode
;
7537 Lisp_Object tmp
= Fassoc (build_string (family
), fm_font_family_alist
);
7541 fontnum
= XINT (XCDR (tmp
));
7542 #if TARGET_API_MAC_CARBON
7543 if (FMGetFontFamilyTextEncoding (fontnum
, &encoding
) != noErr
)
7545 scriptcode
= GetTextEncodingBase (encoding
);
7547 scriptcode
= FontToScript (fontnum
);
7551 font
= (MacFontStruct
*) xmalloc (sizeof (struct MacFontStruct
));
7553 font
->mac_fontnum
= fontnum
;
7554 font
->mac_fontsize
= size
;
7555 font
->mac_fontface
= fontface
;
7556 font
->mac_scriptcode
= scriptcode
;
7558 font
->mac_style
= mac_style
;
7559 #if USE_CG_TEXT_DRAWING
7560 font
->cg_font
= NULL
;
7561 font
->cg_glyphs
= NULL
;
7565 /* Apple Japanese (SJIS) font is listed as both
7566 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
7567 (Roman script) in init_font_name_table (). The latter should be
7568 treated as a one-byte font. */
7569 if (scriptcode
== smJapanese
&& strcmp (charset
, "jisx0201.1976-0") == 0)
7570 font
->mac_scriptcode
= smRoman
;
7572 font
->full_name
= mac_to_x_fontname (family
, size
, fontface
, charset
);
7575 if (font
->mac_style
)
7580 font
->min_byte1
= 0;
7581 font
->max_byte1
= 0xff;
7582 font
->min_char_or_byte2
= 0;
7583 font
->max_char_or_byte2
= 0xff;
7585 font
->bounds
.rows
= xmalloc (sizeof (XCharStructRow
*) * 0x100);
7586 if (font
->bounds
.rows
== NULL
)
7588 mac_unload_font (&one_mac_display_info
, font
);
7591 bzero (font
->bounds
.rows
, sizeof (XCharStructRow
*) * 0x100);
7592 font
->bounds
.rows
[0] = xmalloc (sizeof (XCharStructRow
));
7593 if (font
->bounds
.rows
[0] == NULL
)
7595 mac_unload_font (&one_mac_display_info
, font
);
7598 bzero (font
->bounds
.rows
[0], sizeof (XCharStructRow
));
7600 #if USE_CG_TEXT_DRAWING
7602 FMFontFamily font_family
;
7604 ATSFontRef ats_font
;
7606 err
= FMGetFontFamilyInstanceFromFont (font_id
, &font_family
, &style
);
7608 err
= FMGetFontFromFontFamilyInstance (font_family
, fontface
,
7610 /* Use CG text drawing if italic/bold is not synthesized. */
7611 if (err
== noErr
&& style
== fontface
)
7613 ats_font
= FMGetATSFontRefFromFont (font_id
);
7614 font
->cg_font
= CGFontCreateWithPlatformFont (&ats_font
);
7619 font
->cg_glyphs
= xmalloc (sizeof (CGGlyph
) * 0x100);
7620 if (font
->cg_glyphs
)
7621 bzero (font
->cg_glyphs
, sizeof (CGGlyph
) * 0x100);
7623 space_bounds
= font
->bounds
.rows
[0]->per_char
+ 0x20;
7624 err
= mac_query_char_extents (font
->mac_style
, 0x20,
7625 &font
->ascent
, &font
->descent
,
7627 #if USE_CG_TEXT_DRAWING
7628 (font
->cg_glyphs
? font
->cg_glyphs
+ 0x20
7636 mac_unload_font (&one_mac_display_info
, font
);
7639 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], 0x20);
7641 pcm
= font
->bounds
.rows
[0]->per_char
;
7642 for (c
= 0x21; c
<= 0xff; c
++)
7645 /* Soft hyphen is not supported in ATSUI. */
7653 mac_query_char_extents (font
->mac_style
, c
, NULL
, NULL
, pcm
+ c
,
7654 #if USE_CG_TEXT_DRAWING
7655 (font
->cg_glyphs
? font
->cg_glyphs
+ c
7661 XCHARSTRUCTROW_SET_CHAR_VALID (font
->bounds
.rows
[0], c
);
7663 #if USE_CG_TEXT_DRAWING
7664 if (font
->cg_glyphs
&& font
->cg_glyphs
[c
] == 0)
7666 /* Don't use CG text drawing if font substitution occurs in
7667 ASCII or Latin-1 characters. */
7668 CGFontRelease (font
->cg_font
);
7669 font
->cg_font
= NULL
;
7670 xfree (font
->cg_glyphs
);
7671 font
->cg_glyphs
= NULL
;
7680 SInt16 old_fontnum
, old_fontsize
;
7682 FontInfo the_fontinfo
;
7683 int is_two_byte_font
;
7685 /* Save the current font number used. */
7687 #if TARGET_API_MAC_CARBON
7688 old_fontnum
= GetPortTextFont (port
);
7689 old_fontsize
= GetPortTextSize (port
);
7690 old_fontface
= GetPortTextFace (port
);
7692 old_fontnum
= port
->txFont
;
7693 old_fontsize
= port
->txSize
;
7694 old_fontface
= port
->txFace
;
7699 TextFace (fontface
);
7701 GetFontInfo (&the_fontinfo
);
7703 font
->ascent
= the_fontinfo
.ascent
;
7704 font
->descent
= the_fontinfo
.descent
;
7706 is_two_byte_font
= (font
->mac_scriptcode
== smJapanese
7707 || font
->mac_scriptcode
== smTradChinese
7708 || font
->mac_scriptcode
== smSimpChinese
7709 || font
->mac_scriptcode
== smKorean
);
7711 if (is_two_byte_font
)
7715 font
->min_byte1
= 0xa1;
7716 font
->max_byte1
= 0xfe;
7717 font
->min_char_or_byte2
= 0xa1;
7718 font
->max_char_or_byte2
= 0xfe;
7720 /* Use the width of an "ideographic space" of that font
7721 because the_fontinfo.widMax returns the wrong width for
7723 switch (font
->mac_scriptcode
)
7726 font
->min_byte1
= 0x81;
7727 font
->max_byte1
= 0xfc;
7728 font
->min_char_or_byte2
= 0x40;
7729 font
->max_char_or_byte2
= 0xfc;
7730 char_width
= StringWidth("\p\x81\x40");
7733 font
->min_char_or_byte2
= 0x40;
7734 char_width
= StringWidth("\p\xa1\x40");
7737 char_width
= StringWidth("\p\xa1\xa1");
7740 char_width
= StringWidth("\p\xa1\xa1");
7744 font
->bounds
.per_char
= NULL
;
7746 if (fontface
& italic
)
7747 font
->max_bounds
.rbearing
= char_width
+ 1;
7749 font
->max_bounds
.rbearing
= char_width
;
7750 font
->max_bounds
.lbearing
= 0;
7751 font
->max_bounds
.width
= char_width
;
7752 font
->max_bounds
.ascent
= the_fontinfo
.ascent
;
7753 font
->max_bounds
.descent
= the_fontinfo
.descent
;
7755 font
->min_bounds
= font
->max_bounds
;
7761 font
->min_byte1
= font
->max_byte1
= 0;
7762 font
->min_char_or_byte2
= 0x20;
7763 font
->max_char_or_byte2
= 0xff;
7765 font
->bounds
.per_char
=
7766 xmalloc (sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7767 if (font
->bounds
.per_char
== NULL
)
7769 mac_unload_font (&one_mac_display_info
, font
);
7772 bzero (font
->bounds
.per_char
,
7773 sizeof (XCharStruct
) * (0xff - 0x20 + 1));
7775 space_bounds
= font
->bounds
.per_char
;
7776 mac_query_char_extents (NULL
, 0x20, &font
->ascent
, &font
->descent
,
7777 space_bounds
, NULL
);
7779 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0xff; c
++, pcm
++)
7780 mac_query_char_extents (NULL
, c
, NULL
, NULL
, pcm
, NULL
);
7783 /* Restore previous font number, size and face. */
7784 TextFont (old_fontnum
);
7785 TextSize (old_fontsize
);
7786 TextFace (old_fontface
);
7793 font
->min_bounds
= font
->max_bounds
= *space_bounds
;
7794 for (c
= 0x21, pcm
= space_bounds
+ 1; c
<= 0x7f; c
++, pcm
++)
7797 font
->min_bounds
.lbearing
= min (font
->min_bounds
.lbearing
,
7799 font
->min_bounds
.rbearing
= min (font
->min_bounds
.rbearing
,
7801 font
->min_bounds
.width
= min (font
->min_bounds
.width
,
7803 font
->min_bounds
.ascent
= min (font
->min_bounds
.ascent
,
7806 font
->max_bounds
.lbearing
= max (font
->max_bounds
.lbearing
,
7808 font
->max_bounds
.rbearing
= max (font
->max_bounds
.rbearing
,
7810 font
->max_bounds
.width
= max (font
->max_bounds
.width
,
7812 font
->max_bounds
.ascent
= max (font
->max_bounds
.ascent
,
7817 font
->mac_style
== NULL
&&
7819 font
->max_bounds
.width
== font
->min_bounds
.width
7820 && font
->min_bounds
.lbearing
>= 0
7821 && font
->max_bounds
.rbearing
<= font
->max_bounds
.width
)
7823 /* Fixed width and no overhangs. */
7824 xfree (font
->bounds
.per_char
);
7825 font
->bounds
.per_char
= NULL
;
7829 #if !defined (MAC_OS8) || USE_ATSUI
7830 /* AppKit and WebKit do some adjustment to the heights of Courier,
7831 Helvetica, and Times. This only works on the environments where
7832 the XDrawImageString counterpart is never used. */
7833 if (strcmp (family
, "courier") == 0 || strcmp (family
, "helvetica") == 0
7834 || strcmp (family
, "times") == 0)
7835 font
->ascent
+= (font
->ascent
+ font
->descent
) * .15 + 0.5;
7843 mac_unload_font (dpyinfo
, font
)
7844 struct mac_display_info
*dpyinfo
;
7847 xfree (font
->full_name
);
7849 if (font
->mac_style
)
7853 for (i
= font
->min_byte1
; i
<= font
->max_byte1
; i
++)
7854 if (font
->bounds
.rows
[i
])
7855 xfree (font
->bounds
.rows
[i
]);
7856 xfree (font
->bounds
.rows
);
7857 ATSUDisposeStyle (font
->mac_style
);
7861 if (font
->bounds
.per_char
)
7862 xfree (font
->bounds
.per_char
);
7863 #if USE_CG_TEXT_DRAWING
7865 CGFontRelease (font
->cg_font
);
7866 if (font
->cg_glyphs
)
7867 xfree (font
->cg_glyphs
);
7873 /* Load font named FONTNAME of the size SIZE for frame F, and return a
7874 pointer to the structure font_info while allocating it dynamically.
7875 If SIZE is 0, load any size of font.
7876 If loading is failed, return NULL. */
7879 x_load_font (f
, fontname
, size
)
7881 register char *fontname
;
7884 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
7885 Lisp_Object font_names
;
7887 /* Get a list of all the fonts that match this name. Once we
7888 have a list of matching fonts, we compare them against the fonts
7889 we already have by comparing names. */
7890 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
7892 if (!NILP (font_names
))
7897 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
7898 for (tail
= font_names
; CONSP (tail
); tail
= XCDR (tail
))
7899 if (dpyinfo
->font_table
[i
].name
7900 && (!strcmp (dpyinfo
->font_table
[i
].name
,
7901 SDATA (XCAR (tail
)))
7902 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
7903 SDATA (XCAR (tail
)))))
7904 return (dpyinfo
->font_table
+ i
);
7909 /* Load the font and add it to the table. */
7912 struct MacFontStruct
*font
;
7913 struct font_info
*fontp
;
7914 unsigned long value
;
7917 fontname
= (char *) SDATA (XCAR (font_names
));
7920 font
= (MacFontStruct
*) XLoadQueryFont (FRAME_MAC_DISPLAY (f
), fontname
);
7925 /* Find a free slot in the font table. */
7926 for (i
= 0; i
< dpyinfo
->n_fonts
; ++i
)
7927 if (dpyinfo
->font_table
[i
].name
== NULL
)
7930 /* If no free slot found, maybe enlarge the font table. */
7931 if (i
== dpyinfo
->n_fonts
7932 && dpyinfo
->n_fonts
== dpyinfo
->font_table_size
)
7935 dpyinfo
->font_table_size
= max (16, 2 * dpyinfo
->font_table_size
);
7936 sz
= dpyinfo
->font_table_size
* sizeof *dpyinfo
->font_table
;
7938 = (struct font_info
*) xrealloc (dpyinfo
->font_table
, sz
);
7941 fontp
= dpyinfo
->font_table
+ i
;
7942 if (i
== dpyinfo
->n_fonts
)
7945 /* Now fill in the slots of *FONTP. */
7947 bzero (fontp
, sizeof (*fontp
));
7949 fontp
->font_idx
= i
;
7950 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
7951 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
7953 if (font
->min_bounds
.width
== font
->max_bounds
.width
)
7955 /* Fixed width font. */
7956 fontp
->average_width
= fontp
->space_width
= font
->min_bounds
.width
;
7963 char2b
.byte1
= 0x00, char2b
.byte2
= 0x20;
7964 pcm
= mac_per_char_metric (font
, &char2b
, 0);
7966 fontp
->space_width
= pcm
->width
;
7968 fontp
->space_width
= FONT_WIDTH (font
);
7972 int width
= pcm
->width
;
7973 for (char2b
.byte2
= 33; char2b
.byte2
<= 126; char2b
.byte2
++)
7974 if ((pcm
= mac_per_char_metric (font
, &char2b
, 0)) != NULL
)
7975 width
+= pcm
->width
;
7976 fontp
->average_width
= width
/ 95;
7979 fontp
->average_width
= FONT_WIDTH (font
);
7982 fontp
->full_name
= (char *) xmalloc (strlen (font
->full_name
) + 1);
7983 bcopy (font
->full_name
, fontp
->full_name
, strlen (font
->full_name
) + 1);
7985 fontp
->size
= font
->max_bounds
.width
;
7986 fontp
->height
= FONT_HEIGHT (font
);
7988 /* For some font, ascent and descent in max_bounds field is
7989 larger than the above value. */
7990 int max_height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
7991 if (max_height
> fontp
->height
)
7992 fontp
->height
= max_height
;
7995 /* The slot `encoding' specifies how to map a character
7996 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
7997 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
7998 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
7999 2:0xA020..0xFF7F). For the moment, we don't know which charset
8000 uses this font. So, we set information in fontp->encoding[1]
8001 which is never used by any charset. If mapping can't be
8002 decided, set FONT_ENCODING_NOT_DECIDED. */
8003 if (font
->mac_scriptcode
== smJapanese
)
8004 fontp
->encoding
[1] = 4;
8008 = (font
->max_byte1
== 0
8010 ? (font
->min_char_or_byte2
< 0x80
8011 ? (font
->max_char_or_byte2
< 0x80
8012 ? 0 /* 0x20..0x7F */
8013 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
8014 : 1) /* 0xA0..0xFF */
8016 : (font
->min_byte1
< 0x80
8017 ? (font
->max_byte1
< 0x80
8018 ? (font
->min_char_or_byte2
< 0x80
8019 ? (font
->max_char_or_byte2
< 0x80
8020 ? 0 /* 0x2020..0x7F7F */
8021 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
8022 : 3) /* 0x20A0..0x7FFF */
8023 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
8024 : (font
->min_char_or_byte2
< 0x80
8025 ? (font
->max_char_or_byte2
< 0x80
8026 ? 2 /* 0xA020..0xFF7F */
8027 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
8028 : 1))); /* 0xA0A0..0xFFFF */
8031 #if 0 /* MAC_TODO: fill these out with more reasonably values */
8032 fontp
->baseline_offset
8033 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
8034 ? (long) value
: 0);
8035 fontp
->relative_compose
8036 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
8037 ? (long) value
: 0);
8038 fontp
->default_ascent
8039 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
8040 ? (long) value
: 0);
8042 fontp
->baseline_offset
= 0;
8043 fontp
->relative_compose
= 0;
8044 fontp
->default_ascent
= 0;
8047 /* Set global flag fonts_changed_p to non-zero if the font loaded
8048 has a character with a smaller width than any other character
8049 before, or if the font loaded has a smaller height than any
8050 other font loaded before. If this happens, it will make a
8051 glyph matrix reallocation necessary. */
8052 fonts_changed_p
|= x_compute_min_glyph_bounds (f
);
8059 /* Return a pointer to struct font_info of a font named FONTNAME for
8060 frame F. If no such font is loaded, return NULL. */
8063 x_query_font (f
, fontname
)
8065 register char *fontname
;
8067 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8070 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
8071 if (dpyinfo
->font_table
[i
].name
8072 && (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
8073 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
)))
8074 return (dpyinfo
->font_table
+ i
);
8079 /* Find a CCL program for a font specified by FONTP, and set the member
8080 `encoder' of the structure. */
8083 x_find_ccl_program (fontp
)
8084 struct font_info
*fontp
;
8086 Lisp_Object list
, elt
;
8088 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCDR (list
))
8092 && STRINGP (XCAR (elt
))
8093 && (fast_c_string_match_ignore_case (XCAR (elt
), fontp
->name
)
8099 struct ccl_program
*ccl
8100 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
8102 if (setup_ccl_program (ccl
, XCDR (elt
)) < 0)
8105 fontp
->font_encoder
= ccl
;
8111 /* The Mac Event loop code */
8113 #if !TARGET_API_MAC_CARBON
8115 #include <Quickdraw.h>
8116 #include <Balloons.h>
8117 #include <Devices.h>
8119 #include <Gestalt.h>
8121 #include <Processes.h>
8123 #include <ToolUtils.h>
8124 #include <TextUtils.h>
8125 #include <Dialogs.h>
8128 #include <Resources.h>
8133 #endif /* ! TARGET_API_MAC_CARBON */
8138 #define WINDOW_RESOURCE 128
8139 #define TERM_WINDOW_RESOURCE 129
8141 #define DEFAULT_NUM_COLS 80
8143 #define MIN_DOC_SIZE 64
8144 #define MAX_DOC_SIZE 32767
8146 #define EXTRA_STACK_ALLOC (256 * 1024)
8148 #define ARGV_STRING_LIST_ID 129
8149 #define ABOUT_ALERT_ID 128
8150 #define RAM_TOO_LARGE_ALERT_ID 129
8152 /* Contains the string "reverse", which is a constant for mouse button emu.*/
8153 Lisp_Object Qreverse
;
8156 /* Modifier associated with the control key, or nil to ignore. */
8157 Lisp_Object Vmac_control_modifier
;
8159 /* Modifier associated with the option key, or nil to ignore. */
8160 Lisp_Object Vmac_option_modifier
;
8162 /* Modifier associated with the command key, or nil to ignore. */
8163 Lisp_Object Vmac_command_modifier
;
8165 /* Modifier associated with the function key, or nil to ignore. */
8166 Lisp_Object Vmac_function_modifier
;
8168 /* True if the option and command modifiers should be used to emulate
8169 a three button mouse */
8170 Lisp_Object Vmac_emulate_three_button_mouse
;
8172 #if USE_CARBON_EVENTS
8173 /* Non-zero if the mouse wheel button (i.e. button 4) should map to
8174 mouse-2, instead of mouse-3. */
8175 int mac_wheel_button_is_mouse_2
;
8177 /* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox
8178 for processing before Emacs sees it. */
8179 int mac_pass_command_to_system
;
8181 /* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox
8182 for processing before Emacs sees it. */
8183 int mac_pass_control_to_system
;
8186 /* Points to the variable `inev' in the function XTread_socket. It is
8187 used for passing an input event to the function back from
8188 Carbon/Apple event handlers. */
8189 static struct input_event
*read_socket_inev
= NULL
;
8191 Point saved_menu_event_location
;
8194 #if USE_CARBON_EVENTS
8195 static Lisp_Object Qhicommand
;
8197 extern int mac_ready_for_apple_events
;
8198 extern Lisp_Object Qundefined
;
8199 extern void init_apple_event_handler
P_ ((void));
8200 extern void mac_find_apple_event_spec
P_ ((AEEventClass
, AEEventID
,
8201 Lisp_Object
*, Lisp_Object
*,
8203 extern OSErr init_coercion_handler
P_ ((void));
8205 #if TARGET_API_MAC_CARBON
8207 static pascal OSErr
mac_do_track_drag (DragTrackingMessage
, WindowPtr
, void*, DragReference
);
8208 static pascal OSErr
mac_do_receive_drag (WindowPtr
, void*, DragReference
);
8209 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
8210 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
8213 #if USE_CARBON_EVENTS
8215 extern void init_service_handler ();
8216 static Lisp_Object Qservices
, Qpaste
, Qperform
;
8218 /* Window Event Handler */
8219 static pascal OSStatus
mac_handle_window_event (EventHandlerCallRef
,
8222 OSErr
install_window_handler (WindowPtr
);
8224 extern void init_emacs_passwd_dir ();
8225 extern int emacs_main (int, char **, char **);
8227 extern void initialize_applescript();
8228 extern void terminate_applescript();
8231 #if USE_CARBON_EVENTS
8232 mac_to_emacs_modifiers (UInt32 mods
)
8234 mac_to_emacs_modifiers (EventModifiers mods
)
8237 unsigned int result
= 0;
8238 if (mods
& shiftKey
)
8239 result
|= shift_modifier
;
8241 /* Deactivated to simplify configuration:
8242 if Vmac_option_modifier is non-NIL, we fully process the Option
8243 key. Otherwise, we only process it if an additional Ctrl or Command
8244 is pressed. That way the system may convert the character to a
8246 if ((mods & optionKey) &&
8247 (( !NILP(Vmac_option_modifier) ||
8248 ((mods & cmdKey) || (mods & controlKey))))) */
8250 if (!NILP (Vmac_option_modifier
) && (mods
& optionKey
)) {
8251 Lisp_Object val
= Fget(Vmac_option_modifier
, Qmodifier_value
);
8253 result
|= XUINT(val
);
8255 if (!NILP (Vmac_command_modifier
) && (mods
& cmdKey
)) {
8256 Lisp_Object val
= Fget(Vmac_command_modifier
, Qmodifier_value
);
8258 result
|= XUINT(val
);
8260 if (!NILP (Vmac_control_modifier
) && (mods
& controlKey
)) {
8261 Lisp_Object val
= Fget(Vmac_control_modifier
, Qmodifier_value
);
8263 result
|= XUINT(val
);
8267 if (!NILP (Vmac_function_modifier
) && (mods
& kEventKeyModifierFnMask
)) {
8268 Lisp_Object val
= Fget(Vmac_function_modifier
, Qmodifier_value
);
8270 result
|= XUINT(val
);
8278 mac_get_emulated_btn ( UInt32 modifiers
)
8281 if (!NILP (Vmac_emulate_three_button_mouse
)) {
8282 int cmdIs3
= !EQ (Vmac_emulate_three_button_mouse
, Qreverse
);
8283 if (modifiers
& cmdKey
)
8284 result
= cmdIs3
? 2 : 1;
8285 else if (modifiers
& optionKey
)
8286 result
= cmdIs3
? 1 : 2;
8291 #if USE_CARBON_EVENTS
8292 /* Obtains the event modifiers from the event ref and then calls
8293 mac_to_emacs_modifiers. */
8295 mac_event_to_emacs_modifiers (EventRef eventRef
)
8298 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8299 sizeof (UInt32
), NULL
, &mods
);
8300 if (!NILP (Vmac_emulate_three_button_mouse
) &&
8301 GetEventClass(eventRef
) == kEventClassMouse
)
8303 mods
&= ~(optionKey
| cmdKey
);
8305 return mac_to_emacs_modifiers (mods
);
8308 /* Given an event ref, return the code to use for the mouse button
8309 code in the emacs input_event. */
8311 mac_get_mouse_btn (EventRef ref
)
8313 EventMouseButton result
= kEventMouseButtonPrimary
;
8314 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
8315 sizeof (EventMouseButton
), NULL
, &result
);
8318 case kEventMouseButtonPrimary
:
8319 if (NILP (Vmac_emulate_three_button_mouse
))
8323 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
8324 sizeof (UInt32
), NULL
, &mods
);
8325 return mac_get_emulated_btn(mods
);
8327 case kEventMouseButtonSecondary
:
8328 return mac_wheel_button_is_mouse_2
? 2 : 1;
8329 case kEventMouseButtonTertiary
:
8330 case 4: /* 4 is the number for the mouse wheel button */
8331 return mac_wheel_button_is_mouse_2
? 1 : 2;
8337 /* Normally, ConvertEventRefToEventRecord will correctly handle all
8338 events. However the click of the mouse wheel is not converted to a
8339 mouseDown or mouseUp event. Likewise for dead key down events.
8340 This calls ConvertEventRef, but then checks to see if it is a mouse
8341 up/down, or a dead key down carbon event that has not been
8342 converted, and if so, converts it by hand (to be picked up in the
8343 XTread_socket loop). */
8344 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
8346 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
8351 switch (GetEventClass (eventRef
))
8353 case kEventClassMouse
:
8354 switch (GetEventKind (eventRef
))
8356 case kEventMouseDown
:
8357 eventRec
->what
= mouseDown
;
8362 eventRec
->what
= mouseUp
;
8371 case kEventClassKeyboard
:
8372 switch (GetEventKind (eventRef
))
8374 case kEventRawKeyDown
:
8376 unsigned char char_codes
;
8379 eventRec
->what
= keyDown
;
8380 GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
, typeChar
,
8381 NULL
, sizeof (char), NULL
, &char_codes
);
8382 GetEventParameter (eventRef
, kEventParamKeyCode
, typeUInt32
,
8383 NULL
, sizeof (UInt32
), NULL
, &key_code
);
8384 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
8400 /* Need where and when. */
8403 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
8404 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
8405 /* Use two step process because new event modifiers are 32-bit
8406 and old are 16-bit. Currently, only loss is NumLock & Fn. */
8407 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
8408 NULL
, sizeof (UInt32
), NULL
, &mods
);
8409 eventRec
->modifiers
= mods
;
8411 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
8422 Handle menubar_handle
;
8423 MenuHandle menu_handle
;
8425 menubar_handle
= GetNewMBar (128);
8426 if(menubar_handle
== NULL
)
8428 SetMenuBar (menubar_handle
);
8431 #if !TARGET_API_MAC_CARBON
8432 menu_handle
= GetMenuHandle (M_APPLE
);
8433 if(menu_handle
!= NULL
)
8434 AppendResMenu (menu_handle
,'DRVR');
8442 do_init_managers (void)
8444 #if !TARGET_API_MAC_CARBON
8445 InitGraf (&qd
.thePort
);
8447 FlushEvents (everyEvent
, 0);
8452 #endif /* !TARGET_API_MAC_CARBON */
8455 #if !TARGET_API_MAC_CARBON
8456 /* set up some extra stack space for use by emacs */
8457 SetApplLimit ((Ptr
) ((long) GetApplLimit () - EXTRA_STACK_ALLOC
));
8459 /* MaxApplZone must be called for AppleScript to execute more
8460 complicated scripts */
8463 #endif /* !TARGET_API_MAC_CARBON */
8467 do_check_ram_size (void)
8469 SInt32 physical_ram_size
, logical_ram_size
;
8471 if (Gestalt (gestaltPhysicalRAMSize
, &physical_ram_size
) != noErr
8472 || Gestalt (gestaltLogicalRAMSize
, &logical_ram_size
) != noErr
8473 || physical_ram_size
> (1 << VALBITS
)
8474 || logical_ram_size
> (1 << VALBITS
))
8476 StopAlert (RAM_TOO_LARGE_ALERT_ID
, NULL
);
8482 do_window_update (WindowPtr win
)
8484 struct frame
*f
= mac_window_to_frame (win
);
8488 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
8490 if (win
!= tip_window
)
8492 if (f
->async_visible
== 0)
8494 /* Update events may occur when a frame gets iconified. */
8496 f
->async_visible
= 1;
8497 f
->async_iconified
= 0;
8498 SET_FRAME_GARBAGED (f
);
8504 #if TARGET_API_MAC_CARBON
8505 RgnHandle region
= NewRgn ();
8507 GetPortVisibleRegion (GetWindowPort (win
), region
);
8508 GetRegionBounds (region
, &r
);
8509 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8510 UpdateControls (win
, region
);
8511 DisposeRgn (region
);
8513 r
= (*win
->visRgn
)->rgnBBox
;
8514 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
8515 UpdateControls (win
, win
->visRgn
);
8524 is_emacs_window (WindowPtr win
)
8526 Lisp_Object tail
, frame
;
8531 FOR_EACH_FRAME (tail
, frame
)
8532 if (FRAME_MAC_P (XFRAME (frame
)))
8533 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
8542 /* Window-activate events will do the job. */
8548 /* Window-deactivate events will do the job. */
8553 do_apple_menu (SInt16 menu_item
)
8555 #if !TARGET_API_MAC_CARBON
8557 SInt16 da_driver_refnum
;
8559 if (menu_item
== I_ABOUT
)
8560 NoteAlert (ABOUT_ALERT_ID
, NULL
);
8563 GetMenuItemText (GetMenuHandle (M_APPLE
), menu_item
, item_name
);
8564 da_driver_refnum
= OpenDeskAcc (item_name
);
8566 #endif /* !TARGET_API_MAC_CARBON */
8570 do_menu_choice (SInt32 menu_choice
)
8572 SInt16 menu_id
, menu_item
;
8574 menu_id
= HiWord (menu_choice
);
8575 menu_item
= LoWord (menu_choice
);
8583 do_apple_menu (menu_item
);
8588 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
8589 MenuHandle menu
= GetMenuHandle (menu_id
);
8594 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
8595 menubar_selection_callback (f
, refcon
);
8604 /* Handle drags in size box. Based on code contributed by Ben
8605 Mesander and IM - Window Manager A. */
8608 do_grow_window (WindowPtr w
, EventRecord
*e
)
8611 int rows
, columns
, width
, height
;
8612 struct frame
*f
= mac_window_to_frame (w
);
8613 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
8614 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
8615 #if TARGET_API_MAC_CARBON
8621 if (size_hints
->flags
& PMinSize
)
8623 min_width
= size_hints
->min_width
;
8624 min_height
= size_hints
->min_height
;
8626 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
8628 #if TARGET_API_MAC_CARBON
8629 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
8631 height
= new_rect
.bottom
- new_rect
.top
;
8632 width
= new_rect
.right
- new_rect
.left
;
8634 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
8635 /* see if it really changed size */
8638 height
= HiWord (grow_size
);
8639 width
= LoWord (grow_size
);
8642 if (width
!= FRAME_PIXEL_WIDTH (f
)
8643 || height
!= FRAME_PIXEL_HEIGHT (f
))
8645 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8646 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8648 x_set_window_size (f
, 0, columns
, rows
);
8653 /* Handle clicks in zoom box. Calculation of "standard state" based
8654 on code in IM - Window Manager A and code contributed by Ben
8655 Mesander. The standard state of an Emacs window is 80-characters
8656 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
8659 do_zoom_window (WindowPtr w
, int zoom_in_or_out
)
8662 Rect zoom_rect
, port_rect
;
8664 int w_title_height
, columns
, rows
, width
, height
;
8665 struct frame
*f
= mac_window_to_frame (w
);
8666 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
8668 #if TARGET_API_MAC_CARBON
8670 Point standard_size
;
8672 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8673 standard_size
.v
= dpyinfo
->height
;
8675 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
))
8676 zoom_in_or_out
= inZoomIn
;
8679 /* Adjust the standard size according to character boundaries. */
8681 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, zoom_rect
.right
- zoom_rect
.left
);
8682 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8683 standard_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
8684 standard_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8685 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
8686 if (IsWindowInStandardState (w
, &standard_size
, &zoom_rect
)
8687 && port_rect
.left
== zoom_rect
.left
8688 && port_rect
.top
== zoom_rect
.top
)
8689 zoom_in_or_out
= inZoomIn
;
8691 zoom_in_or_out
= inZoomOut
;
8694 ZoomWindowIdeal (w
, zoom_in_or_out
, &standard_size
);
8696 #else /* not TARGET_API_MAC_CARBON */
8697 GetPort (&save_port
);
8699 SetPortWindowPort (w
);
8701 /* Clear window to avoid flicker. */
8702 EraseRect (&(w
->portRect
));
8703 if (zoom_in_or_out
== inZoomOut
)
8705 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
8706 LocalToGlobal (&top_left
);
8708 /* calculate height of window's title bar */
8709 w_title_height
= top_left
.v
- 1
8710 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
8712 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
8713 zoom_rect
= qd
.screenBits
.bounds
;
8714 zoom_rect
.top
+= w_title_height
;
8715 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
8717 zoom_rect
.right
= zoom_rect
.left
8718 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
8720 /* Adjust the standard size according to character boundaries. */
8721 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
8723 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
8725 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
8729 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
8731 SetPort (save_port
);
8732 #endif /* not TARGET_API_MAC_CARBON */
8734 /* retrieve window size and update application values */
8735 #if TARGET_API_MAC_CARBON
8736 GetWindowPortBounds (w
, &port_rect
);
8738 port_rect
= w
->portRect
;
8740 height
= port_rect
.bottom
- port_rect
.top
;
8741 width
= port_rect
.right
- port_rect
.left
;
8743 if (width
!= FRAME_PIXEL_WIDTH (f
)
8744 || height
!= FRAME_PIXEL_HEIGHT (f
))
8746 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
8747 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
8749 change_frame_size (f
, rows
, columns
, 0, 1, 0);
8750 SET_FRAME_GARBAGED (f
);
8751 cancel_mouse_face (f
);
8753 FRAME_PIXEL_WIDTH (f
) = width
;
8754 FRAME_PIXEL_HEIGHT (f
) = height
;
8756 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
8760 mac_store_apple_event (class, id
, desc
)
8761 Lisp_Object
class, id
;
8765 struct input_event buf
;
8768 desc_copy
= xmalloc (sizeof (AEDesc
));
8769 if (desc_copy
== NULL
)
8772 err
= AEDuplicateDesc (desc
, desc_copy
);
8777 buf
.kind
= MAC_APPLE_EVENT
;
8780 buf
.code
= (int)desc_copy
;
8781 XSETFRAME (buf
.frame_or_window
,
8782 mac_focus_frame (&one_mac_display_info
));
8784 kbd_buffer_store_event (&buf
);
8791 mac_make_lispy_event_code (code
)
8794 AEDesc
*desc
= (AEDesc
*)code
;
8797 obj
= mac_aedesc_to_lisp (desc
);
8798 AEDisposeDesc (desc
);
8804 #if USE_CARBON_EVENTS
8805 static pascal OSStatus
8806 mac_handle_command_event (next_handler
, event
, data
)
8807 EventHandlerCallRef next_handler
;
8814 Lisp_Object class_key
, id_key
, binding
;
8816 result
= CallNextEventHandler (next_handler
, event
);
8817 if (result
!= eventNotHandledErr
)
8820 GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
, NULL
,
8821 sizeof (HICommand
), NULL
, &command
);
8823 if (command
.commandID
== 0)
8824 return eventNotHandledErr
;
8826 /* A HICommand event is mapped to an Apple event whose event class
8827 symbol is `hicommand' and event ID is its command ID. */
8828 class_key
= Qhicommand
;
8829 mac_find_apple_event_spec (0, command
.commandID
,
8830 &class_key
, &id_key
, &binding
);
8831 if (!NILP (binding
) && !EQ (binding
, Qundefined
))
8832 if (INTEGERP (binding
))
8833 return XINT (binding
);
8836 AppleEvent apple_event
;
8838 static EventParamName names
[] = {kEventParamDirectObject
,
8839 kEventParamKeyModifiers
};
8840 static EventParamType types
[] = {typeHICommand
,
8842 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
8846 err
= mac_store_apple_event (class_key
, id_key
, &apple_event
);
8847 AEDisposeDesc (&apple_event
);
8853 return eventNotHandledErr
;
8857 init_command_handler ()
8860 EventTypeSpec specs
[] = {{kEventClassCommand
, kEventCommandProcess
}};
8861 static EventHandlerUPP handle_command_eventUPP
= NULL
;
8863 if (handle_command_eventUPP
== NULL
)
8864 handle_command_eventUPP
= NewEventHandlerUPP (mac_handle_command_event
);
8865 return InstallApplicationEventHandler (handle_command_eventUPP
,
8866 GetEventTypeCount (specs
), specs
,
8870 static pascal OSStatus
8871 mac_handle_window_event (next_handler
, event
, data
)
8872 EventHandlerCallRef next_handler
;
8879 XSizeHints
*size_hints
;
8881 GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
8882 NULL
, sizeof (WindowPtr
), NULL
, &wp
);
8884 switch (GetEventKind (event
))
8886 case kEventWindowUpdate
:
8887 result
= CallNextEventHandler (next_handler
, event
);
8888 if (result
!= eventNotHandledErr
)
8891 do_window_update (wp
);
8894 case kEventWindowBoundsChanging
:
8895 result
= CallNextEventHandler (next_handler
, event
);
8896 if (result
!= eventNotHandledErr
)
8899 GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
8900 NULL
, sizeof (UInt32
), NULL
, &attributes
);
8901 size_hints
= FRAME_SIZE_HINTS (mac_window_to_frame (wp
));
8902 if ((attributes
& kWindowBoundsChangeUserResize
)
8903 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
8904 == (PResizeInc
| PBaseSize
| PMinSize
)))
8909 GetEventParameter (event
, kEventParamCurrentBounds
,
8911 NULL
, sizeof (Rect
), NULL
, &bounds
);
8912 width
= bounds
.right
- bounds
.left
;
8913 height
= bounds
.bottom
- bounds
.top
;
8915 if (width
< size_hints
->min_width
)
8916 width
= size_hints
->min_width
;
8918 width
= size_hints
->base_width
8919 + (int) ((width
- size_hints
->base_width
)
8920 / (float) size_hints
->width_inc
+ .5)
8921 * size_hints
->width_inc
;
8923 if (height
< size_hints
->min_height
)
8924 height
= size_hints
->min_height
;
8926 height
= size_hints
->base_height
8927 + (int) ((height
- size_hints
->base_height
)
8928 / (float) size_hints
->height_inc
+ .5)
8929 * size_hints
->height_inc
;
8931 bounds
.right
= bounds
.left
+ width
;
8932 bounds
.bottom
= bounds
.top
+ height
;
8933 SetEventParameter (event
, kEventParamCurrentBounds
,
8934 typeQDRectangle
, sizeof (Rect
), &bounds
);
8939 case kEventWindowShown
:
8940 case kEventWindowHidden
:
8941 case kEventWindowExpanded
:
8942 case kEventWindowCollapsed
:
8943 result
= CallNextEventHandler (next_handler
, event
);
8945 mac_handle_visibility_change (mac_window_to_frame (wp
));
8951 return eventNotHandledErr
;
8954 static pascal OSStatus
8955 mac_handle_mouse_event (next_handler
, event
, data
)
8956 EventHandlerCallRef next_handler
;
8962 switch (GetEventKind (event
))
8964 case kEventMouseWheelMoved
:
8968 EventMouseWheelAxis axis
;
8972 result
= CallNextEventHandler (next_handler
, event
);
8973 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
8976 GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
8977 NULL
, sizeof (WindowRef
), NULL
, &wp
);
8978 f
= mac_window_to_frame (wp
);
8979 if (f
!= mac_focus_frame (&one_mac_display_info
))
8982 GetEventParameter (event
, kEventParamMouseWheelAxis
,
8983 typeMouseWheelAxis
, NULL
,
8984 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
8985 if (axis
!= kEventMouseWheelAxisY
)
8988 GetEventParameter (event
, kEventParamMouseWheelDelta
, typeSInt32
,
8989 NULL
, sizeof (SInt32
), NULL
, &delta
);
8990 GetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
8991 NULL
, sizeof (Point
), NULL
, &point
);
8992 read_socket_inev
->kind
= WHEEL_EVENT
;
8993 read_socket_inev
->code
= 0;
8994 read_socket_inev
->modifiers
=
8995 (mac_event_to_emacs_modifiers (event
)
8996 | ((delta
< 0) ? down_modifier
: up_modifier
));
8997 SetPortWindowPort (wp
);
8998 GlobalToLocal (&point
);
8999 XSETINT (read_socket_inev
->x
, point
.h
);
9000 XSETINT (read_socket_inev
->y
, point
.v
);
9001 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
9011 return eventNotHandledErr
;
9016 mac_store_services_event (event
)
9020 AppleEvent apple_event
;
9023 switch (GetEventKind (event
))
9025 case kEventServicePaste
:
9027 err
= create_apple_event_from_event_ref (event
, 0, NULL
, NULL
,
9031 case kEventServicePerform
:
9033 static EventParamName names
[] = {kEventParamServiceMessageName
,
9034 kEventParamServiceUserData
};
9035 static EventParamType types
[] = {typeCFStringRef
,
9039 err
= create_apple_event_from_event_ref (event
, 2, names
, types
,
9050 err
= mac_store_apple_event (Qservices
, id_key
, &apple_event
);
9051 AEDisposeDesc (&apple_event
);
9056 #endif /* MAC_OSX */
9057 #endif /* USE_CARBON_EVENTS */
9061 install_window_handler (window
)
9065 #if USE_CARBON_EVENTS
9066 EventTypeSpec specs_window
[] =
9067 {{kEventClassWindow
, kEventWindowUpdate
},
9068 {kEventClassWindow
, kEventWindowBoundsChanging
},
9069 {kEventClassWindow
, kEventWindowShown
},
9070 {kEventClassWindow
, kEventWindowHidden
},
9071 {kEventClassWindow
, kEventWindowExpanded
},
9072 {kEventClassWindow
, kEventWindowCollapsed
}};
9073 EventTypeSpec specs_mouse
[] = {{kEventClassMouse
, kEventMouseWheelMoved
}};
9074 static EventHandlerUPP handle_window_eventUPP
= NULL
;
9075 static EventHandlerUPP handle_mouse_eventUPP
= NULL
;
9077 if (handle_window_eventUPP
== NULL
)
9078 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
9079 if (handle_mouse_eventUPP
== NULL
)
9080 handle_mouse_eventUPP
= NewEventHandlerUPP (mac_handle_mouse_event
);
9081 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
9082 GetEventTypeCount (specs_window
),
9083 specs_window
, NULL
, NULL
);
9085 err
= InstallWindowEventHandler (window
, handle_mouse_eventUPP
,
9086 GetEventTypeCount (specs_mouse
),
9087 specs_mouse
, NULL
, NULL
);
9089 #if TARGET_API_MAC_CARBON
9090 if (mac_do_track_dragUPP
== NULL
)
9091 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
9092 if (mac_do_receive_dragUPP
== NULL
)
9093 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
9096 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
9098 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
9104 remove_window_handler (window
)
9107 #if TARGET_API_MAC_CARBON
9108 if (mac_do_track_dragUPP
)
9109 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
9110 if (mac_do_receive_dragUPP
)
9111 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
9115 #if TARGET_API_MAC_CARBON
9117 mac_do_track_drag (DragTrackingMessage message
, WindowPtr window
,
9118 void *handlerRefCon
, DragReference theDrag
)
9120 static int can_accept
;
9123 ItemReference theItem
;
9124 FlavorFlags theFlags
;
9127 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9128 return dragNotAcceptedErr
;
9132 case kDragTrackingEnterHandler
:
9133 CountDragItems (theDrag
, &items
);
9135 for (index
= 1; index
<= items
; index
++)
9137 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9138 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9139 if (result
== noErr
)
9147 case kDragTrackingEnterWindow
:
9150 RgnHandle hilite_rgn
= NewRgn ();
9152 struct frame
*f
= mac_window_to_frame (window
);
9154 GetWindowPortBounds (window
, &r
);
9155 OffsetRect (&r
, -r
.left
, -r
.top
);
9156 RectRgn (hilite_rgn
, &r
);
9157 ShowDragHilite (theDrag
, hilite_rgn
, true);
9158 DisposeRgn (hilite_rgn
);
9159 SetThemeCursor (kThemeCopyArrowCursor
);
9163 case kDragTrackingInWindow
:
9166 case kDragTrackingLeaveWindow
:
9169 struct frame
*f
= mac_window_to_frame (window
);
9171 HideDragHilite (theDrag
);
9172 SetThemeCursor (kThemeArrowCursor
);
9176 case kDragTrackingLeaveHandler
:
9184 mac_do_receive_drag (WindowPtr window
, void *handlerRefCon
,
9185 DragReference theDrag
)
9189 FlavorFlags theFlags
;
9192 ItemReference theItem
;
9194 Size size
= sizeof (HFSFlavor
);
9195 Lisp_Object file_list
;
9197 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
9198 return dragNotAcceptedErr
;
9201 GetDragMouse (theDrag
, &mouse
, 0L);
9202 CountDragItems (theDrag
, &items
);
9203 for (index
= 1; index
<= items
; index
++)
9205 /* Only handle file references. */
9206 GetDragItemReferenceNumber (theDrag
, index
, &theItem
);
9207 result
= GetFlavorFlags (theDrag
, theItem
, flavorTypeHFS
, &theFlags
);
9208 if (result
== noErr
)
9213 err
= GetFlavorData (theDrag
, theItem
, flavorTypeHFS
,
9216 err
= AECoercePtr (typeFSS
, &data
.fileSpec
, sizeof (FSSpec
),
9217 TYPE_FILE_NAME
, &desc
);
9222 /* x-dnd functions expect undecoded filenames. */
9223 file
= make_uninit_string (AEGetDescDataSize (&desc
));
9224 err
= AEGetDescData (&desc
, SDATA (file
), SBYTES (file
));
9226 file_list
= Fcons (file
, file_list
);
9227 AEDisposeDesc (&desc
);
9231 /* If there are items in the list, construct an event and post it to
9232 the queue like an interrupt using kbd_buffer_store_event. */
9233 if (!NILP (file_list
))
9235 struct input_event event
;
9237 struct frame
*f
= mac_window_to_frame (window
);
9240 GlobalToLocal (&mouse
);
9241 GetDragModifiers (theDrag
, NULL
, NULL
, &modifiers
);
9243 event
.kind
= DRAG_N_DROP_EVENT
;
9245 event
.modifiers
= mac_to_emacs_modifiers (modifiers
);
9246 event
.timestamp
= TickCount () * (1000 / 60);
9247 XSETINT (event
.x
, mouse
.h
);
9248 XSETINT (event
.y
, mouse
.v
);
9249 XSETFRAME (frame
, f
);
9250 event
.frame_or_window
= frame
;
9251 event
.arg
= file_list
;
9252 /* Post to the interrupt queue */
9253 kbd_buffer_store_event (&event
);
9254 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
9256 ProcessSerialNumber psn
;
9257 GetCurrentProcess (&psn
);
9258 SetFrontProcess (&psn
);
9264 return dragNotAcceptedErr
;
9271 profiler_exit_proc ()
9273 ProfilerDump ("\pEmacs.prof");
9278 /* These few functions implement Emacs as a normal Mac application
9279 (almost): set up the heap and the Toolbox, handle necessary system
9280 events plus a few simple menu events. They also set up Emacs's
9281 access to functions defined in the rest of this file. Emacs uses
9282 function hooks to perform all its terminal I/O. A complete list of
9283 these functions appear in termhooks.h. For what they do, read the
9284 comments there and see also w32term.c and xterm.c. What's
9285 noticeably missing here is the event loop, which is normally
9286 present in most Mac application. After performing the necessary
9287 Mac initializations, main passes off control to emacs_main
9288 (corresponding to main in emacs.c). Emacs_main calls XTread_socket
9289 (defined further below) to read input. This is where
9290 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */
9297 #if __profile__ /* is the profiler on? */
9298 if (ProfilerInit(collectDetailed
, bestTimeBase
, 5000, 200))
9303 /* set creator and type for files created by MSL */
9308 do_init_managers ();
9313 do_check_ram_size ();
9316 init_emacs_passwd_dir ();
9320 init_coercion_handler ();
9322 initialize_applescript ();
9324 init_apple_event_handler ();
9330 /* set up argv array from STR# resource */
9331 get_string_list (&argv
, ARGV_STRING_LIST_ID
);
9335 /* free up AppleScript resources on exit */
9336 atexit (terminate_applescript
);
9338 #if __profile__ /* is the profiler on? */
9339 atexit (profiler_exit_proc
);
9342 /* 3rd param "envp" never used in emacs_main */
9343 (void) emacs_main (argc
, argv
, 0);
9346 /* Never reached - real exit in Fkill_emacs */
9351 /* Table for translating Mac keycode to X keysym values. Contributed
9353 Mapping for special keys is now identical to that in Apple X11
9354 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>)
9355 on the right of the Cmd key on laptops, and fn + `enter' (->
9357 static unsigned char keycode_to_xkeysym_table
[] = {
9358 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9359 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9360 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9362 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
9363 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0,
9364 /*0x38*/ 0, 0, 0, 0,
9365 /*0x3C*/ 0, 0, 0, 0,
9367 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
9368 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/,
9369 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
9370 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
9372 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
9373 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
9374 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
9375 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
9377 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
9378 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
9379 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
9380 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/,
9382 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/,
9383 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/,
9384 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
9385 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
9390 keycode_to_xkeysym (int keyCode
, int *xKeySym
)
9392 *xKeySym
= keycode_to_xkeysym_table
[keyCode
& 0x7f];
9393 return *xKeySym
!= 0;
9396 static unsigned char fn_keycode_to_xkeysym_table
[] = {
9397 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9398 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9399 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9401 /*0x30*/ 0, 0, 0, 0,
9402 /*0x34*/ 0, 0, 0, 0,
9403 /*0x38*/ 0, 0, 0, 0,
9404 /*0x3C*/ 0, 0, 0, 0,
9406 /*0x40*/ 0, 0x2e /*kp-. = .*/, 0, 0x50 /*kp-* = 'p'*/,
9407 /*0x44*/ 0, '/' /*kp-+*/, 0, 0,
9408 /*0x48*/ 0, 0, 0, 0x30 /*kp-/ = '0'*/,
9409 /*0x4C*/ 0, 0, 0x3b /*kp-- = ';'*/, 0,
9411 /*0x50*/ 0, 0x2d /*kp-= = '-'*/, 0x6d /*kp-0 = 'm'*/, 0x6a /*kp-1 = 'j'*/,
9412 /*0x54*/ 0x6b /*kp-2 = 'k'*/, 0x6c /*kp-3 = 'l'*/, 'u' /*kp-4*/, 'i' /*kp-5*/,
9413 /*0x58*/ 'o' /*kp-6*/, '7' /*kp-7*/, 0, '8' /*kp-8*/,
9414 /*0x5C*/ '9' /*kp-9*/, 0, 0, 0,
9416 /*0x60*/ 0, 0, 0, 0,
9417 /*0x64*/ 0, 0, 0, 0,
9418 /*0x68*/ 0, 0, 0, 0,
9419 /*0x6C*/ 0, 0, 0, 0,
9421 /*0x70*/ 0, 0, 0, 0,
9422 /*0x74*/ 0, 0, 0, 0,
9423 /*0x78*/ 0, 0, 0, 0,
9427 convert_fn_keycode (EventRef eventRef
, int keyCode
, int *newCode
)
9430 /* Use the special map to translate keys when function modifier is
9431 to be caught. KeyTranslate can't be used in that case.
9432 We can't detect the function key using the input_event.modifiers,
9433 because this uses the high word of an UInt32. Therefore,
9434 we'll just read it out of the original eventRef.
9438 /* TODO / known issues
9440 - Fn-Shift-j is regonized as Fn-j and not Fn-J.
9441 The above table always translates to lower characters. We need to use
9442 the KCHR keyboard resource (KeyTranslate() ) to map k->K and 8->*.
9444 - The table is meant for English language keyboards, and it will work
9445 for many others with the exception of key combinations like Fn-ö on
9446 a German keyboard, which is currently mapped to Fn-;.
9447 How to solve this without keeping separate tables for all keyboards
9448 around? KeyTranslate isn't of much help here, as it only takes a 16-bit
9449 value for keycode with the modifiers in he high byte, i.e. no room for the
9450 Fn modifier. That's why we need the table.
9455 if (!NILP(Vmac_function_modifier
))
9457 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
9458 sizeof (UInt32
), NULL
, &mods
);
9459 if (mods
& kEventKeyModifierFnMask
)
9460 { *newCode
= fn_keycode_to_xkeysym_table
[keyCode
& 0x7f];
9462 return (*newCode
!= 0);
9470 backtranslate_modified_keycode(int mods
, int keycode
, int def
)
9472 EventModifiers mapped_modifiers
=
9473 (NILP (Vmac_control_modifier
) ? 0 : controlKey
)
9474 | (NILP (Vmac_option_modifier
) ? 0 : optionKey
)
9475 | (NILP (Vmac_command_modifier
) ? 0 : cmdKey
);
9477 if (mods
& mapped_modifiers
)
9479 /* This code comes from Keyboard Resource,
9480 Appendix C of IM - Text. This is necessary
9481 since shift is ignored in KCHR table
9482 translation when option or command is pressed.
9483 It also does not translate correctly
9484 control-shift chars like C-% so mask off shift
9487 Not done for combinations with the option key (alt)
9488 unless it is to be caught by Emacs: this is
9489 to preserve key combinations translated by the OS
9492 /* Mask off modifier keys that are mapped to some Emacs
9494 int new_modifiers
= mods
& ~mapped_modifiers
;
9495 /* set high byte of keycode to modifier high byte*/
9496 int new_keycode
= keycode
| new_modifiers
;
9497 Ptr kchr_ptr
= (Ptr
) GetScriptManagerVariable (smKCHRCache
);
9498 unsigned long some_state
= 0;
9499 return (int) KeyTranslate (kchr_ptr
, new_keycode
,
9500 &some_state
) & 0xff;
9501 /* TO DO: Recognize two separate resulting characters, "for
9502 example, when the user presses Option-E followed by N, you
9503 can map this through the KeyTranslate function using the
9504 U.S. 'KCHR' resource to produce ´n, which KeyTranslate
9505 returns as two characters in the bytes labeled Character code
9506 1 and Character code 2." (from Carbon API doc) */
9514 #if !USE_CARBON_EVENTS
9515 static RgnHandle mouse_region
= NULL
;
9518 mac_wait_next_event (er
, sleep_time
, dequeue
)
9523 static EventRecord er_buf
= {nullEvent
};
9524 UInt32 target_tick
, current_tick
;
9525 EventMask event_mask
;
9527 if (mouse_region
== NULL
)
9528 mouse_region
= NewRgn ();
9530 event_mask
= everyEvent
;
9531 if (!mac_ready_for_apple_events
)
9532 event_mask
-= highLevelEventMask
;
9534 current_tick
= TickCount ();
9535 target_tick
= current_tick
+ sleep_time
;
9537 if (er_buf
.what
== nullEvent
)
9538 while (!WaitNextEvent (event_mask
, &er_buf
,
9539 target_tick
- current_tick
, mouse_region
))
9541 current_tick
= TickCount ();
9542 if (target_tick
<= current_tick
)
9548 er_buf
.what
= nullEvent
;
9551 #endif /* not USE_CARBON_EVENTS */
9553 /* Emacs calls this whenever it wants to read an input event from the
9556 XTread_socket (sd
, expected
, hold_quit
)
9558 struct input_event
*hold_quit
;
9560 struct input_event inev
;
9562 #if USE_CARBON_EVENTS
9564 EventTargetRef toolbox_dispatcher
;
9567 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
9569 if (interrupt_input_blocked
)
9571 interrupt_input_pending
= 1;
9575 interrupt_input_pending
= 0;
9578 /* So people can tell when we have read the available input. */
9579 input_signal_count
++;
9581 #if USE_CARBON_EVENTS
9582 toolbox_dispatcher
= GetEventDispatcherTarget ();
9584 while (!ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
9585 kEventRemoveFromQueue
, &eventRef
))
9586 #else /* !USE_CARBON_EVENTS */
9587 while (mac_wait_next_event (&er
, 0, true))
9588 #endif /* !USE_CARBON_EVENTS */
9592 unsigned long timestamp
;
9594 /* It is necessary to set this (additional) argument slot of an
9595 event to nil because keyboard.c protects incompletely
9596 processed event from being garbage collected by placing them
9597 in the kbd_buffer_gcpro vector. */
9599 inev
.kind
= NO_EVENT
;
9602 #if USE_CARBON_EVENTS
9603 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
9605 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
9608 #if USE_CARBON_EVENTS
9609 /* Handle new events */
9610 if (!mac_convert_event_ref (eventRef
, &er
))
9612 /* There used to be a handler for the kEventMouseWheelMoved
9613 event here. But as of Mac OS X 10.4, this kind of event
9614 is not directly posted to the main event queue by
9615 two-finger scrolling on the trackpad. Instead, some
9616 private event is posted and it is converted to a wheel
9617 event by the default handler for the application target.
9618 The converted one can be received by a Carbon event
9619 handler installed on a window target. */
9620 read_socket_inev
= &inev
;
9621 SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
9622 read_socket_inev
= NULL
;
9625 #endif /* USE_CARBON_EVENTS */
9631 WindowPtr window_ptr
;
9632 ControlPartCode part_code
;
9635 #if USE_CARBON_EVENTS
9636 /* This is needed to send mouse events like aqua window
9637 buttons to the correct handler. */
9638 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9639 != eventNotHandledErr
)
9642 last_mouse_glyph_frame
= 0;
9644 if (dpyinfo
->grabbed
&& last_mouse_frame
9645 && FRAME_LIVE_P (last_mouse_frame
))
9647 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
9648 part_code
= inContent
;
9652 part_code
= FindWindow (er
.where
, &window_ptr
);
9653 if (tip_window
&& window_ptr
== tip_window
)
9655 HideWindow (tip_window
);
9656 part_code
= FindWindow (er
.where
, &window_ptr
);
9660 if (er
.what
!= mouseDown
&&
9661 (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
9667 f
= mac_focus_frame (dpyinfo
);
9668 saved_menu_event_location
= er
.where
;
9669 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
9670 XSETFRAME (inev
.frame_or_window
, f
);
9674 if (window_ptr
!= FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo
)))
9675 SelectWindow (window_ptr
);
9678 ControlPartCode control_part_code
;
9680 Point mouse_loc
= er
.where
;
9682 ControlKind control_kind
;
9685 f
= mac_window_to_frame (window_ptr
);
9686 /* convert to local coordinates of new window */
9687 SetPortWindowPort (window_ptr
);
9689 GlobalToLocal (&mouse_loc
);
9690 #if TARGET_API_MAC_CARBON
9691 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
9692 &control_part_code
);
9695 GetControlKind (ch
, &control_kind
);
9698 control_part_code
= FindControl (mouse_loc
, window_ptr
,
9702 #if USE_CARBON_EVENTS
9703 inev
.code
= mac_get_mouse_btn (eventRef
);
9704 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
9706 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
9707 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
9709 XSETINT (inev
.x
, mouse_loc
.h
);
9710 XSETINT (inev
.y
, mouse_loc
.v
);
9712 if (dpyinfo
->grabbed
&& tracked_scroll_bar
9714 #ifndef USE_TOOLKIT_SCROLL_BARS
9715 /* control_part_code becomes kControlNoPart if
9716 a progress indicator is clicked. */
9717 && control_part_code
!= kControlNoPart
9718 #else /* USE_TOOLKIT_SCROLL_BARS */
9720 && control_kind
.kind
== kControlKindScrollBar
9721 #endif /* MAC_OSX */
9722 #endif /* USE_TOOLKIT_SCROLL_BARS */
9725 struct scroll_bar
*bar
;
9727 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9729 bar
= tracked_scroll_bar
;
9730 #ifndef USE_TOOLKIT_SCROLL_BARS
9731 control_part_code
= kControlIndicatorPart
;
9735 bar
= (struct scroll_bar
*) GetControlReference (ch
);
9736 #ifdef USE_TOOLKIT_SCROLL_BARS
9737 /* Make the "Ctrl-Mouse-2 splits window" work
9738 for toolkit scroll bars. */
9739 if (er
.modifiers
& controlKey
)
9740 x_scroll_bar_handle_click (bar
, control_part_code
,
9742 else if (er
.what
== mouseDown
)
9743 x_scroll_bar_handle_press (bar
, control_part_code
,
9746 x_scroll_bar_handle_release (bar
, &inev
);
9747 #else /* not USE_TOOLKIT_SCROLL_BARS */
9748 x_scroll_bar_handle_click (bar
, control_part_code
,
9750 if (er
.what
== mouseDown
9751 && control_part_code
== kControlIndicatorPart
)
9752 tracked_scroll_bar
= bar
;
9754 tracked_scroll_bar
= NULL
;
9755 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9760 int x
= mouse_loc
.h
;
9761 int y
= mouse_loc
.v
;
9763 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
9764 if (EQ (window
, f
->tool_bar_window
))
9766 if (er
.what
== mouseDown
)
9767 handle_tool_bar_click (f
, x
, y
, 1, 0);
9769 handle_tool_bar_click (f
, x
, y
, 0,
9775 XSETFRAME (inev
.frame_or_window
, f
);
9776 inev
.kind
= MOUSE_CLICK_EVENT
;
9780 if (er
.what
== mouseDown
)
9782 dpyinfo
->grabbed
|= (1 << inev
.code
);
9783 last_mouse_frame
= f
;
9786 last_tool_bar_item
= -1;
9790 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
9791 /* If a button is released though it was not
9792 previously pressed, that would be because
9793 of multi-button emulation. */
9794 dpyinfo
->grabbed
= 0;
9796 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
9799 /* Ignore any mouse motion that happened before
9800 this event; any subsequent mouse-movement Emacs
9801 events should reflect only motion after the
9806 #ifdef USE_TOOLKIT_SCROLL_BARS
9807 if (inev
.kind
== MOUSE_CLICK_EVENT
)
9812 inev
.modifiers
|= down_modifier
;
9815 inev
.modifiers
|= up_modifier
;
9822 #if TARGET_API_MAC_CARBON
9823 DragWindow (window_ptr
, er
.where
, NULL
);
9824 #else /* not TARGET_API_MAC_CARBON */
9825 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
9826 #endif /* not TARGET_API_MAC_CARBON */
9827 /* Update the frame parameters. */
9829 struct frame
*f
= mac_window_to_frame (window_ptr
);
9831 if (f
&& !f
->async_iconified
)
9832 x_real_positions (f
, &f
->left_pos
, &f
->top_pos
);
9837 if (TrackGoAway (window_ptr
, er
.where
))
9839 inev
.kind
= DELETE_WINDOW_EVENT
;
9840 XSETFRAME (inev
.frame_or_window
,
9841 mac_window_to_frame (window_ptr
));
9845 /* window resize handling added --ben */
9847 do_grow_window (window_ptr
, &er
);
9850 /* window zoom handling added --ben */
9853 if (TrackBox (window_ptr
, er
.where
, part_code
))
9854 do_zoom_window (window_ptr
, part_code
);
9864 #if USE_CARBON_EVENTS
9865 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9866 != eventNotHandledErr
)
9869 do_window_update ((WindowPtr
) er
.message
);
9874 #if USE_CARBON_EVENTS
9875 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9876 != eventNotHandledErr
)
9879 switch ((er
.message
>> 24) & 0x000000FF)
9881 case suspendResumeMessage
:
9882 if ((er
.message
& resumeFlag
) == 1)
9888 case mouseMovedMessage
:
9889 #if !USE_CARBON_EVENTS
9890 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
9891 er
.where
.h
+ 1, er
.where
.v
+ 1);
9893 previous_help_echo_string
= help_echo_string
;
9894 help_echo_string
= Qnil
;
9896 if (dpyinfo
->grabbed
&& last_mouse_frame
9897 && FRAME_LIVE_P (last_mouse_frame
))
9898 f
= last_mouse_frame
;
9900 f
= dpyinfo
->x_focus_frame
;
9902 if (dpyinfo
->mouse_face_hidden
)
9904 dpyinfo
->mouse_face_hidden
= 0;
9905 clear_mouse_face (dpyinfo
);
9910 WindowPtr wp
= FRAME_MAC_WINDOW (f
);
9911 Point mouse_pos
= er
.where
;
9913 SetPortWindowPort (wp
);
9915 GlobalToLocal (&mouse_pos
);
9917 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
9918 #ifdef USE_TOOLKIT_SCROLL_BARS
9919 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
9921 #else /* not USE_TOOLKIT_SCROLL_BARS */
9922 x_scroll_bar_note_movement (tracked_scroll_bar
,
9924 - XINT (tracked_scroll_bar
->top
),
9925 er
.when
* (1000 / 60));
9926 #endif /* not USE_TOOLKIT_SCROLL_BARS */
9929 /* Generate SELECT_WINDOW_EVENTs when needed. */
9930 if (mouse_autoselect_window
)
9934 window
= window_from_coordinates (f
,
9939 /* Window will be selected only when it is
9940 not selected now and last mouse movement
9941 event was not in it. Minibuffer window
9942 will be selected iff it is active. */
9943 if (WINDOWP (window
)
9944 && !EQ (window
, last_window
)
9945 && !EQ (window
, selected_window
))
9947 inev
.kind
= SELECT_WINDOW_EVENT
;
9948 inev
.frame_or_window
= window
;
9953 if (!note_mouse_movement (f
, &mouse_pos
))
9954 help_echo_string
= previous_help_echo_string
;
9958 /* If the contents of the global variable
9959 help_echo_string has changed, generate a
9961 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
9969 WindowPtr window_ptr
= (WindowPtr
) er
.message
;
9971 #if USE_CARBON_EVENTS
9972 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
9973 != eventNotHandledErr
)
9976 if (window_ptr
== tip_window
)
9978 HideWindow (tip_window
);
9982 if (!is_emacs_window (window_ptr
))
9985 if ((er
.modifiers
& activeFlag
) != 0)
9987 /* A window has been activated */
9988 Point mouse_loc
= er
.where
;
9990 x_detect_focus_change (dpyinfo
, &er
, &inev
);
9992 SetPortWindowPort (window_ptr
);
9993 GlobalToLocal (&mouse_loc
);
9994 /* Window-activated event counts as mouse movement,
9995 so update things that depend on mouse position. */
9996 note_mouse_movement (mac_window_to_frame (window_ptr
),
10001 /* A window has been deactivated */
10002 #if USE_TOOLKIT_SCROLL_BARS
10003 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
10005 struct input_event event
;
10007 EVENT_INIT (event
);
10008 event
.kind
= NO_EVENT
;
10009 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
10010 if (event
.kind
!= NO_EVENT
)
10012 event
.timestamp
= timestamp
;
10013 kbd_buffer_store_event_hold (&event
, hold_quit
);
10018 dpyinfo
->grabbed
= 0;
10020 x_detect_focus_change (dpyinfo
, &er
, &inev
);
10022 f
= mac_window_to_frame (window_ptr
);
10023 if (f
== dpyinfo
->mouse_face_mouse_frame
)
10025 /* If we move outside the frame, then we're
10026 certainly no longer on any text in the
10028 clear_mouse_face (dpyinfo
);
10029 dpyinfo
->mouse_face_mouse_frame
= 0;
10032 /* Generate a nil HELP_EVENT to cancel a help-echo.
10033 Do it only if there's something to cancel.
10034 Otherwise, the startup message is cleared when the
10035 mouse leaves the frame. */
10036 if (any_help_event_p
)
10045 int keycode
= (er
.message
& keyCodeMask
) >> 8;
10048 #if USE_CARBON_EVENTS && defined (MAC_OSX)
10049 /* When using Carbon Events, we need to pass raw keyboard
10050 events to the TSM ourselves. If TSM handles it, it
10051 will pass back noErr, otherwise it will pass back
10052 "eventNotHandledErr" and we can process it
10054 if ((mac_pass_command_to_system
10055 || !(er
.modifiers
& cmdKey
))
10056 && (mac_pass_control_to_system
10057 || !(er
.modifiers
& controlKey
))
10058 && (NILP (Vmac_option_modifier
)
10059 || !(er
.modifiers
& optionKey
)))
10060 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
10061 != eventNotHandledErr
)
10066 if (dpyinfo
->x_focus_frame
== NULL
)
10068 /* Beep if keyboard input occurs when all the frames
10076 static SInt16 last_key_script
= -1;
10077 SInt16 current_key_script
= GetScriptManagerVariable (smKeyScript
);
10079 if (last_key_script
!= current_key_script
)
10081 struct input_event event
;
10083 EVENT_INIT (event
);
10084 event
.kind
= LANGUAGE_CHANGE_EVENT
;
10086 event
.code
= current_key_script
;
10087 event
.timestamp
= timestamp
;
10088 kbd_buffer_store_event (&event
);
10091 last_key_script
= current_key_script
;
10096 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
))
10098 clear_mouse_face (dpyinfo
);
10099 dpyinfo
->mouse_face_hidden
= 1;
10102 /* translate the keycode back to determine the original key */
10103 /* Convert key code if function key is pressed.
10104 Otherwise, if non-ASCII-event, take care of that
10105 without re-translating the key code. */
10106 #if USE_CARBON_EVENTS
10107 if (convert_fn_keycode (eventRef
, keycode
, &xkeysym
))
10109 inev
.code
= xkeysym
;
10110 /* this doesn't work - tried to add shift modifiers */
10112 backtranslate_modified_keycode(er
.modifiers
& (~0x2200),
10113 xkeysym
| 0x80, xkeysym
);
10114 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10118 if (keycode_to_xkeysym (keycode
, &xkeysym
))
10120 inev
.code
= 0xff00 | xkeysym
;
10121 inev
.kind
= NON_ASCII_KEYSTROKE_EVENT
;
10126 backtranslate_modified_keycode(er
.modifiers
, keycode
,
10127 er
.message
& charCodeMask
);
10128 inev
.kind
= ASCII_KEYSTROKE_EVENT
;
10132 #if USE_CARBON_EVENTS
10133 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
10135 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
);
10137 inev
.modifiers
|= (extra_keyboard_modifiers
10138 & (meta_modifier
| alt_modifier
10139 | hyper_modifier
| super_modifier
));
10140 XSETFRAME (inev
.frame_or_window
, mac_focus_frame (dpyinfo
));
10143 case kHighLevelEvent
:
10144 read_socket_inev
= &inev
;
10145 AEProcessAppleEvent (&er
);
10146 read_socket_inev
= NULL
;
10152 #if USE_CARBON_EVENTS
10153 ReleaseEvent (eventRef
);
10156 if (inev
.kind
!= NO_EVENT
)
10158 inev
.timestamp
= timestamp
;
10159 kbd_buffer_store_event_hold (&inev
, hold_quit
);
10164 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
10169 XSETFRAME (frame
, f
);
10175 any_help_event_p
= 1;
10176 gen_help_event (help_echo_string
, frame
, help_echo_window
,
10177 help_echo_object
, help_echo_pos
);
10181 help_echo_string
= Qnil
;
10182 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
10189 /* If the focus was just given to an autoraising frame,
10191 /* ??? This ought to be able to handle more than one such frame. */
10192 if (pending_autoraise_frame
)
10194 x_raise_frame (pending_autoraise_frame
);
10195 pending_autoraise_frame
= 0;
10198 #if !USE_CARBON_EVENTS
10199 /* Check which frames are still visible. We do this here because
10200 there doesn't seem to be any direct notification from the Window
10201 Manager that the visibility of a window has changed (at least,
10202 not in all cases). */
10204 Lisp_Object tail
, frame
;
10206 FOR_EACH_FRAME (tail
, frame
)
10208 struct frame
*f
= XFRAME (frame
);
10210 /* The tooltip has been drawn already. Avoid the
10211 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
10212 if (EQ (frame
, tip_frame
))
10215 if (FRAME_MAC_P (f
))
10216 mac_handle_visibility_change (f
);
10226 /* Need to override CodeWarrior's input function so no conversion is
10227 done on newlines Otherwise compiled functions in .elc files will be
10228 read incorrectly. Defined in ...:MSL C:MSL
10229 Common:Source:buffer_io.c. */
10232 __convert_to_newlines (unsigned char * p
, size_t * n
)
10234 #pragma unused(p,n)
10238 __convert_from_newlines (unsigned char * p
, size_t * n
)
10240 #pragma unused(p,n)
10246 make_mac_terminal_frame (struct frame
*f
)
10251 XSETFRAME (frame
, f
);
10253 f
->output_method
= output_mac
;
10254 f
->output_data
.mac
= (struct mac_output
*)
10255 xmalloc (sizeof (struct mac_output
));
10256 bzero (f
->output_data
.mac
, sizeof (struct mac_output
));
10258 XSETFRAME (FRAME_KBOARD (f
)->Vdefault_minibuffer_frame
, f
);
10260 FRAME_COLS (f
) = 96;
10261 FRAME_LINES (f
) = 4;
10263 FRAME_CAN_HAVE_SCROLL_BARS (f
) = 1;
10264 FRAME_VERTICAL_SCROLL_BAR_TYPE (f
) = vertical_scroll_bar_right
;
10266 FRAME_DESIRED_CURSOR (f
) = FILLED_BOX_CURSOR
;
10268 f
->output_data
.mac
->cursor_pixel
= 0;
10269 f
->output_data
.mac
->border_pixel
= 0x00ff00;
10270 f
->output_data
.mac
->mouse_pixel
= 0xff00ff;
10271 f
->output_data
.mac
->cursor_foreground_pixel
= 0x0000ff;
10273 f
->output_data
.mac
->text_cursor
= kThemeIBeamCursor
;
10274 f
->output_data
.mac
->nontext_cursor
= kThemeArrowCursor
;
10275 f
->output_data
.mac
->modeline_cursor
= kThemeArrowCursor
;
10276 f
->output_data
.mac
->hand_cursor
= kThemePointingHandCursor
;
10277 f
->output_data
.mac
->hourglass_cursor
= kThemeWatchCursor
;
10278 f
->output_data
.mac
->horizontal_drag_cursor
= kThemeResizeLeftRightCursor
;
10280 FRAME_FONTSET (f
) = -1;
10281 f
->output_data
.mac
->explicit_parent
= 0;
10284 f
->border_width
= 0;
10286 f
->internal_border_width
= 0;
10291 f
->new_text_cols
= 0;
10292 f
->new_text_lines
= 0;
10294 SetRect (&r
, f
->left_pos
, f
->top_pos
,
10295 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
10296 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
10300 if (!(FRAME_MAC_WINDOW (f
) =
10301 NewCWindow (NULL
, &r
, "\p", true, dBoxProc
,
10302 (WindowPtr
) -1, 1, (long) f
->output_data
.mac
)))
10304 /* so that update events can find this mac_output struct */
10305 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
10311 /* Need to be initialized for unshow_buffer in window.c. */
10312 selected_window
= f
->selected_window
;
10314 Fmodify_frame_parameters (frame
,
10315 Fcons (Fcons (Qfont
,
10316 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil
));
10317 Fmodify_frame_parameters (frame
,
10318 Fcons (Fcons (Qforeground_color
,
10319 build_string ("black")), Qnil
));
10320 Fmodify_frame_parameters (frame
,
10321 Fcons (Fcons (Qbackground_color
,
10322 build_string ("white")), Qnil
));
10327 /***********************************************************************
10329 ***********************************************************************/
10331 int mac_initialized
= 0;
10334 mac_initialize_display_info ()
10336 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
10337 GDHandle main_device_handle
;
10339 bzero (dpyinfo
, sizeof (*dpyinfo
));
10342 dpyinfo
->mac_id_name
10343 = (char *) xmalloc (SCHARS (Vinvocation_name
)
10344 + SCHARS (Vsystem_name
)
10346 sprintf (dpyinfo
->mac_id_name
, "%s@%s",
10347 SDATA (Vinvocation_name
), SDATA (Vsystem_name
));
10349 dpyinfo
->mac_id_name
= (char *) xmalloc (strlen ("Mac Display") + 1);
10350 strcpy (dpyinfo
->mac_id_name
, "Mac Display");
10353 main_device_handle
= LMGetMainDevice();
10355 dpyinfo
->reference_count
= 0;
10356 dpyinfo
->resx
= 72.0;
10357 dpyinfo
->resy
= 72.0;
10358 dpyinfo
->color_p
= TestDeviceAttribute (main_device_handle
, gdDevType
);
10360 /* HasDepth returns true if it is possible to have a 32 bit display,
10361 but this may not be what is actually used. Mac OSX can do better.
10362 CGMainDisplayID is only available on OSX 10.2 and higher, but the
10363 header for CGGetActiveDisplayList says that the first display returned
10364 is the active one, so we use that. */
10366 CGDirectDisplayID disp_id
[1];
10367 CGDisplayCount disp_count
;
10368 CGDisplayErr error_code
;
10370 error_code
= CGGetActiveDisplayList (1, disp_id
, &disp_count
);
10371 if (error_code
!= 0)
10372 error ("No display found, CGGetActiveDisplayList error %d", error_code
);
10374 dpyinfo
->n_planes
= CGDisplayBitsPerPixel (disp_id
[0]);
10377 for (dpyinfo
->n_planes
= 32; dpyinfo
->n_planes
> 0; dpyinfo
->n_planes
>>= 1)
10378 if (HasDepth (main_device_handle
, dpyinfo
->n_planes
,
10379 gdDevType
, dpyinfo
->color_p
))
10382 dpyinfo
->height
= (**main_device_handle
).gdRect
.bottom
;
10383 dpyinfo
->width
= (**main_device_handle
).gdRect
.right
;
10384 dpyinfo
->grabbed
= 0;
10385 dpyinfo
->root_window
= NULL
;
10386 dpyinfo
->image_cache
= make_image_cache ();
10388 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
10389 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
10390 dpyinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
10391 dpyinfo
->mouse_face_window
= Qnil
;
10392 dpyinfo
->mouse_face_overlay
= Qnil
;
10393 dpyinfo
->mouse_face_hidden
= 0;
10398 mac_make_rdb (xrm_option
)
10401 XrmDatabase database
;
10403 database
= xrm_get_preference_database (NULL
);
10405 xrm_merge_string_database (database
, xrm_option
);
10410 struct mac_display_info
*
10411 mac_term_init (display_name
, xrm_option
, resource_name
)
10412 Lisp_Object display_name
;
10414 char *resource_name
;
10416 struct mac_display_info
*dpyinfo
;
10420 if (!mac_initialized
)
10423 mac_initialized
= 1;
10426 if (x_display_list
)
10427 error ("Sorry, this version can only handle one display");
10429 mac_initialize_display_info ();
10431 dpyinfo
= &one_mac_display_info
;
10433 dpyinfo
->xrdb
= mac_make_rdb (xrm_option
);
10435 /* Put this display on the chain. */
10436 dpyinfo
->next
= x_display_list
;
10437 x_display_list
= dpyinfo
;
10439 /* Put it on x_display_name_list. */
10440 x_display_name_list
= Fcons (Fcons (display_name
,
10441 Fcons (Qnil
, dpyinfo
->xrdb
)),
10442 x_display_name_list
);
10443 dpyinfo
->name_list_element
= XCAR (x_display_name_list
);
10449 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10452 x_delete_display (dpyinfo
)
10453 struct mac_display_info
*dpyinfo
;
10457 /* Discard this display from x_display_name_list and x_display_list.
10458 We can't use Fdelq because that can quit. */
10459 if (! NILP (x_display_name_list
)
10460 && EQ (XCAR (x_display_name_list
), dpyinfo
->name_list_element
))
10461 x_display_name_list
= XCDR (x_display_name_list
);
10466 tail
= x_display_name_list
;
10467 while (CONSP (tail
) && CONSP (XCDR (tail
)))
10469 if (EQ (XCAR (XCDR (tail
)), dpyinfo
->name_list_element
))
10471 XSETCDR (tail
, XCDR (XCDR (tail
)));
10474 tail
= XCDR (tail
);
10478 if (x_display_list
== dpyinfo
)
10479 x_display_list
= dpyinfo
->next
;
10482 struct x_display_info
*tail
;
10484 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
10485 if (tail
->next
== dpyinfo
)
10486 tail
->next
= tail
->next
->next
;
10489 /* Free the font names in the font table. */
10490 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
10491 if (dpyinfo
->font_table
[i
].name
)
10493 if (dpyinfo
->font_table
[i
].name
!= dpyinfo
->font_table
[i
].full_name
)
10494 xfree (dpyinfo
->font_table
[i
].full_name
);
10495 xfree (dpyinfo
->font_table
[i
].name
);
10498 if (dpyinfo
->font_table
->font_encoder
)
10499 xfree (dpyinfo
->font_table
->font_encoder
);
10501 xfree (dpyinfo
->font_table
);
10502 xfree (dpyinfo
->mac_id_name
);
10504 if (x_display_list
== 0)
10506 mac_clear_font_name_table ();
10507 bzero (dpyinfo
, sizeof (*dpyinfo
));
10516 extern int inhibit_window_system
;
10517 extern int noninteractive
;
10518 CFBundleRef appsBundle
;
10521 /* No need to test if already -nw*/
10522 if (inhibit_window_system
|| noninteractive
)
10525 appsBundle
= CFBundleGetMainBundle();
10526 if (appsBundle
!= NULL
)
10528 CFStringRef cfBI
= CFSTR("CFBundleIdentifier");
10529 CFTypeRef res
= CFBundleGetValueForInfoDictionaryKey(appsBundle
, cfBI
);
10530 /* We found the bundle identifier, now we know we are valid. */
10537 /* MAC_TODO: Have this start the bundled executable */
10539 /* For now, prevent the fatal error by bringing it up in the terminal */
10540 inhibit_window_system
= 1;
10544 MakeMeTheFrontProcess ()
10546 ProcessSerialNumber psn
;
10549 err
= GetCurrentProcess (&psn
);
10551 (void) SetFrontProcess (&psn
);
10554 /***** Code to handle C-g testing *****/
10556 /* Contains the Mac modifier formed from quit_char */
10557 int mac_quit_char_modifiers
= 0;
10558 int mac_quit_char_keycode
;
10559 extern int quit_char
;
10562 mac_determine_quit_char_modifiers()
10564 /* Todo: Determine modifiers from quit_char. */
10565 UInt32 qc_modifiers
= ctrl_modifier
;
10567 /* Map modifiers */
10568 mac_quit_char_modifiers
= 0;
10569 if (qc_modifiers
& ctrl_modifier
) mac_quit_char_modifiers
|= controlKey
;
10570 if (qc_modifiers
& shift_modifier
) mac_quit_char_modifiers
|= shiftKey
;
10571 if (qc_modifiers
& alt_modifier
) mac_quit_char_modifiers
|= optionKey
;
10575 init_quit_char_handler ()
10577 /* TODO: Let this support keys other the 'g' */
10578 mac_quit_char_keycode
= 5;
10579 /* Look at <architecture/adb_kb_map.h> for details */
10580 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
10582 mac_determine_quit_char_modifiers();
10584 #endif /* MAC_OSX */
10592 MenuItemIndex menu_index
;
10594 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
10595 &menu
, &menu_index
);
10597 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10598 #if USE_CARBON_EVENTS
10599 EnableMenuCommand (NULL
, kHICommandPreferences
);
10600 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
10601 &menu
, &menu_index
);
10604 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
10605 InsertMenuItemTextWithCFString (menu
, NULL
,
10606 0, kMenuItemAttrSeparator
, 0);
10607 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
10608 0, 0, kHICommandAbout
);
10610 #endif /* USE_CARBON_EVENTS */
10611 #else /* !MAC_OSX */
10612 #if USE_CARBON_EVENTS
10613 SetMenuItemCommandID (GetMenuHandle (M_APPLE
), I_ABOUT
, kHICommandAbout
);
10619 /* Set up use of X before we make the first connection. */
10621 extern frame_parm_handler mac_frame_parm_handlers
[];
10623 static struct redisplay_interface x_redisplay_interface
=
10625 mac_frame_parm_handlers
,
10629 x_clear_end_of_line
,
10631 x_after_update_window_line
,
10632 x_update_window_begin
,
10633 x_update_window_end
,
10636 0, /* flush_display_optional */
10637 x_clear_window_mouse_face
,
10638 x_get_glyph_overhangs
,
10639 x_fix_overlapping_area
,
10640 x_draw_fringe_bitmap
,
10641 0, /* define_fringe_bitmap */
10642 0, /* destroy_fringe_bitmap */
10643 mac_per_char_metric
,
10645 mac_compute_glyph_string_overhangs
,
10646 x_draw_glyph_string
,
10647 mac_define_frame_cursor
,
10648 mac_clear_frame_area
,
10649 mac_draw_window_cursor
,
10650 mac_draw_vertical_window_border
,
10651 mac_shift_glyphs_for_insert
10657 rif
= &x_redisplay_interface
;
10659 clear_frame_hook
= x_clear_frame
;
10660 ins_del_lines_hook
= x_ins_del_lines
;
10661 delete_glyphs_hook
= x_delete_glyphs
;
10662 ring_bell_hook
= XTring_bell
;
10663 reset_terminal_modes_hook
= XTreset_terminal_modes
;
10664 set_terminal_modes_hook
= XTset_terminal_modes
;
10665 update_begin_hook
= x_update_begin
;
10666 update_end_hook
= x_update_end
;
10667 set_terminal_window_hook
= XTset_terminal_window
;
10668 read_socket_hook
= XTread_socket
;
10669 frame_up_to_date_hook
= XTframe_up_to_date
;
10670 mouse_position_hook
= XTmouse_position
;
10671 frame_rehighlight_hook
= XTframe_rehighlight
;
10672 frame_raise_lower_hook
= XTframe_raise_lower
;
10674 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
10675 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
10676 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
10677 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
10679 scroll_region_ok
= 1; /* we'll scroll partial frames */
10680 char_ins_del_ok
= 1;
10681 line_ins_del_ok
= 1; /* we'll just blt 'em */
10682 fast_clear_end_of_line
= 1; /* X does this well */
10683 memory_below_frame
= 0; /* we don't remember what scrolls
10687 last_tool_bar_item
= -1;
10688 any_help_event_p
= 0;
10690 /* Try to use interrupt input; if we can't, then start polling. */
10691 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
10695 #if TARGET_API_MAC_CARBON
10697 #if USE_CARBON_EVENTS
10699 init_service_handler ();
10701 init_quit_char_handler ();
10702 #endif /* MAC_OSX */
10704 init_command_handler ();
10707 #endif /* USE_CARBON_EVENTS */
10710 init_coercion_handler ();
10712 init_apple_event_handler ();
10714 if (!inhibit_window_system
)
10715 MakeMeTheFrontProcess ();
10726 staticpro (&x_error_message_string
);
10727 x_error_message_string
= Qnil
;
10730 Qcontrol
= intern ("control"); staticpro (&Qcontrol
);
10731 Qmeta
= intern ("meta"); staticpro (&Qmeta
);
10732 Qalt
= intern ("alt"); staticpro (&Qalt
);
10733 Qhyper
= intern ("hyper"); staticpro (&Qhyper
);
10734 Qsuper
= intern ("super"); staticpro (&Qsuper
);
10735 Qmodifier_value
= intern ("modifier-value");
10736 staticpro (&Qmodifier_value
);
10738 Fput (Qcontrol
, Qmodifier_value
, make_number (ctrl_modifier
));
10739 Fput (Qmeta
, Qmodifier_value
, make_number (meta_modifier
));
10740 Fput (Qalt
, Qmodifier_value
, make_number (alt_modifier
));
10741 Fput (Qhyper
, Qmodifier_value
, make_number (hyper_modifier
));
10742 Fput (Qsuper
, Qmodifier_value
, make_number (super_modifier
));
10744 #if USE_CARBON_EVENTS
10745 Qhicommand
= intern ("hicommand"); staticpro (&Qhicommand
);
10747 Qservices
= intern ("services"); staticpro (&Qservices
);
10748 Qpaste
= intern ("paste"); staticpro (&Qpaste
);
10749 Qperform
= intern ("perform"); staticpro (&Qperform
);
10754 Fprovide (intern ("mac-carbon"), Qnil
);
10757 staticpro (&Qreverse
);
10758 Qreverse
= intern ("reverse");
10760 staticpro (&x_display_name_list
);
10761 x_display_name_list
= Qnil
;
10763 staticpro (&last_mouse_scroll_bar
);
10764 last_mouse_scroll_bar
= Qnil
;
10766 staticpro (&fm_font_family_alist
);
10767 fm_font_family_alist
= Qnil
;
10770 staticpro (&atsu_font_id_hash
);
10771 atsu_font_id_hash
= Qnil
;
10774 /* We don't yet support this, but defining this here avoids whining
10775 from cus-start.el and other places, like "M-x set-variable". */
10776 DEFVAR_BOOL ("x-use-underline-position-properties",
10777 &x_use_underline_position_properties
,
10778 doc
: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
10779 nil means ignore them. If you encounter fonts with bogus
10780 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
10781 to 4.1, set this to nil.
10783 NOTE: Not supported on Mac yet. */);
10784 x_use_underline_position_properties
= 0;
10786 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars
,
10787 doc
: /* If not nil, Emacs uses toolkit scroll bars. */);
10788 #ifdef USE_TOOLKIT_SCROLL_BARS
10789 Vx_toolkit_scroll_bars
= Qt
;
10791 Vx_toolkit_scroll_bars
= Qnil
;
10794 staticpro (&last_mouse_motion_frame
);
10795 last_mouse_motion_frame
= Qnil
;
10797 /* Variables to configure modifier key assignment. */
10799 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier
,
10800 doc
: /* *Modifier key assumed when the Mac control key is pressed.
10801 The value can be `control', `meta', `alt', `hyper', or `super' for the
10802 respective modifier. The default is `control'. */);
10803 Vmac_control_modifier
= Qcontrol
;
10805 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier
,
10806 doc
: /* *Modifier key assumed when the Mac alt/option key is pressed.
10807 The value can be `control', `meta', `alt', `hyper', or `super' for the
10808 respective modifier. If the value is nil then the key will act as the
10809 normal Mac control modifier, and the option key can be used to compose
10810 characters depending on the chosen Mac keyboard setting. */);
10811 Vmac_option_modifier
= Qnil
;
10813 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier
,
10814 doc
: /* *Modifier key assumed when the Mac command key is pressed.
10815 The value can be `control', `meta', `alt', `hyper', or `super' for the
10816 respective modifier. The default is `meta'. */);
10817 Vmac_command_modifier
= Qmeta
;
10819 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier
,
10820 doc
: /* *Modifier key assumed when the Mac function key is pressed.
10821 The value can be `control', `meta', `alt', `hyper', or `super' for the
10822 respective modifier. Note that remapping the function key may lead to
10823 unexpected results for some keys on non-US/GB keyboards. */);
10824 Vmac_function_modifier
= Qnil
;
10826 DEFVAR_LISP ("mac-emulate-three-button-mouse",
10827 &Vmac_emulate_three_button_mouse
,
10828 doc
: /* *Specify a way of three button mouse emulation.
10829 The value can be nil, t, or the symbol `reverse'.
10830 nil means that no emulation should be done and the modifiers should be
10831 placed on the mouse-1 event.
10832 t means that when the option-key is held down while pressing the mouse
10833 button, the click will register as mouse-2 and while the command-key
10834 is held down, the click will register as mouse-3.
10835 The symbol `reverse' means that the option-key will register for
10836 mouse-3 and the command-key will register for mouse-2. */);
10837 Vmac_emulate_three_button_mouse
= Qnil
;
10839 #if USE_CARBON_EVENTS
10840 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2
,
10841 doc
: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3.
10842 Otherwise, the right click will be treated as mouse-2 and the wheel
10843 button will be mouse-3. */);
10844 mac_wheel_button_is_mouse_2
= 1;
10846 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system
,
10847 doc
: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */);
10848 mac_pass_command_to_system
= 1;
10850 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system
,
10851 doc
: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */);
10852 mac_pass_control_to_system
= 1;
10856 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics
,
10857 doc
: /* *If non-nil, allow anti-aliasing.
10858 The text will be rendered using Core Graphics text rendering which
10859 may anti-alias the text. */);
10860 mac_use_core_graphics
= 0;
10862 /* Register an entry for `mac-roman' so that it can be used when
10863 creating the terminal frame on Mac OS 9 before loading
10864 term/mac-win.elc. */
10865 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist
,
10866 doc
: /* Alist of Emacs character sets vs text encodings and coding systems.
10867 Each entry should be of the form:
10869 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM)
10871 where CHARSET-NAME is a string used in font names to identify the
10872 charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and
10873 CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */);
10874 Vmac_charset_info_alist
=
10875 Fcons (list3 (build_string ("mac-roman"),
10876 make_number (smRoman
), Qnil
), Qnil
);
10879 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
10880 (do not change this comment) */